1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portlet.journal.service.impl;
24  
25  import com.liferay.portal.PortalException;
26  import com.liferay.portal.SystemException;
27  import com.liferay.portal.kernel.util.CharPool;
28  import com.liferay.portal.kernel.util.OrderByComparator;
29  import com.liferay.portal.kernel.util.StringPool;
30  import com.liferay.portal.kernel.util.StringUtil;
31  import com.liferay.portal.kernel.util.Validator;
32  import com.liferay.portal.model.ResourceConstants;
33  import com.liferay.portal.model.User;
34  import com.liferay.portal.util.PortalUtil;
35  import com.liferay.portlet.journal.DuplicateStructureIdException;
36  import com.liferay.portlet.journal.NoSuchStructureException;
37  import com.liferay.portlet.journal.RequiredStructureException;
38  import com.liferay.portlet.journal.StructureDescriptionException;
39  import com.liferay.portlet.journal.StructureIdException;
40  import com.liferay.portlet.journal.StructureNameException;
41  import com.liferay.portlet.journal.StructureXsdException;
42  import com.liferay.portlet.journal.model.JournalStructure;
43  import com.liferay.portlet.journal.model.impl.JournalStructureImpl;
44  import com.liferay.portlet.journal.service.base.JournalStructureLocalServiceBaseImpl;
45  import com.liferay.portlet.journal.util.JournalUtil;
46  
47  import java.io.IOException;
48  import java.io.StringReader;
49  
50  import java.util.Date;
51  import java.util.HashSet;
52  import java.util.List;
53  import java.util.Set;
54  
55  import org.apache.commons.logging.Log;
56  import org.apache.commons.logging.LogFactory;
57  
58  import org.dom4j.Document;
59  import org.dom4j.DocumentException;
60  import org.dom4j.Element;
61  import org.dom4j.io.SAXReader;
62  
63  /**
64   * <a href="JournalStructureLocalServiceImpl.java.html"><b><i>View Source</i>
65   * </b></a>
66   *
67   * @author Brian Wing Shun Chan
68   *
69   */
70  public class JournalStructureLocalServiceImpl
71      extends JournalStructureLocalServiceBaseImpl {
72  
73      public JournalStructure addStructure(
74              long userId, String structureId, boolean autoStructureId, long plid,
75              String name, String description, String xsd,
76              boolean addCommunityPermissions, boolean addGuestPermissions)
77          throws PortalException, SystemException {
78  
79          return addStructure(
80              null, userId, structureId, autoStructureId, plid, name, description,
81              xsd, Boolean.valueOf(addCommunityPermissions),
82              Boolean.valueOf(addGuestPermissions), null, null);
83      }
84  
85      public JournalStructure addStructure(
86              String uuid, long userId, String structureId,
87              boolean autoStructureId, long plid, String name, String description,
88              String xsd, boolean addCommunityPermissions,
89              boolean addGuestPermissions)
90          throws PortalException, SystemException {
91  
92          return addStructure(
93              uuid, userId, structureId, autoStructureId, plid, name, description,
94              xsd, Boolean.valueOf(addCommunityPermissions),
95              Boolean.valueOf(addGuestPermissions), null, null);
96      }
97  
98      public JournalStructure addStructure(
99              long userId, String structureId, boolean autoStructureId, long plid,
100             String name, String description, String xsd,
101             String[] communityPermissions, String[] guestPermissions)
102         throws PortalException, SystemException {
103 
104         return addStructure(
105             null, userId, structureId, autoStructureId, plid, name, description,
106             xsd, null, null, communityPermissions, guestPermissions);
107     }
108 
109     public JournalStructure addStructure(
110             String uuid, long userId, String structureId,
111             boolean autoStructureId, long plid, String name,
112             String description, String xsd, Boolean addCommunityPermissions,
113             Boolean addGuestPermissions, String[] communityPermissions,
114             String[] guestPermissions)
115         throws PortalException, SystemException {
116 
117         long groupId = PortalUtil.getPortletGroupId(plid);
118 
119         return addStructureToGroup(
120             uuid, userId, structureId, autoStructureId, groupId, name,
121             description, xsd, addCommunityPermissions, addGuestPermissions,
122             communityPermissions, guestPermissions);
123     }
124 
125     public JournalStructure addStructureToGroup(
126             String uuid, long userId, String structureId,
127             boolean autoStructureId, long groupId, String name,
128             String description, String xsd, Boolean addCommunityPermissions,
129             Boolean addGuestPermissions, String[] communityPermissions,
130             String[] guestPermissions)
131         throws PortalException, SystemException {
132 
133         // Structure
134 
135         User user = userPersistence.findByPrimaryKey(userId);
136         structureId = structureId.trim().toUpperCase();
137         Date now = new Date();
138 
139         try {
140             xsd = JournalUtil.formatXML(xsd);
141         }
142         catch (DocumentException de) {
143             throw new StructureXsdException();
144         }
145         catch (IOException ioe) {
146             throw new StructureXsdException();
147         }
148 
149         validate(
150             groupId, structureId, autoStructureId, name, description, xsd);
151 
152         if (autoStructureId) {
153             structureId = String.valueOf(counterLocalService.increment());
154         }
155 
156         long id = counterLocalService.increment();
157 
158         JournalStructure structure = journalStructurePersistence.create(id);
159 
160         structure.setUuid(uuid);
161         structure.setGroupId(groupId);
162         structure.setCompanyId(user.getCompanyId());
163         structure.setUserId(user.getUserId());
164         structure.setUserName(user.getFullName());
165         structure.setCreateDate(now);
166         structure.setModifiedDate(now);
167         structure.setStructureId(structureId);
168         structure.setName(name);
169         structure.setDescription(description);
170         structure.setXsd(xsd);
171 
172         journalStructurePersistence.update(structure, false);
173 
174         // Resources
175 
176         if ((addCommunityPermissions != null) &&
177             (addGuestPermissions != null)) {
178 
179             addStructureResources(
180                 structure, addCommunityPermissions.booleanValue(),
181                 addGuestPermissions.booleanValue());
182         }
183         else {
184             addStructureResources(
185                 structure, communityPermissions, guestPermissions);
186         }
187 
188         return structure;
189     }
190 
191     public void addStructureResources(
192             long groupId, String structureId, boolean addCommunityPermissions,
193             boolean addGuestPermissions)
194         throws PortalException, SystemException {
195 
196         JournalStructure structure = journalStructurePersistence.findByG_S(
197             groupId, structureId);
198 
199         addStructureResources(
200             structure, addCommunityPermissions, addGuestPermissions);
201     }
202 
203     public void addStructureResources(
204             JournalStructure structure, boolean addCommunityPermissions,
205             boolean addGuestPermissions)
206         throws PortalException, SystemException {
207 
208         resourceLocalService.addResources(
209             structure.getCompanyId(), structure.getGroupId(),
210             structure.getUserId(), JournalStructure.class.getName(),
211             structure.getId(), false, addCommunityPermissions,
212             addGuestPermissions);
213     }
214 
215     public void addStructureResources(
216             long groupId, String structureId, String[] communityPermissions,
217             String[] guestPermissions)
218         throws PortalException, SystemException {
219 
220         JournalStructure structure = journalStructurePersistence.findByG_S(
221             groupId, structureId);
222 
223         addStructureResources(
224             structure, communityPermissions, guestPermissions);
225     }
226 
227     public void addStructureResources(
228             JournalStructure structure, String[] communityPermissions,
229             String[] guestPermissions)
230         throws PortalException, SystemException {
231 
232         resourceLocalService.addModelResources(
233             structure.getCompanyId(), structure.getGroupId(),
234             structure.getUserId(), JournalStructure.class.getName(),
235             structure.getId(), communityPermissions, guestPermissions);
236     }
237 
238     public void checkNewLine(long groupId, String structureId)
239         throws PortalException, SystemException {
240 
241         JournalStructure structure = journalStructurePersistence.findByG_S(
242             groupId, structureId);
243 
244         String xsd = structure.getXsd();
245 
246         if ((xsd != null) && (xsd.indexOf("\\n") != -1)) {
247             xsd = StringUtil.replace(
248                 xsd,
249                 new String[] {"\\n", "\\r"},
250                 new String[] {"\n", "\r"});
251 
252             structure.setXsd(xsd);
253 
254             journalStructurePersistence.update(structure, false);
255         }
256     }
257 
258     public JournalStructure copyStructure(
259             long userId, long groupId, String oldStructureId,
260             String newStructureId, boolean autoStructureId)
261         throws PortalException, SystemException {
262 
263         // Structure
264 
265         User user = userPersistence.findByPrimaryKey(userId);
266         oldStructureId = oldStructureId.trim().toUpperCase();
267         newStructureId = newStructureId.trim().toUpperCase();
268         Date now = new Date();
269 
270         JournalStructure oldStructure = journalStructurePersistence.findByG_S(
271             groupId, oldStructureId);
272 
273         if (autoStructureId) {
274             newStructureId = String.valueOf(counterLocalService.increment());
275         }
276         else {
277             validate(newStructureId);
278 
279             JournalStructure newStructure =
280                 journalStructurePersistence.fetchByG_S(groupId, newStructureId);
281 
282             if (newStructure != null) {
283                 throw new DuplicateStructureIdException();
284             }
285         }
286 
287         long id = counterLocalService.increment();
288 
289         JournalStructure newStructure = journalStructurePersistence.create(id);
290 
291         newStructure.setGroupId(groupId);
292         newStructure.setCompanyId(user.getCompanyId());
293         newStructure.setUserId(user.getUserId());
294         newStructure.setUserName(user.getFullName());
295         newStructure.setCreateDate(now);
296         newStructure.setModifiedDate(now);
297         newStructure.setStructureId(newStructureId);
298         newStructure.setName(oldStructure.getName());
299         newStructure.setDescription(oldStructure.getDescription());
300         newStructure.setXsd(oldStructure.getXsd());
301 
302         journalStructurePersistence.update(newStructure, false);
303 
304         // Resources
305 
306         addStructureResources(newStructure, true, true);
307 
308         return null;
309     }
310 
311     public void deleteStructure(long groupId, String structureId)
312         throws PortalException, SystemException {
313 
314         structureId = structureId.trim().toUpperCase();
315 
316         JournalStructure structure = journalStructurePersistence.findByG_S(
317             groupId, structureId);
318 
319         deleteStructure(structure);
320     }
321 
322     public void deleteStructure(JournalStructure structure)
323         throws PortalException, SystemException {
324 
325         if (journalArticlePersistence.countByG_S(
326                 structure.getGroupId(), structure.getStructureId()) > 0) {
327 
328             throw new RequiredStructureException();
329         }
330 
331         if (journalTemplatePersistence.countByG_S(
332                 structure.getGroupId(), structure.getStructureId()) > 0) {
333 
334             throw new RequiredStructureException();
335         }
336 
337         // WebDAVProps
338 
339         webDAVPropsLocalService.deleteWebDAVProps(
340             JournalStructure.class.getName(), structure.getPrimaryKey());
341 
342         // Resources
343 
344         resourceLocalService.deleteResource(
345             structure.getCompanyId(), JournalStructure.class.getName(),
346             ResourceConstants.SCOPE_INDIVIDUAL, structure.getId());
347 
348         // Structure
349 
350         journalStructurePersistence.remove(structure.getPrimaryKey());
351     }
352 
353     public void deleteStructures(long groupId)
354         throws PortalException, SystemException {
355 
356         for (JournalStructure structure :
357                 journalStructurePersistence.findByGroupId(groupId)) {
358 
359             deleteStructure(structure);
360         }
361     }
362 
363     public JournalStructure getStructure(long id)
364         throws PortalException, SystemException {
365 
366         return journalStructurePersistence.findByPrimaryKey(id);
367     }
368 
369     public JournalStructure getStructure(long groupId, String structureId)
370         throws PortalException, SystemException {
371 
372         structureId = structureId.trim().toUpperCase();
373 
374         if (groupId == 0) {
375             _log.error(
376                 "No group id was passed for " + structureId + ". Group id is " +
377                     "required since 4.2.0. Please update all custom code and " +
378                         "data that references structures without a group id.");
379 
380             List<JournalStructure> structures =
381                 journalStructurePersistence.findByStructureId(structureId);
382 
383             if (structures.size() == 0) {
384                 throw new NoSuchStructureException(
385                     "No JournalStructure exists with the structure id " +
386                         structureId);
387             }
388             else {
389                 return structures.get(0);
390             }
391         }
392         else {
393             return journalStructurePersistence.findByG_S(groupId, structureId);
394         }
395     }
396 
397     public List<JournalStructure> getStructures() throws SystemException {
398         return journalStructurePersistence.findAll();
399     }
400 
401     public List<JournalStructure> getStructures(long groupId)
402         throws SystemException {
403 
404         return journalStructurePersistence.findByGroupId(groupId);
405     }
406 
407     public List<JournalStructure> getStructures(
408             long groupId, int start, int end)
409         throws SystemException {
410 
411         return journalStructurePersistence.findByGroupId(groupId, start, end);
412     }
413 
414     public int getStructuresCount(long groupId) throws SystemException {
415         return journalStructurePersistence.countByGroupId(groupId);
416     }
417 
418     public List<JournalStructure> search(
419             long companyId, long groupId, String keywords, int start, int end,
420             OrderByComparator obc)
421         throws SystemException {
422 
423         return journalStructureFinder.findByKeywords(
424             companyId, groupId, keywords, start, end, obc);
425     }
426 
427     public List<JournalStructure> search(
428             long companyId, long groupId, String structureId, String name,
429             String description, boolean andOperator, int start, int end,
430             OrderByComparator obc)
431         throws SystemException {
432 
433         return journalStructureFinder.findByC_G_S_N_D(
434             companyId, groupId, structureId, name, description, andOperator,
435             start, end, obc);
436     }
437 
438     public int searchCount(long companyId, long groupId, String keywords)
439         throws SystemException {
440 
441         return journalStructureFinder.countByKeywords(
442             companyId, groupId, keywords);
443     }
444 
445     public int searchCount(
446             long companyId, long groupId, String structureId, String name,
447             String description, boolean andOperator)
448         throws SystemException {
449 
450         return journalStructureFinder.countByC_G_S_N_D(
451             companyId, groupId, structureId, name, description, andOperator);
452     }
453 
454     public JournalStructure updateStructure(
455             long groupId, String structureId, String name, String description,
456             String xsd)
457         throws PortalException, SystemException {
458 
459         structureId = structureId.trim().toUpperCase();
460 
461         try {
462             xsd = JournalUtil.formatXML(xsd);
463         }
464         catch (DocumentException de) {
465             throw new StructureXsdException();
466         }
467         catch (IOException ioe) {
468             throw new StructureXsdException();
469         }
470 
471         validate(name, description, xsd);
472 
473         JournalStructure structure = journalStructurePersistence.findByG_S(
474             groupId, structureId);
475 
476         structure.setModifiedDate(new Date());
477         structure.setName(name);
478         structure.setDescription(description);
479         structure.setXsd(xsd);
480 
481         journalStructurePersistence.update(structure, false);
482 
483         return structure;
484     }
485 
486     protected void validate(String structureId) throws PortalException {
487         if ((Validator.isNull(structureId)) ||
488             (Validator.isNumber(structureId)) ||
489             (structureId.indexOf(StringPool.SPACE) != -1)) {
490 
491             throw new StructureIdException();
492         }
493     }
494 
495     protected void validate(
496             long groupId, String structureId, boolean autoStructureId,
497             String name, String description, String xsd)
498         throws PortalException, SystemException {
499 
500         if (!autoStructureId) {
501             validate(structureId);
502 
503             try {
504                 journalStructurePersistence.findByG_S(groupId, structureId);
505 
506                 throw new DuplicateStructureIdException();
507             }
508             catch (NoSuchStructureException nste) {
509             }
510         }
511 
512         validate(name, description, xsd);
513     }
514 
515     protected void validate(String name, String description, String xsd)
516         throws PortalException {
517 
518         if (Validator.isNull(name)) {
519             throw new StructureNameException();
520         }
521         else if (Validator.isNull(description)) {
522             throw new StructureDescriptionException();
523         }
524 
525         if (Validator.isNull(xsd)) {
526             throw new StructureXsdException();
527         }
528         else {
529             try {
530                 SAXReader reader = new SAXReader();
531 
532                 Document doc = reader.read(new StringReader(xsd));
533 
534                 Element root = doc.getRootElement();
535 
536                 List<Element> children = root.elements();
537 
538                 if (children.size() == 0) {
539                     throw new StructureXsdException();
540                 }
541 
542                 Set<String> elNames = new HashSet<String>();
543 
544                 validate(children, elNames);
545             }
546             catch (Exception e) {
547                 throw new StructureXsdException();
548             }
549         }
550     }
551 
552     protected void validate(List<Element> children, Set<String> elNames)
553         throws PortalException {
554 
555         for (Element el : children) {
556             String elName = el.attributeValue("name", StringPool.BLANK);
557             String elType = el.attributeValue("type", StringPool.BLANK);
558 
559             if (Validator.isNull(elName) ||
560                 elName.startsWith(JournalStructureImpl.RESERVED)) {
561 
562                 throw new StructureXsdException();
563             }
564             else {
565                 char[] c = elName.toCharArray();
566 
567                 for (int i = 0; i < c.length; i++) {
568                     if ((!Validator.isChar(c[i])) &&
569                         (!Validator.isDigit(c[i])) && (c[i] != CharPool.DASH) &&
570                         (c[i] != CharPool.UNDERLINE)) {
571 
572                         throw new StructureXsdException();
573                     }
574                 }
575 
576                 String completePath = elName;
577 
578                 Element parent = el.getParent();
579 
580                 while (!parent.isRootElement()) {
581                     completePath =
582                         parent.attributeValue("name", StringPool.BLANK) +
583                             StringPool.SLASH + completePath;
584 
585                     parent = parent.getParent();
586                 }
587 
588                 String elNameLowerCase = completePath.toLowerCase();
589 
590                 if (elNames.contains(elNameLowerCase)) {
591                     throw new StructureXsdException();
592                 }
593                 else {
594                     elNames.add(elNameLowerCase);
595                 }
596             }
597 
598             if (Validator.isNull(elType)) {
599                 throw new StructureXsdException();
600             }
601 
602             validate(el.elements(), elNames);
603         }
604     }
605 
606     private static Log _log =
607         LogFactory.getLog(JournalStructureLocalServiceImpl.class);
608 
609 }