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