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.portal.service.impl;
24  
25  import com.liferay.portal.SystemException;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.plugin.PluginPackage;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.HttpUtil;
31  import com.liferay.portal.kernel.util.ListUtil;
32  import com.liferay.portal.kernel.util.ObjectValuePair;
33  import com.liferay.portal.kernel.util.StringPool;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.kernel.velocity.VelocityContext;
36  import com.liferay.portal.kernel.velocity.VelocityEngineUtil;
37  import com.liferay.portal.kernel.xml.Document;
38  import com.liferay.portal.kernel.xml.Element;
39  import com.liferay.portal.kernel.xml.SAXReaderUtil;
40  import com.liferay.portal.model.LayoutTemplate;
41  import com.liferay.portal.model.LayoutTemplateConstants;
42  import com.liferay.portal.model.PluginSetting;
43  import com.liferay.portal.model.impl.LayoutTemplateImpl;
44  import com.liferay.portal.service.PluginSettingLocalServiceUtil;
45  import com.liferay.portal.service.base.LayoutTemplateLocalServiceBaseImpl;
46  import com.liferay.portal.util.PropsValues;
47  import com.liferay.portlet.layoutconfiguration.util.velocity.InitColumnProcessor;
48  
49  import java.io.IOException;
50  import java.io.PrintWriter;
51  import java.io.StringWriter;
52  
53  import java.util.ArrayList;
54  import java.util.HashSet;
55  import java.util.Iterator;
56  import java.util.LinkedHashMap;
57  import java.util.List;
58  import java.util.Map;
59  import java.util.Set;
60  
61  import javax.servlet.ServletContext;
62  
63  /**
64   * <a href="LayoutTemplateLocalServiceImpl.java.html"><b><i>View Source</i></b>
65   * </a>
66   *
67   * @author Ivica Cardic
68   * @author Jorge Ferrer
69   * @author Brian Wing Shun Chan
70   * @author Raymond Augé
71   *
72  */
73  public class LayoutTemplateLocalServiceImpl
74      extends LayoutTemplateLocalServiceBaseImpl {
75  
76      public String getContent(
77              String layoutTemplateId, boolean standard, String themeId)
78          throws SystemException {
79  
80          LayoutTemplate layoutTemplate = getLayoutTemplate(
81              layoutTemplateId, standard, themeId);
82  
83          if (layoutTemplate == null) {
84              if (_log.isWarnEnabled()) {
85                  _log.warn(
86                      "Layout template " + layoutTemplateId + " does not exist");
87              }
88  
89              layoutTemplate = getLayoutTemplate(
90                  PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID, standard, themeId);
91  
92              if (layoutTemplate == null) {
93                  _log.error(
94                      "Layout template " + layoutTemplateId +
95                          " and default layout template " +
96                              PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
97                                  " do not exist");
98  
99                  return StringPool.BLANK;
100             }
101         }
102 
103         if (PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
104             return layoutTemplate.getContent();
105         }
106         else {
107             try {
108                 return layoutTemplate.getUncachedContent();
109             }
110             catch (IOException ioe) {
111                 throw new SystemException(ioe);
112             }
113         }
114     }
115 
116     public LayoutTemplate getLayoutTemplate(
117         String layoutTemplateId, boolean standard, String themeId) {
118 
119         if (Validator.isNull(layoutTemplateId)) {
120             return null;
121         }
122 
123         LayoutTemplate layoutTemplate = null;
124 
125         if (themeId != null) {
126             if (standard) {
127                 layoutTemplate = _getThemesStandard(themeId).get(
128                     layoutTemplateId);
129             }
130             else {
131                 layoutTemplate = _getThemesCustom(themeId).get(
132                     layoutTemplateId);
133             }
134 
135             if (layoutTemplate != null) {
136                 return layoutTemplate;
137             }
138         }
139 
140         if (standard) {
141             layoutTemplate = _warStandard.get(layoutTemplateId);
142 
143             if (layoutTemplate == null) {
144                 layoutTemplate = _portalStandard.get(layoutTemplateId);
145             }
146         }
147         else {
148             layoutTemplate = _warCustom.get(layoutTemplateId);
149 
150             if (layoutTemplate == null) {
151                 layoutTemplate = _portalCustom.get(layoutTemplateId);
152             }
153         }
154 
155         return layoutTemplate;
156     }
157 
158     public List<LayoutTemplate> getLayoutTemplates() {
159         List<LayoutTemplate> customLayoutTemplates =
160             new ArrayList<LayoutTemplate>(
161                             _portalCustom.size() + _warCustom.size());
162 
163         customLayoutTemplates.addAll(
164             ListUtil.fromCollection(_portalCustom.values()));
165 
166         customLayoutTemplates.addAll(
167             ListUtil.fromCollection(_warCustom.values()));
168 
169         return customLayoutTemplates;
170     }
171 
172     public List<LayoutTemplate> getLayoutTemplates(String themeId) {
173         Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
174 
175         List<LayoutTemplate> customLayoutTemplates =
176             new ArrayList<LayoutTemplate>(
177                 _portalCustom.size() + _warCustom.size() +
178                     _themesCustom.size());
179 
180         Iterator<Map.Entry<String, LayoutTemplate>> itr =
181             _portalCustom.entrySet().iterator();
182 
183         while (itr.hasNext()) {
184             Map.Entry<String, LayoutTemplate> entry = itr.next();
185 
186             String layoutTemplateId = entry.getKey();
187             LayoutTemplate layoutTemplate = entry.getValue();
188 
189             if (_themesCustom.containsKey(layoutTemplateId)) {
190                 customLayoutTemplates.add(_themesCustom.get(layoutTemplateId));
191             }
192             else if (_warCustom.containsKey(layoutTemplateId)) {
193                 customLayoutTemplates.add(_warCustom.get(layoutTemplateId));
194             }
195             else {
196                 customLayoutTemplates.add(layoutTemplate);
197             }
198         }
199 
200         itr = _warCustom.entrySet().iterator();
201 
202         while (itr.hasNext()) {
203             Map.Entry<String, LayoutTemplate> entry = itr.next();
204 
205             String layoutTemplateId = entry.getKey();
206 
207             if (!_portalCustom.containsKey(layoutTemplateId) &&
208                 !_themesCustom.containsKey(layoutTemplateId)) {
209 
210                 customLayoutTemplates.add(_warCustom.get(layoutTemplateId));
211             }
212         }
213 
214         itr = _themesCustom.entrySet().iterator();
215 
216         while (itr.hasNext()) {
217             Map.Entry<String, LayoutTemplate> entry = itr.next();
218 
219             String layoutTemplateId = entry.getKey();
220 
221             if (!_portalCustom.containsKey(layoutTemplateId) &&
222                 !_warCustom.containsKey(layoutTemplateId)) {
223 
224                 customLayoutTemplates.add(_themesCustom.get(layoutTemplateId));
225             }
226         }
227 
228         return customLayoutTemplates;
229     }
230 
231     public String getWapContent(
232             String layoutTemplateId, boolean standard, String themeId)
233         throws SystemException {
234 
235         LayoutTemplate layoutTemplate = getLayoutTemplate(
236             layoutTemplateId, standard, themeId);
237 
238         if (layoutTemplate == null) {
239             if (_log.isWarnEnabled()) {
240                 _log.warn(
241                     "Layout template " + layoutTemplateId + " does not exist");
242             }
243 
244             layoutTemplate = getLayoutTemplate(
245                 PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID, standard, themeId);
246 
247             if (layoutTemplate == null) {
248                 _log.error(
249                     "Layout template " + layoutTemplateId +
250                         " and default layout template " +
251                             PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
252                                 " do not exist");
253 
254                 return StringPool.BLANK;
255             }
256         }
257 
258         if (PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
259             return layoutTemplate.getWapContent();
260         }
261         else {
262             try {
263                 return layoutTemplate.getUncachedWapContent();
264             }
265             catch (IOException ioe) {
266                 throw new SystemException(ioe);
267             }
268         }
269     }
270 
271     public List<ObjectValuePair<String, Boolean>> init(
272         ServletContext servletContext, String[] xmls,
273         PluginPackage pluginPackage) {
274 
275         return init(null, servletContext, xmls, pluginPackage);
276     }
277 
278     public List<ObjectValuePair<String, Boolean>> init(
279         String servletContextName, ServletContext servletContext, String[] xmls,
280         PluginPackage pluginPackage) {
281 
282         List<ObjectValuePair<String, Boolean>> layoutTemplateIds =
283             new ArrayList<ObjectValuePair<String, Boolean>>();
284 
285         try {
286             for (int i = 0; i < xmls.length; i++) {
287                 Set<ObjectValuePair<String, Boolean>> curLayoutTemplateIds =
288                     _readLayoutTemplates(
289                         servletContextName, servletContext, xmls[i],
290                         pluginPackage);
291 
292                 Iterator<ObjectValuePair<String, Boolean>> itr =
293                     curLayoutTemplateIds.iterator();
294 
295                 while (itr.hasNext()) {
296                     ObjectValuePair<String, Boolean> ovp = itr.next();
297 
298                     if (!layoutTemplateIds.contains(ovp)) {
299                         layoutTemplateIds.add(ovp);
300                     }
301                 }
302             }
303         }
304         catch (Exception e) {
305             _log.error(e, e);
306         }
307 
308         return layoutTemplateIds;
309     }
310 
311     public void readLayoutTemplate(
312         String servletContextName, ServletContext servletContext,
313         Set<ObjectValuePair<String, Boolean>> layoutTemplateIds,
314         com.liferay.portal.kernel.xml.Element el, boolean standard,
315         String themeId, PluginPackage pluginPackage) {
316 
317         Map<String, LayoutTemplate> layoutTemplates = null;
318 
319         if (themeId != null) {
320             if (standard) {
321                 layoutTemplates = _getThemesStandard(themeId);
322             }
323             else {
324                 layoutTemplates = _getThemesCustom(themeId);
325             }
326         }
327         else if (servletContextName != null) {
328             if (standard) {
329                 layoutTemplates = _warStandard;
330             }
331             else {
332                 layoutTemplates = _warCustom;
333             }
334         }
335         else {
336             if (standard) {
337                 layoutTemplates = _portalStandard;
338             }
339             else {
340                 layoutTemplates = _portalCustom;
341             }
342         }
343 
344         Iterator<com.liferay.portal.kernel.xml.Element> itr = el.elements(
345             "layout-template").iterator();
346 
347         while (itr.hasNext()) {
348             com.liferay.portal.kernel.xml.Element layoutTemplate = itr.next();
349 
350             String layoutTemplateId = layoutTemplate.attributeValue("id");
351 
352             if (layoutTemplateIds != null) {
353                 ObjectValuePair<String, Boolean> ovp =
354                     new ObjectValuePair<String, Boolean>(
355                         layoutTemplateId, standard);
356 
357                 layoutTemplateIds.add(ovp);
358             }
359 
360             LayoutTemplate layoutTemplateModel = layoutTemplates.get(
361                 layoutTemplateId);
362 
363             if (layoutTemplateModel == null) {
364                 layoutTemplateModel = new LayoutTemplateImpl(layoutTemplateId);
365 
366                 layoutTemplates.put(layoutTemplateId, layoutTemplateModel);
367             }
368 
369             PluginSetting pluginSetting =
370                 PluginSettingLocalServiceUtil.getDefaultPluginSetting();
371 
372             layoutTemplateModel.setPluginPackage(pluginPackage);
373             layoutTemplateModel.setServletContext(servletContext);
374 
375             if (servletContextName != null) {
376                 layoutTemplateModel.setServletContextName(servletContextName);
377             }
378 
379             layoutTemplateModel.setStandard(standard);
380             layoutTemplateModel.setThemeId(themeId);
381             layoutTemplateModel.setName(GetterUtil.getString(
382                 layoutTemplate.attributeValue("name"),
383                 layoutTemplateModel.getName()));
384             layoutTemplateModel.setTemplatePath(GetterUtil.getString(
385                 layoutTemplate.elementText("template-path"),
386                 layoutTemplateModel.getTemplatePath()));
387             layoutTemplateModel.setWapTemplatePath(GetterUtil.getString(
388                 layoutTemplate.elementText("wap-template-path"),
389                 layoutTemplateModel.getWapTemplatePath()));
390             layoutTemplateModel.setThumbnailPath(GetterUtil.getString(
391                 layoutTemplate.elementText("thumbnail-path"),
392                 layoutTemplateModel.getThumbnailPath()));
393 
394             String content = null;
395 
396             try {
397                 content = HttpUtil.URLtoString(servletContext.getResource(
398                     layoutTemplateModel.getTemplatePath()));
399             }
400             catch (Exception e) {
401                 _log.error(
402                     "Unable to get content at template path " +
403                         layoutTemplateModel.getTemplatePath() + ": " +
404                             e.getMessage());
405             }
406 
407             if (Validator.isNull(content)) {
408                 _log.error(
409                     "No content found at template path " +
410                         layoutTemplateModel.getTemplatePath());
411             }
412             else {
413                 StringBuilder sb = new StringBuilder();
414 
415                 sb.append(themeId);
416 
417                 if (standard) {
418                     sb.append(LayoutTemplateConstants.STANDARD_SEPARATOR);
419                 }
420                 else {
421                     sb.append(LayoutTemplateConstants.CUSTOM_SEPARATOR);
422                 }
423 
424                 sb.append(layoutTemplateId);
425 
426                 String velocityTemplateId = sb.toString();
427 
428                 layoutTemplateModel.setContent(content);
429                 layoutTemplateModel.setColumns(
430                     _getColumns(velocityTemplateId, content));
431             }
432 
433             if (Validator.isNull(layoutTemplateModel.getWapTemplatePath())) {
434                 _log.error(
435                     "The element wap-template-path is not defined for " +
436                         layoutTemplateId);
437             }
438             else {
439                 String wapContent = null;
440 
441                 try {
442                     wapContent = HttpUtil.URLtoString(
443                         servletContext.getResource(
444                             layoutTemplateModel.getWapTemplatePath()));
445                 }
446                 catch (Exception e) {
447                     _log.error(
448                         "Unable to get content at WAP template path " +
449                             layoutTemplateModel.getWapTemplatePath() + ": " +
450                                 e.getMessage());
451                 }
452 
453                 if (Validator.isNull(wapContent)) {
454                     _log.error(
455                         "No content found at WAP template path " +
456                             layoutTemplateModel.getWapTemplatePath());
457                 }
458                 else {
459                     layoutTemplateModel.setWapContent(wapContent);
460                 }
461             }
462 
463             com.liferay.portal.kernel.xml.Element rolesEl =
464                 layoutTemplate.element("roles");
465 
466             if (rolesEl != null) {
467                 Iterator<com.liferay.portal.kernel.xml.Element> itr2 =
468                     rolesEl.elements("role-name").iterator();
469 
470                 while (itr2.hasNext()) {
471                     com.liferay.portal.kernel.xml.Element roleNameEl =
472                         itr2.next();
473 
474                     pluginSetting.addRole(roleNameEl.getText());
475                 }
476             }
477 
478             layoutTemplateModel.setDefaultPluginSetting(pluginSetting);
479         }
480     }
481 
482     public void uninstallLayoutTemplate(
483         String layoutTemplateId, boolean standard) {
484 
485         if (standard) {
486             VelocityEngineUtil.flushTemplate(
487                 "null" + LayoutTemplateConstants.STANDARD_SEPARATOR +
488                     layoutTemplateId);
489 
490             _warStandard.remove(layoutTemplateId);
491         }
492         else {
493             VelocityEngineUtil.flushTemplate(
494                 "null" + LayoutTemplateConstants.CUSTOM_SEPARATOR +
495                     layoutTemplateId);
496 
497             _warCustom.remove(layoutTemplateId);
498         }
499     }
500 
501     public void uninstallLayoutTemplates(String themeId) {
502         Map<String, LayoutTemplate> _themesStandard =
503             _getThemesStandard(themeId);
504 
505         for (Map.Entry<String, LayoutTemplate> entry :
506                 _themesStandard.entrySet()) {
507 
508             LayoutTemplate layoutTemplate = entry.getValue();
509 
510             VelocityEngineUtil.flushTemplate(
511                 themeId + LayoutTemplateConstants.STANDARD_SEPARATOR +
512                     layoutTemplate.getLayoutTemplateId());
513         }
514 
515         _themesStandard.clear();
516 
517         Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
518 
519         for (Map.Entry<String, LayoutTemplate> entry :
520                 _themesCustom.entrySet()) {
521 
522             LayoutTemplate layoutTemplate = entry.getValue();
523 
524             VelocityEngineUtil.flushTemplate(
525                 themeId + LayoutTemplateConstants.CUSTOM_SEPARATOR +
526                     layoutTemplate.getLayoutTemplateId());
527         }
528 
529         _themesCustom.clear();
530     }
531 
532     private List<String> _getColumns(
533         String velocityTemplateId, String velocityTemplateContent) {
534 
535         try {
536             InitColumnProcessor processor = new InitColumnProcessor();
537 
538             VelocityContext velocityContext =
539                 VelocityEngineUtil.getStandardToolsContext();
540 
541             velocityContext.put("processor", processor);
542 
543             VelocityEngineUtil.mergeTemplate(
544                 velocityTemplateId, velocityTemplateContent, velocityContext,
545                 new PrintWriter(new StringWriter()));
546 
547             return ListUtil.sort(processor.getColumns());
548         }
549         catch (Exception e) {
550             _log.error(e);
551 
552             return new ArrayList<String>();
553         }
554     }
555 
556     private Set<ObjectValuePair<String, Boolean>> _readLayoutTemplates(
557             String servletContextName, ServletContext servletContext,
558             String xml, PluginPackage pluginPackage)
559         throws Exception {
560 
561         Set<ObjectValuePair<String, Boolean>> layoutTemplateIds =
562             new HashSet<ObjectValuePair<String, Boolean>>();
563 
564         if (xml == null) {
565             return layoutTemplateIds;
566         }
567 
568         Document doc = SAXReaderUtil.read(xml, true);
569 
570         Element root = doc.getRootElement();
571 
572         Element standardEl = root.element("standard");
573 
574         if (standardEl != null) {
575             readLayoutTemplate(
576                 servletContextName, servletContext, layoutTemplateIds,
577                 standardEl, true, null, pluginPackage);
578         }
579 
580         Element customEl = root.element("custom");
581 
582         if (customEl != null) {
583             readLayoutTemplate(
584                 servletContextName, servletContext, layoutTemplateIds,
585                 customEl, false, null, pluginPackage);
586         }
587 
588         return layoutTemplateIds;
589     }
590 
591     private Map<String, LayoutTemplate> _getThemesCustom(String themeId) {
592         String key = themeId + LayoutTemplateConstants.CUSTOM_SEPARATOR;
593 
594         Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
595 
596         if (layoutTemplates == null) {
597             layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
598 
599             _themes.put(key, layoutTemplates);
600         }
601 
602         return layoutTemplates;
603     }
604 
605     private Map<String, LayoutTemplate> _getThemesStandard(String themeId) {
606         String key = themeId + LayoutTemplateConstants.STANDARD_SEPARATOR;
607 
608         Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
609 
610         if (layoutTemplates == null) {
611             layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
612 
613             _themes.put(key, layoutTemplates);
614         }
615 
616         return layoutTemplates;
617     }
618 
619     private static Log _log =
620         LogFactoryUtil.getLog(LayoutTemplateLocalServiceImpl.class);
621 
622     private static Map<String, LayoutTemplate> _portalStandard =
623         new LinkedHashMap<String, LayoutTemplate>();
624     private static Map<String, LayoutTemplate> _portalCustom =
625         new LinkedHashMap<String, LayoutTemplate>();
626 
627     private static Map<String, LayoutTemplate> _warStandard =
628         new LinkedHashMap<String, LayoutTemplate>();
629     private static Map<String, LayoutTemplate> _warCustom =
630         new LinkedHashMap<String, LayoutTemplate>();
631 
632     private static Map<String, Map<String, LayoutTemplate>> _themes =
633         new LinkedHashMap<String, Map<String, LayoutTemplate>>();
634 
635 }