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.kernel.xml.Document;
34  import com.liferay.portal.kernel.xml.Element;
35  import com.liferay.portal.kernel.xml.SAXReaderUtil;
36  import com.liferay.portal.model.LayoutTemplate;
37  import com.liferay.portal.model.PluginSetting;
38  import com.liferay.portal.model.impl.LayoutTemplateImpl;
39  import com.liferay.portal.service.PluginSettingLocalServiceUtil;
40  import com.liferay.portal.service.base.LayoutTemplateLocalServiceBaseImpl;
41  import com.liferay.portal.util.PropsValues;
42  import com.liferay.portlet.layoutconfiguration.util.velocity.InitColumnProcessor;
43  
44  import java.io.IOException;
45  import java.io.PrintWriter;
46  import java.io.StringWriter;
47  
48  import java.util.ArrayList;
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  /**
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   *
71  */
72  public class LayoutTemplateLocalServiceImpl
73      extends LayoutTemplateLocalServiceBaseImpl {
74  
75      public 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_LAYOUT_TEMPLATE_ID, standard, themeId);
90  
91              if (layoutTemplate == null) {
92                  _log.error(
93                      "Layout template " + layoutTemplateId +
94                          " and default layout template " +
95                              PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
96                                  " do 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 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 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 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 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_LAYOUT_TEMPLATE_ID, standard, themeId);
245 
246             if (layoutTemplate == null) {
247                 _log.error(
248                     "Layout template " + layoutTemplateId +
249                         " and default layout template " +
250                             PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
251                                 " do not exist");
252 
253                 return StringPool.BLANK;
254             }
255         }
256 
257         if (PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
258             return layoutTemplate.getWapContent();
259         }
260         else {
261             try {
262                 return layoutTemplate.getUncachedWapContent();
263             }
264             catch (IOException ioe) {
265                 throw new SystemException(ioe);
266             }
267         }
268     }
269 
270     public List<ObjectValuePair<String, Boolean>> init(
271         ServletContext servletContext, String[] xmls,
272         PluginPackage pluginPackage) {
273 
274         return init(null, servletContext, xmls, pluginPackage);
275     }
276 
277     public List<ObjectValuePair<String, Boolean>> init(
278         String servletContextName, ServletContext servletContext, String[] xmls,
279         PluginPackage pluginPackage) {
280 
281         List<ObjectValuePair<String, Boolean>> layoutTemplateIds =
282             new ArrayList<ObjectValuePair<String, Boolean>>();
283 
284         try {
285             for (int i = 0; i < xmls.length; i++) {
286                 Set<ObjectValuePair<String, Boolean>> curLayoutTemplateIds =
287                     _readLayoutTemplates(
288                         servletContextName, servletContext, xmls[i],
289                         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             _log.error(e, e);
305         }
306 
307         return layoutTemplateIds;
308     }
309 
310     public void readLayoutTemplate(
311         String servletContextName, ServletContext servletContext,
312         Set<ObjectValuePair<String, Boolean>> layoutTemplateIds,
313         com.liferay.portal.kernel.xml.Element el, boolean standard,
314         String themeId, PluginPackage pluginPackage) {
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<com.liferay.portal.kernel.xml.Element> itr = el.elements(
344             "layout-template").iterator();
345 
346         while (itr.hasNext()) {
347             com.liferay.portal.kernel.xml.Element layoutTemplate = itr.next();
348 
349             String layoutTemplateId = layoutTemplate.attributeValue("id");
350 
351             if (layoutTemplateIds != null) {
352                 ObjectValuePair<String, Boolean> ovp =
353                     new ObjectValuePair<String, Boolean>(
354                         layoutTemplateId, standard);
355 
356                 layoutTemplateIds.add(ovp);
357             }
358 
359             LayoutTemplate layoutTemplateModel = layoutTemplates.get(
360                 layoutTemplateId);
361 
362             if (layoutTemplateModel == null) {
363                 layoutTemplateModel = new LayoutTemplateImpl(layoutTemplateId);
364 
365                 layoutTemplates.put(layoutTemplateId, layoutTemplateModel);
366             }
367 
368             PluginSetting pluginSetting =
369                 PluginSettingLocalServiceUtil.getDefaultPluginSetting();
370 
371             layoutTemplateModel.setPluginPackage(pluginPackage);
372             layoutTemplateModel.setServletContext(servletContext);
373 
374             if (servletContextName != null) {
375                 layoutTemplateModel.setServletContextName(servletContextName);
376             }
377 
378             layoutTemplateModel.setStandard(standard);
379             layoutTemplateModel.setName(GetterUtil.getString(
380                 layoutTemplate.attributeValue("name"),
381                 layoutTemplateModel.getName()));
382             layoutTemplateModel.setTemplatePath(GetterUtil.getString(
383                 layoutTemplate.elementText("template-path"),
384                 layoutTemplateModel.getTemplatePath()));
385             layoutTemplateModel.setWapTemplatePath(GetterUtil.getString(
386                 layoutTemplate.elementText("wap-template-path"),
387                 layoutTemplateModel.getWapTemplatePath()));
388             layoutTemplateModel.setThumbnailPath(GetterUtil.getString(
389                 layoutTemplate.elementText("thumbnail-path"),
390                 layoutTemplateModel.getThumbnailPath()));
391 
392             String content = null;
393 
394             try {
395                 content = HttpUtil.URLtoString(servletContext.getResource(
396                     layoutTemplateModel.getTemplatePath()));
397             }
398             catch (Exception e) {
399                 _log.error(
400                     "Unable to get content at template path " +
401                         layoutTemplateModel.getTemplatePath() + ": " +
402                             e.getMessage());
403             }
404 
405             if (Validator.isNull(content)) {
406                 _log.error(
407                     "No content found at template path " +
408                         layoutTemplateModel.getTemplatePath());
409             }
410             else {
411                 layoutTemplateModel.setContent(content);
412                 layoutTemplateModel.setColumns(_getColumns(content));
413             }
414 
415             if (Validator.isNull(layoutTemplateModel.getWapTemplatePath())) {
416                 _log.error(
417                     "The element wap-template-path is not defined for " +
418                         layoutTemplateId);
419             }
420             else {
421                 String wapContent = null;
422 
423                 try {
424                     wapContent = HttpUtil.URLtoString(
425                         servletContext.getResource(
426                             layoutTemplateModel.getWapTemplatePath()));
427                 }
428                 catch (Exception e) {
429                     _log.error(
430                         "Unable to get content at WAP template path " +
431                             layoutTemplateModel.getWapTemplatePath() + ": " +
432                                 e.getMessage());
433                 }
434 
435                 if (Validator.isNull(wapContent)) {
436                     _log.error(
437                         "No content found at WAP template path " +
438                             layoutTemplateModel.getWapTemplatePath());
439                 }
440                 else {
441                     layoutTemplateModel.setWapContent(wapContent);
442                 }
443             }
444 
445             com.liferay.portal.kernel.xml.Element rolesEl =
446                 layoutTemplate.element("roles");
447 
448             if (rolesEl != null) {
449                 Iterator<com.liferay.portal.kernel.xml.Element> itr2 =
450                     rolesEl.elements("role-name").iterator();
451 
452                 while (itr2.hasNext()) {
453                     com.liferay.portal.kernel.xml.Element roleNameEl =
454                         itr2.next();
455 
456                     pluginSetting.addRole(roleNameEl.getText());
457                 }
458             }
459 
460             layoutTemplateModel.setDefaultPluginSetting(pluginSetting);
461         }
462     }
463 
464     public void uninstallLayoutTemplate(
465         String layoutTemplateId, boolean standard) {
466 
467         if (standard) {
468             _warStandard.remove(layoutTemplateId);
469         }
470         else {
471             _warCustom.remove(layoutTemplateId);
472         }
473     }
474 
475     public void uninstallLayoutTemplates(String themeId) {
476         _getThemesStandard(themeId).clear();
477         _getThemesCustom(themeId).clear();
478     }
479 
480     private List<String> _getColumns(String content) {
481         try {
482             InitColumnProcessor processor = new InitColumnProcessor();
483 
484             VelocityContext context = new VelocityContext();
485 
486             context.put("processor", processor);
487 
488             Velocity.evaluate(
489                 context, new PrintWriter(new StringWriter()),
490                 LayoutTemplateLocalServiceImpl.class.getName(), content);
491 
492             return ListUtil.sort(processor.getColumns());
493         }
494         catch (Exception e) {
495             _log.error(e);
496 
497             return new ArrayList<String>();
498         }
499     }
500 
501     private Set<ObjectValuePair<String, Boolean>> _readLayoutTemplates(
502             String servletContextName, ServletContext servletContext,
503             String xml, PluginPackage pluginPackage)
504         throws Exception {
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 = SAXReaderUtil.read(xml, true);
514 
515         Element root = doc.getRootElement();
516 
517         Element standardEl = root.element("standard");
518 
519         if (standardEl != null) {
520             readLayoutTemplate(
521                 servletContextName, servletContext, layoutTemplateIds,
522                 standardEl, true, null, pluginPackage);
523         }
524 
525         Element customEl = root.element("custom");
526 
527         if (customEl != null) {
528             readLayoutTemplate(
529                 servletContextName, servletContext, layoutTemplateIds,
530                 customEl, false, null, pluginPackage);
531         }
532 
533         return layoutTemplateIds;
534     }
535 
536     private Map<String, LayoutTemplate> _getThemesCustom(String themeId) {
537         String key = themeId + _CUSTOM_SEPARATOR;
538 
539         Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
540 
541         if (layoutTemplates == null) {
542             layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
543 
544             _themes.put(key, layoutTemplates);
545         }
546 
547         return layoutTemplates;
548     }
549 
550     private Map<String, LayoutTemplate> _getThemesStandard(String themeId) {
551         String key = themeId + _STANDARD_SEPARATOR;
552 
553         Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
554 
555         if (layoutTemplates == null) {
556             layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
557 
558             _themes.put(key, layoutTemplates);
559         }
560 
561         return layoutTemplates;
562     }
563 
564     private static final String _STANDARD_SEPARATOR = "_STANDARD_";
565 
566     private static final String _CUSTOM_SEPARATOR = "_CUSTOM_";
567 
568     private static Log _log =
569         LogFactory.getLog(LayoutTemplateLocalServiceImpl.class);
570 
571     private static Map<String, LayoutTemplate> _portalStandard =
572         new LinkedHashMap<String, LayoutTemplate>();
573     private static Map<String, LayoutTemplate> _portalCustom =
574         new LinkedHashMap<String, LayoutTemplate>();
575 
576     private static Map<String, LayoutTemplate> _warStandard =
577         new LinkedHashMap<String, LayoutTemplate>();
578     private static Map<String, LayoutTemplate> _warCustom =
579         new LinkedHashMap<String, LayoutTemplate>();
580 
581     private static Map<String, Map<String, LayoutTemplate>> _themes =
582         new LinkedHashMap<String, Map<String, LayoutTemplate>>();
583 
584 }