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