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