1   /**
2    * Copyright (c) 2000-2009 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.log.Log;
28  import com.liferay.portal.kernel.log.LogFactoryUtil;
29  import com.liferay.portal.kernel.util.FileUtil;
30  import com.liferay.portal.kernel.util.GetterUtil;
31  import com.liferay.portal.kernel.util.OrderByComparator;
32  import com.liferay.portal.kernel.util.StringPool;
33  import com.liferay.portal.kernel.util.StringUtil;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.model.Image;
36  import com.liferay.portal.model.ResourceConstants;
37  import com.liferay.portal.model.User;
38  import com.liferay.portal.service.ServiceContext;
39  import com.liferay.portal.util.PrefsPropsUtil;
40  import com.liferay.portal.util.PropsKeys;
41  import com.liferay.portlet.expando.model.ExpandoBridge;
42  import com.liferay.portlet.journal.DuplicateTemplateIdException;
43  import com.liferay.portlet.journal.NoSuchTemplateException;
44  import com.liferay.portlet.journal.RequiredTemplateException;
45  import com.liferay.portlet.journal.TemplateDescriptionException;
46  import com.liferay.portlet.journal.TemplateIdException;
47  import com.liferay.portlet.journal.TemplateNameException;
48  import com.liferay.portlet.journal.TemplateSmallImageNameException;
49  import com.liferay.portlet.journal.TemplateSmallImageSizeException;
50  import com.liferay.portlet.journal.TemplateXslException;
51  import com.liferay.portlet.journal.model.JournalTemplate;
52  import com.liferay.portlet.journal.model.impl.JournalTemplateImpl;
53  import com.liferay.portlet.journal.service.base.JournalTemplateLocalServiceBaseImpl;
54  import com.liferay.portlet.journal.util.JournalUtil;
55  
56  import java.io.File;
57  import java.io.IOException;
58  
59  import java.util.Date;
60  import java.util.List;
61  
62  /**
63   * <a href="JournalTemplateLocalServiceImpl.java.html"><b><i>View Source</i></b>
64   * </a>
65   *
66   * @author Brian Wing Shun Chan
67   * @author Raymond Augé
68   *
69   */
70  public class JournalTemplateLocalServiceImpl
71      extends JournalTemplateLocalServiceBaseImpl {
72  
73      public JournalTemplate addTemplate(
74              long userId, long groupId, String templateId,
75              boolean autoTemplateId, String structureId, String name,
76              String description, String xsl, boolean formatXsl, String langType,
77              boolean cacheable, boolean smallImage, String smallImageURL,
78              File smallFile, ServiceContext serviceContext)
79          throws PortalException, SystemException {
80  
81          return addTemplate(
82              null, userId, groupId, templateId, autoTemplateId, structureId,
83              name, description, xsl, formatXsl, langType, cacheable, smallImage,
84              smallImageURL, smallFile, serviceContext);
85      }
86  
87      public JournalTemplate addTemplate(
88              String uuid, long userId, long groupId, String templateId,
89              boolean autoTemplateId, String structureId, String name,
90              String description, String xsl, boolean formatXsl, String langType,
91              boolean cacheable, boolean smallImage, String smallImageURL,
92              File smallFile, ServiceContext serviceContext)
93          throws PortalException, SystemException {
94  
95          // Template
96  
97          User user = userPersistence.findByPrimaryKey(userId);
98          templateId = templateId.trim().toUpperCase();
99          Date now = new Date();
100 
101         try {
102             if (formatXsl) {
103                 if (langType.equals(JournalTemplateImpl.LANG_TYPE_VM)) {
104                     xsl = JournalUtil.formatVM(xsl);
105                 }
106                 else {
107                     xsl = JournalUtil.formatXML(xsl);
108                 }
109             }
110         }
111         catch (Exception e) {
112             throw new TemplateXslException();
113         }
114 
115         byte[] smallBytes = null;
116 
117         try {
118             smallBytes = FileUtil.getBytes(smallFile);
119         }
120         catch (IOException ioe) {
121         }
122 
123         validate(
124             groupId, templateId, autoTemplateId, name, description, xsl,
125             smallImage, smallImageURL, smallFile, smallBytes);
126 
127         if (autoTemplateId) {
128             templateId = String.valueOf(counterLocalService.increment());
129         }
130 
131         long id = counterLocalService.increment();
132 
133         JournalTemplate template = journalTemplatePersistence.create(id);
134 
135         template.setUuid(uuid);
136         template.setGroupId(groupId);
137         template.setCompanyId(user.getCompanyId());
138         template.setUserId(user.getUserId());
139         template.setUserName(user.getFullName());
140         template.setCreateDate(now);
141         template.setModifiedDate(now);
142         template.setTemplateId(templateId);
143         template.setStructureId(structureId);
144         template.setName(name);
145         template.setDescription(description);
146         template.setXsl(xsl);
147         template.setLangType(langType);
148         template.setCacheable(cacheable);
149         template.setSmallImage(smallImage);
150         template.setSmallImageId(counterLocalService.increment());
151         template.setSmallImageURL(smallImageURL);
152 
153         journalTemplatePersistence.update(template, false);
154 
155         // Resources
156 
157         if (serviceContext.getAddCommunityPermissions() ||
158             serviceContext.getAddGuestPermissions()) {
159 
160             addTemplateResources(
161                 template, serviceContext.getAddCommunityPermissions(),
162                 serviceContext.getAddGuestPermissions());
163         }
164         else {
165             addTemplateResources(
166                 template, serviceContext.getCommunityPermissions(),
167                 serviceContext.getGuestPermissions());
168         }
169 
170         // Expando
171 
172         ExpandoBridge expandoBridge = template.getExpandoBridge();
173 
174         expandoBridge.setAttributes(serviceContext);
175 
176         // Small image
177 
178         saveImages(
179             smallImage, template.getSmallImageId(), smallFile, smallBytes);
180 
181         return template;
182     }
183 
184     public void addTemplateResources(
185             long groupId, String templateId, boolean addCommunityPermissions,
186             boolean addGuestPermissions)
187         throws PortalException, SystemException {
188 
189         JournalTemplate template = journalTemplatePersistence.findByG_T(
190             groupId, templateId);
191 
192         addTemplateResources(
193             template, addCommunityPermissions, addGuestPermissions);
194     }
195 
196     public void addTemplateResources(
197             JournalTemplate template, boolean addCommunityPermissions,
198             boolean addGuestPermissions)
199         throws PortalException, SystemException {
200 
201         resourceLocalService.addResources(
202             template.getCompanyId(), template.getGroupId(),
203             template.getUserId(), JournalTemplate.class.getName(),
204             template.getId(), false, addCommunityPermissions,
205             addGuestPermissions);
206     }
207 
208     public void addTemplateResources(
209             long groupId, String templateId, String[] communityPermissions,
210             String[] guestPermissions)
211         throws PortalException, SystemException {
212 
213         JournalTemplate template = journalTemplatePersistence.findByG_T(
214             groupId, templateId);
215 
216         addTemplateResources(template, communityPermissions, guestPermissions);
217     }
218 
219     public void addTemplateResources(
220             JournalTemplate template, String[] communityPermissions,
221             String[] guestPermissions)
222         throws PortalException, SystemException {
223 
224         resourceLocalService.addModelResources(
225             template.getCompanyId(), template.getGroupId(),
226             template.getUserId(), JournalTemplate.class.getName(),
227             template.getId(), communityPermissions, guestPermissions);
228     }
229 
230     public void checkNewLine(long groupId, String templateId)
231         throws PortalException, SystemException {
232 
233         JournalTemplate template = journalTemplatePersistence.findByG_T(
234             groupId, templateId);
235 
236         String xsl = template.getXsl();
237 
238         if ((xsl != null) && (xsl.indexOf("\\n") != -1)) {
239             xsl = StringUtil.replace(
240                 xsl,
241                 new String[] {"\\n", "\\r"},
242                 new String[] {"\n", "\r"});
243 
244             template.setXsl(xsl);
245 
246             journalTemplatePersistence.update(template, false);
247         }
248     }
249 
250     public JournalTemplate copyTemplate(
251             long userId, long groupId, String oldTemplateId,
252             String newTemplateId, boolean autoTemplateId)
253         throws PortalException, SystemException {
254 
255         // Template
256 
257         User user = userPersistence.findByPrimaryKey(userId);
258         oldTemplateId = oldTemplateId.trim().toUpperCase();
259         newTemplateId = newTemplateId.trim().toUpperCase();
260         Date now = new Date();
261 
262         JournalTemplate oldTemplate = journalTemplatePersistence.findByG_T(
263             groupId, oldTemplateId);
264 
265         if (autoTemplateId) {
266             newTemplateId = String.valueOf(counterLocalService.increment());
267         }
268         else {
269             validate(newTemplateId);
270 
271             JournalTemplate newTemplate = journalTemplatePersistence.fetchByG_T(
272                 groupId, newTemplateId);
273 
274             if (newTemplate != null) {
275                 throw new DuplicateTemplateIdException();
276             }
277         }
278 
279         long id = counterLocalService.increment();
280 
281         JournalTemplate newTemplate = journalTemplatePersistence.create(id);
282 
283         newTemplate.setGroupId(groupId);
284         newTemplate.setCompanyId(user.getCompanyId());
285         newTemplate.setUserId(user.getUserId());
286         newTemplate.setUserName(user.getFullName());
287         newTemplate.setCreateDate(now);
288         newTemplate.setModifiedDate(now);
289         newTemplate.setTemplateId(newTemplateId);
290         newTemplate.setStructureId(oldTemplate.getStructureId());
291         newTemplate.setName(oldTemplate.getName());
292         newTemplate.setDescription(oldTemplate.getDescription());
293         newTemplate.setXsl(oldTemplate.getXsl());
294         newTemplate.setLangType(oldTemplate.getLangType());
295         newTemplate.setCacheable(oldTemplate.isCacheable());
296         newTemplate.setSmallImage(oldTemplate.isSmallImage());
297         newTemplate.setSmallImageId(counterLocalService.increment());
298         newTemplate.setSmallImageURL(oldTemplate.getSmallImageURL());
299 
300         journalTemplatePersistence.update(newTemplate, false);
301 
302         // Small image
303 
304         if (oldTemplate.getSmallImage()) {
305             Image image = imageLocalService.getImage(
306                 oldTemplate.getSmallImageId());
307 
308             byte[] smallBytes = image.getTextObj();
309 
310             imageLocalService.updateImage(
311                 newTemplate.getSmallImageId(), smallBytes);
312         }
313 
314         // Resources
315 
316         addTemplateResources(newTemplate, true, true);
317 
318         return newTemplate;
319     }
320 
321     public void deleteTemplate(long groupId, String templateId)
322         throws PortalException, SystemException {
323 
324         templateId = templateId.trim().toUpperCase();
325 
326         JournalTemplate template = journalTemplatePersistence.findByG_T(
327             groupId, templateId);
328 
329         deleteTemplate(template);
330     }
331 
332     public void deleteTemplate(JournalTemplate template)
333         throws PortalException, SystemException {
334 
335         if (journalArticlePersistence.countByG_T(
336                 template.getGroupId(), template.getTemplateId()) > 0) {
337 
338             throw new RequiredTemplateException();
339         }
340 
341         // WebDAVProps
342 
343         webDAVPropsLocalService.deleteWebDAVProps(
344             JournalTemplate.class.getName(), template.getPrimaryKey());
345 
346         // Small image
347 
348         imageLocalService.deleteImage(template.getSmallImageId());
349 
350         // Expando
351 
352         expandoValueLocalService.deleteValues(
353             JournalTemplate.class.getName(), template.getPrimaryKey());
354 
355         // Resources
356 
357         resourceLocalService.deleteResource(
358             template.getCompanyId(), JournalTemplate.class.getName(),
359             ResourceConstants.SCOPE_INDIVIDUAL, template.getId());
360 
361         // Template
362 
363         journalTemplatePersistence.remove(template);
364     }
365 
366     public void deleteTemplates(long groupId)
367         throws PortalException, SystemException {
368 
369         for (JournalTemplate template :
370                 journalTemplatePersistence.findByGroupId(groupId)) {
371 
372             deleteTemplate(template);
373         }
374     }
375 
376     public List<JournalTemplate> getStructureTemplates(
377             long groupId, String structureId)
378         throws SystemException {
379 
380         return journalTemplatePersistence.findByG_S(groupId, structureId);
381     }
382 
383     public List<JournalTemplate> getStructureTemplates(
384             long groupId, String structureId, int start, int end)
385         throws SystemException {
386 
387         return journalTemplatePersistence.findByG_S(
388             groupId, structureId, start, end);
389     }
390 
391     public int getStructureTemplatesCount(long groupId, String structureId)
392         throws SystemException {
393 
394         return journalTemplatePersistence.countByG_S(groupId, structureId);
395     }
396 
397     public JournalTemplate getTemplate(long id)
398         throws PortalException, SystemException {
399 
400         return journalTemplatePersistence.findByPrimaryKey(id);
401     }
402 
403     public JournalTemplate getTemplate(long groupId, String templateId)
404         throws PortalException, SystemException {
405 
406         templateId = GetterUtil.getString(templateId).toUpperCase();
407 
408         if (groupId == 0) {
409             _log.error(
410                 "No group id was passed for " + templateId + ". Group id is " +
411                     "required since 4.2.0. Please update all custom code and " +
412                         "data that references templates without a group id.");
413 
414             List<JournalTemplate> templates =
415                 journalTemplatePersistence.findByTemplateId(
416                     templateId);
417 
418             if (templates.size() == 0) {
419                 throw new NoSuchTemplateException(
420                     "No JournalTemplate exists with the template id " +
421                         templateId);
422             }
423             else {
424                 return templates.get(0);
425             }
426         }
427         else {
428             return journalTemplatePersistence.findByG_T(groupId, templateId);
429         }
430     }
431 
432     public JournalTemplate getTemplateBySmallImageId(long smallImageId)
433         throws PortalException, SystemException {
434 
435         return journalTemplatePersistence.findBySmallImageId(smallImageId);
436     }
437 
438     public List<JournalTemplate> getTemplates() throws SystemException {
439         return journalTemplatePersistence.findAll();
440     }
441 
442     public List<JournalTemplate> getTemplates(long groupId)
443         throws SystemException {
444 
445         return journalTemplatePersistence.findByGroupId(groupId);
446     }
447 
448     public List<JournalTemplate> getTemplates(long groupId, int start, int end)
449         throws SystemException {
450 
451         return journalTemplatePersistence.findByGroupId(groupId, start, end);
452     }
453 
454     public int getTemplatesCount(long groupId) throws SystemException {
455         return journalTemplatePersistence.countByGroupId(groupId);
456     }
457 
458     public boolean hasTemplate(long groupId, String templateId)
459         throws SystemException {
460 
461         try {
462             getTemplate(groupId, templateId);
463 
464             return true;
465         }
466         catch (PortalException pe) {
467             return false;
468         }
469     }
470 
471     public List<JournalTemplate> search(
472             long companyId, long groupId, String keywords, String structureId,
473             String structureIdComparator, int start, int end,
474             OrderByComparator obc)
475         throws SystemException {
476 
477         return journalTemplateFinder.findByKeywords(
478             companyId, groupId, keywords, structureId, structureIdComparator,
479             start, end, obc);
480     }
481 
482     public List<JournalTemplate> search(
483             long companyId, long groupId, String templateId, String structureId,
484             String structureIdComparator, String name, String description,
485             boolean andOperator, int start, int end, OrderByComparator obc)
486         throws SystemException {
487 
488         return journalTemplateFinder.findByC_G_T_S_N_D(
489             companyId, groupId, templateId, structureId, structureIdComparator,
490             name, description, andOperator, start, end, obc);
491     }
492 
493     public int searchCount(
494             long companyId, long groupId, String keywords, String structureId,
495             String structureIdComparator)
496         throws SystemException {
497 
498         return journalTemplateFinder.countByKeywords(
499             companyId, groupId, keywords, structureId, structureIdComparator);
500     }
501 
502     public int searchCount(
503             long companyId, long groupId, String templateId, String structureId,
504             String structureIdComparator, String name, String description,
505             boolean andOperator)
506         throws SystemException {
507 
508         return journalTemplateFinder.countByC_G_T_S_N_D(
509             companyId, groupId, templateId, structureId, structureIdComparator,
510             name, description, andOperator);
511     }
512 
513     public JournalTemplate updateTemplate(
514             long groupId, String templateId, String structureId, String name,
515             String description, String xsl, boolean formatXsl, String langType,
516             boolean cacheable, boolean smallImage, String smallImageURL,
517             File smallFile, ServiceContext serviceContext)
518         throws PortalException, SystemException {
519 
520         // Template
521 
522         templateId = templateId.trim().toUpperCase();
523 
524         try {
525             if (formatXsl) {
526                 if (langType.equals(JournalTemplateImpl.LANG_TYPE_VM)) {
527                     xsl = JournalUtil.formatVM(xsl);
528                 }
529                 else {
530                     xsl = JournalUtil.formatXML(xsl);
531                 }
532             }
533         }
534         catch (Exception e) {
535             throw new TemplateXslException();
536         }
537 
538         byte[] smallBytes = null;
539 
540         try {
541             smallBytes = FileUtil.getBytes(smallFile);
542         }
543         catch (IOException ioe) {
544         }
545 
546         validate(
547             name, description, xsl, smallImage, smallImageURL, smallFile,
548             smallBytes);
549 
550         JournalTemplate template = journalTemplatePersistence.findByG_T(
551             groupId, templateId);
552 
553         template.setModifiedDate(new Date());
554 
555         if (Validator.isNull(template.getStructureId()) &&
556             Validator.isNotNull(structureId)) {
557 
558             // Allow users to set the structure if and only if it currently
559             // does not have one. Otherwise, you can have bad data because there
560             // may be an existing article that has chosen to use a structure and
561             // template combination that no longer exists.
562 
563             template.setStructureId(structureId);
564         }
565 
566         template.setName(name);
567         template.setDescription(description);
568         template.setXsl(xsl);
569         template.setLangType(langType);
570         template.setCacheable(cacheable);
571         template.setSmallImage(smallImage);
572         template.setSmallImageURL(smallImageURL);
573 
574         journalTemplatePersistence.update(template, false);
575 
576         // Expando
577 
578         ExpandoBridge expandoBridge = template.getExpandoBridge();
579 
580         expandoBridge.setAttributes(serviceContext);
581 
582         // Small image
583 
584         saveImages(
585             smallImage, template.getSmallImageId(), smallFile, smallBytes);
586 
587         return template;
588     }
589 
590     protected void saveImages(
591             boolean smallImage, long smallImageId, File smallFile,
592             byte[] smallBytes)
593         throws PortalException, SystemException {
594 
595         if (smallImage) {
596             if ((smallFile != null) && (smallBytes != null)) {
597                 imageLocalService.updateImage(smallImageId, smallBytes);
598             }
599         }
600         else {
601             imageLocalService.deleteImage(smallImageId);
602         }
603     }
604 
605     protected void validate(String templateId) throws PortalException {
606         if ((Validator.isNull(templateId)) ||
607             (Validator.isNumber(templateId)) ||
608             (templateId.indexOf(StringPool.SPACE) != -1)) {
609 
610             throw new TemplateIdException();
611         }
612     }
613 
614     protected void validate(
615             long groupId, String templateId, boolean autoTemplateId,
616             String name, String description, String xsl, boolean smallImage,
617             String smallImageURL, File smallFile, byte[] smallBytes)
618         throws PortalException, SystemException {
619 
620         if (!autoTemplateId) {
621             validate(templateId);
622 
623             JournalTemplate template = journalTemplatePersistence.fetchByG_T(
624                 groupId, templateId);
625 
626             if (template != null) {
627                 throw new DuplicateTemplateIdException();
628             }
629         }
630 
631         validate(
632             name, description, xsl, smallImage, smallImageURL, smallFile,
633             smallBytes);
634     }
635 
636     protected void validate(
637             String name, String description, String xsl, boolean smallImage,
638             String smallImageURL, File smallFile, byte[] smallBytes)
639         throws PortalException, SystemException {
640 
641         if (Validator.isNull(name)) {
642             throw new TemplateNameException();
643         }
644         else if (Validator.isNull(description)) {
645             throw new TemplateDescriptionException();
646         }
647         else if (Validator.isNull(xsl)) {
648             throw new TemplateXslException();
649         }
650 
651         String[] imageExtensions = PrefsPropsUtil.getStringArray(
652             PropsKeys.JOURNAL_IMAGE_EXTENSIONS, StringPool.COMMA);
653 
654         if (smallImage && Validator.isNull(smallImageURL) &&
655             smallFile != null && smallBytes != null) {
656 
657             String smallImageName = smallFile.getName();
658 
659             if (smallImageName != null) {
660                 boolean validSmallImageExtension = false;
661 
662                 for (int i = 0; i < imageExtensions.length; i++) {
663                     if (StringPool.STAR.equals(imageExtensions[i]) ||
664                         StringUtil.endsWith(
665                             smallImageName, imageExtensions[i])) {
666 
667                         validSmallImageExtension = true;
668 
669                         break;
670                     }
671                 }
672 
673                 if (!validSmallImageExtension) {
674                     throw new TemplateSmallImageNameException(smallImageName);
675                 }
676             }
677 
678             long smallImageMaxSize = PrefsPropsUtil.getLong(
679                 PropsKeys.JOURNAL_IMAGE_SMALL_MAX_SIZE);
680 
681             if ((smallImageMaxSize > 0) &&
682                 ((smallBytes == null) ||
683                     (smallBytes.length > smallImageMaxSize))) {
684 
685                 throw new TemplateSmallImageSizeException();
686             }
687         }
688     }
689 
690     private static Log _log =
691         LogFactoryUtil.getLog(JournalTemplateLocalServiceImpl.class);
692 
693 }