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