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