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