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.OrderByComparator;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.StringUtil;
30  import com.liferay.portal.kernel.util.Validator;
31  import com.liferay.portal.model.User;
32  import com.liferay.portal.model.impl.ResourceImpl;
33  import com.liferay.portal.util.PortalUtil;
34  import com.liferay.portlet.journal.DuplicateStructureIdException;
35  import com.liferay.portlet.journal.NoSuchStructureException;
36  import com.liferay.portlet.journal.RequiredStructureException;
37  import com.liferay.portlet.journal.StructureDescriptionException;
38  import com.liferay.portlet.journal.StructureIdException;
39  import com.liferay.portlet.journal.StructureNameException;
40  import com.liferay.portlet.journal.StructureXsdException;
41  import com.liferay.portlet.journal.model.JournalStructure;
42  import com.liferay.portlet.journal.model.impl.JournalStructureImpl;
43  import com.liferay.portlet.journal.service.base.JournalStructureLocalServiceBaseImpl;
44  import com.liferay.portlet.journal.util.JournalUtil;
45  
46  import java.io.IOException;
47  import java.io.StringReader;
48  
49  import java.util.Date;
50  import java.util.HashSet;
51  import java.util.Iterator;
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);
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);
255         }
256     }
257 
258     public void deleteStructure(long groupId, String structureId)
259         throws PortalException, SystemException {
260 
261         structureId = structureId.trim().toUpperCase();
262 
263         JournalStructure structure = journalStructurePersistence.findByG_S(
264             groupId, structureId);
265 
266         deleteStructure(structure);
267     }
268 
269     public void deleteStructure(JournalStructure structure)
270         throws PortalException, SystemException {
271 
272         if (journalArticlePersistence.countByG_S(
273                 structure.getGroupId(), structure.getStructureId()) > 0) {
274 
275             throw new RequiredStructureException();
276         }
277 
278         if (journalTemplatePersistence.countByG_S(
279                 structure.getGroupId(), structure.getStructureId()) > 0) {
280 
281             throw new RequiredStructureException();
282         }
283 
284         // Resources
285 
286         resourceLocalService.deleteResource(
287             structure.getCompanyId(), JournalStructure.class.getName(),
288             ResourceImpl.SCOPE_INDIVIDUAL, structure.getId());
289 
290         // WebDAVProps
291 
292         webDAVPropsLocalService.deleteWebDAVProps(
293             JournalStructure.class.getName(), structure.getPrimaryKey());
294 
295         // Structure
296 
297         journalStructurePersistence.remove(structure.getPrimaryKey());
298     }
299 
300     public void deleteStructures(long groupId)
301         throws PortalException, SystemException {
302 
303         Iterator itr = journalStructurePersistence.findByGroupId(
304             groupId).iterator();
305 
306         while (itr.hasNext()) {
307             JournalStructure structure = (JournalStructure)itr.next();
308 
309             deleteStructure(structure);
310         }
311     }
312 
313     public JournalStructure getStructure(long id)
314         throws PortalException, SystemException {
315 
316         return journalStructurePersistence.findByPrimaryKey(id);
317     }
318 
319     public JournalStructure getStructure(long groupId, String structureId)
320         throws PortalException, SystemException {
321 
322         structureId = structureId.trim().toUpperCase();
323 
324         if (groupId == 0) {
325             _log.error(
326                 "No group id was passed for " + structureId + ". Group id is " +
327                     "required since 4.2.0. Please update all custom code and " +
328                         "data that references structures without a group id.");
329 
330             List structures = journalStructurePersistence.findByStructureId(
331                 structureId);
332 
333             if (structures.size() == 0) {
334                 throw new NoSuchStructureException(
335                     "No JournalStructure exists with the structure id " +
336                         structureId);
337             }
338             else {
339                 return (JournalStructure)structures.get(0);
340             }
341         }
342         else {
343             return journalStructurePersistence.findByG_S(groupId, structureId);
344         }
345     }
346 
347     public List getStructures() throws SystemException {
348         return journalStructurePersistence.findAll();
349     }
350 
351     public List getStructures(long groupId) throws SystemException {
352         return journalStructurePersistence.findByGroupId(groupId);
353     }
354 
355     public List getStructures(long groupId, int begin, int end)
356         throws SystemException {
357 
358         return journalStructurePersistence.findByGroupId(groupId, begin, end);
359     }
360 
361     public int getStructuresCount(long groupId) throws SystemException {
362         return journalStructurePersistence.countByGroupId(groupId);
363     }
364 
365     public List search(
366             long companyId, long groupId, String keywords, int begin, int end,
367             OrderByComparator obc)
368         throws SystemException {
369 
370         return journalStructureFinder.findByKeywords(
371             companyId, groupId, keywords, begin, end, obc);
372     }
373 
374     public List search(
375             long companyId, long groupId, String structureId, String name,
376             String description, boolean andOperator, int begin, int end,
377             OrderByComparator obc)
378         throws SystemException {
379 
380         return journalStructureFinder.findByC_G_S_N_D(
381             companyId, groupId, structureId, name, description, andOperator,
382             begin, end, obc);
383     }
384 
385     public int searchCount(long companyId, long groupId, String keywords)
386         throws SystemException {
387 
388         return journalStructureFinder.countByKeywords(
389             companyId, groupId, keywords);
390     }
391 
392     public int searchCount(
393             long companyId, long groupId, String structureId, String name,
394             String description, boolean andOperator)
395         throws SystemException {
396 
397         return journalStructureFinder.countByC_G_S_N_D(
398             companyId, groupId, structureId, name, description, andOperator);
399     }
400 
401     public JournalStructure updateStructure(
402             long groupId, String structureId, String name, String description,
403             String xsd)
404         throws PortalException, SystemException {
405 
406         structureId = structureId.trim().toUpperCase();
407 
408         try {
409             xsd = JournalUtil.formatXML(xsd);
410         }
411         catch (DocumentException de) {
412             throw new StructureXsdException();
413         }
414         catch (IOException ioe) {
415             throw new StructureXsdException();
416         }
417 
418         validate(name, description, xsd);
419 
420         JournalStructure structure = journalStructurePersistence.findByG_S(
421             groupId, structureId);
422 
423         structure.setModifiedDate(new Date());
424         structure.setName(name);
425         structure.setDescription(description);
426         structure.setXsd(xsd);
427 
428         journalStructurePersistence.update(structure);
429 
430         return structure;
431     }
432 
433     protected void validate(
434             long groupId, String structureId, boolean autoStructureId,
435             String name, String description, String xsd)
436         throws PortalException, SystemException {
437 
438         if (!autoStructureId) {
439             if ((Validator.isNull(structureId)) ||
440                 (Validator.isNumber(structureId)) ||
441                 (structureId.indexOf(StringPool.SPACE) != -1)) {
442 
443                 throw new StructureIdException();
444             }
445 
446             try {
447                 journalStructurePersistence.findByG_S(groupId, structureId);
448 
449                 throw new DuplicateStructureIdException();
450             }
451             catch (NoSuchStructureException nste) {
452             }
453         }
454 
455         validate(name, description, xsd);
456     }
457 
458     protected void validate(String name, String description, String xsd)
459         throws PortalException {
460 
461         if (Validator.isNull(name)) {
462             throw new StructureNameException();
463         }
464         else if (Validator.isNull(description)) {
465             throw new StructureDescriptionException();
466         }
467 
468         if (Validator.isNull(xsd)) {
469             throw new StructureXsdException();
470         }
471         else {
472             try {
473                 SAXReader reader = new SAXReader();
474 
475                 Document doc = reader.read(new StringReader(xsd));
476 
477                 Element root = doc.getRootElement();
478 
479                 List children = root.elements();
480 
481                 if (children.size() == 0) {
482                     throw new StructureXsdException();
483                 }
484 
485                 Set elNames = new HashSet();
486 
487                 validate(children, elNames);
488             }
489             catch (Exception e) {
490                 throw new StructureXsdException();
491             }
492         }
493     }
494 
495     protected void validate(List children, Set elNames) throws PortalException {
496         Iterator itr = children.iterator();
497 
498         while (itr.hasNext()) {
499             Element el = (Element)itr.next();
500 
501             String elName = el.attributeValue("name", StringPool.BLANK);
502             String elType = el.attributeValue("type", StringPool.BLANK);
503 
504             if (Validator.isNull(elName) ||
505                 elName.startsWith(JournalStructureImpl.RESERVED)) {
506 
507                 throw new StructureXsdException();
508             }
509             else {
510                 char[] c = elName.toCharArray();
511 
512                 for (int i = 0; i < c.length; i++) {
513                     if ((!Validator.isChar(c[i])) &&
514                         (!Validator.isDigit(c[i])) &&
515                         (c[i] != '_') && (c[i] != '-')) {
516 
517                         throw new StructureXsdException();
518                     }
519                 }
520 
521                 String completePath = elName;
522 
523                 Element parent = el.getParent();
524 
525                 while (!parent.isRootElement()) {
526                     completePath =
527                         parent.attributeValue("name", StringPool.BLANK) +
528                             StringPool.SLASH + completePath;
529 
530                     parent = parent.getParent();
531                 }
532 
533                 String elNameLowerCase = completePath.toLowerCase();
534 
535                 if (elNames.contains(elNameLowerCase)) {
536                     throw new StructureXsdException();
537                 }
538                 else {
539                     elNames.add(elNameLowerCase);
540                 }
541             }
542 
543             if (Validator.isNull(elType)) {
544                 throw new StructureXsdException();
545             }
546 
547             validate(el.elements(), elNames);
548         }
549     }
550 
551     private static Log _log =
552         LogFactory.getLog(JournalStructureLocalServiceImpl.class);
553 
554 }