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