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