001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.io.DummyWriter;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.plugin.PluginPackage;
022    import com.liferay.portal.kernel.template.StringTemplateResource;
023    import com.liferay.portal.kernel.template.Template;
024    import com.liferay.portal.kernel.template.TemplateContextType;
025    import com.liferay.portal.kernel.template.TemplateManager;
026    import com.liferay.portal.kernel.template.TemplateManagerUtil;
027    import com.liferay.portal.kernel.template.TemplateResourceLoaderUtil;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.HttpUtil;
030    import com.liferay.portal.kernel.util.ListUtil;
031    import com.liferay.portal.kernel.util.ObjectValuePair;
032    import com.liferay.portal.kernel.util.StringBundler;
033    import com.liferay.portal.kernel.util.StringPool;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.kernel.xml.Document;
036    import com.liferay.portal.kernel.xml.Element;
037    import com.liferay.portal.kernel.xml.SAXReaderUtil;
038    import com.liferay.portal.model.LayoutTemplate;
039    import com.liferay.portal.model.LayoutTemplateConstants;
040    import com.liferay.portal.model.PluginSetting;
041    import com.liferay.portal.model.impl.LayoutTemplateImpl;
042    import com.liferay.portal.service.base.LayoutTemplateLocalServiceBaseImpl;
043    import com.liferay.portal.util.PropsValues;
044    import com.liferay.portlet.layoutconfiguration.util.velocity.InitColumnProcessor;
045    
046    import java.io.IOException;
047    
048    import java.util.ArrayList;
049    import java.util.HashSet;
050    import java.util.LinkedHashMap;
051    import java.util.List;
052    import java.util.Map;
053    import java.util.Set;
054    
055    import javax.servlet.ServletContext;
056    
057    /**
058     * @author Ivica Cardic
059     * @author Jorge Ferrer
060     * @author Brian Wing Shun Chan
061     * @author Raymond Augé
062     */
063    public class LayoutTemplateLocalServiceImpl
064            extends LayoutTemplateLocalServiceBaseImpl {
065    
066            public String getContent(
067                            String layoutTemplateId, boolean standard, String themeId)
068                    throws SystemException {
069    
070                    LayoutTemplate layoutTemplate = getLayoutTemplate(
071                            layoutTemplateId, standard, themeId);
072    
073                    if (layoutTemplate == null) {
074                            if (_log.isWarnEnabled()) {
075                                    _log.warn(
076                                            "Layout template " + layoutTemplateId + " does not exist");
077                            }
078    
079                            layoutTemplate = getLayoutTemplate(
080                                    PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID, standard, themeId);
081    
082                            if (layoutTemplate == null) {
083                                    _log.error(
084                                            "Layout template " + layoutTemplateId +
085                                                    " and default layout template " +
086                                                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
087                                                                    " do not exist");
088    
089                                    return StringPool.BLANK;
090                            }
091                    }
092    
093                    if (PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
094                            return layoutTemplate.getContent();
095                    }
096                    else {
097                            try {
098                                    return layoutTemplate.getUncachedContent();
099                            }
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(ListUtil.fromMapValues(_portalCustom));
154                    customLayoutTemplates.addAll(ListUtil.fromMapValues(_warCustom));
155    
156                    return customLayoutTemplates;
157            }
158    
159            public List<LayoutTemplate> getLayoutTemplates(String themeId) {
160                    Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
161    
162                    List<LayoutTemplate> customLayoutTemplates =
163                            new ArrayList<LayoutTemplate>(
164                                    _portalCustom.size() + _warCustom.size() +
165                                            _themesCustom.size());
166    
167                    for (Map.Entry<String, LayoutTemplate> entry :
168                                    _portalCustom.entrySet()) {
169    
170                            String layoutTemplateId = entry.getKey();
171                            LayoutTemplate layoutTemplate = entry.getValue();
172    
173                            LayoutTemplate themeCustomLayoutTemplate = _themesCustom.get(
174                                    layoutTemplateId);
175    
176                            if (themeCustomLayoutTemplate != null) {
177                                    customLayoutTemplates.add(themeCustomLayoutTemplate);
178                            }
179                            else {
180                                    LayoutTemplate warCustomLayoutTemplate = _warCustom.get(
181                                            layoutTemplateId);
182    
183                                    if (warCustomLayoutTemplate != null) {
184                                            customLayoutTemplates.add(warCustomLayoutTemplate);
185                                    }
186                                    else {
187                                            customLayoutTemplates.add(layoutTemplate);
188                                    }
189                            }
190                    }
191    
192                    for (Map.Entry<String, LayoutTemplate> entry : _warCustom.entrySet()) {
193                            String layoutTemplateId = entry.getKey();
194    
195                            if (!_portalCustom.containsKey(layoutTemplateId) &&
196                                    !_themesCustom.containsKey(layoutTemplateId)) {
197    
198                                    customLayoutTemplates.add(_warCustom.get(layoutTemplateId));
199                            }
200                    }
201    
202                    for (Map.Entry<String, LayoutTemplate> entry :
203                                    _themesCustom.entrySet()) {
204    
205                            String layoutTemplateId = entry.getKey();
206    
207                            if (!_portalCustom.containsKey(layoutTemplateId) &&
208                                    !_warCustom.containsKey(layoutTemplateId)) {
209    
210                                    customLayoutTemplates.add(_themesCustom.get(layoutTemplateId));
211                            }
212                    }
213    
214                    return customLayoutTemplates;
215            }
216    
217            public String getWapContent(
218                            String layoutTemplateId, boolean standard, String themeId)
219                    throws SystemException {
220    
221                    LayoutTemplate layoutTemplate = getLayoutTemplate(
222                            layoutTemplateId, standard, themeId);
223    
224                    if (layoutTemplate == null) {
225                            if (_log.isWarnEnabled()) {
226                                    _log.warn(
227                                            "Layout template " + layoutTemplateId + " does not exist");
228                            }
229    
230                            layoutTemplate = getLayoutTemplate(
231                                    PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID, standard, themeId);
232    
233                            if (layoutTemplate == null) {
234                                    _log.error(
235                                            "Layout template " + layoutTemplateId +
236                                                    " and default layout template " +
237                                                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
238                                                                    " do not exist");
239    
240                                    return StringPool.BLANK;
241                            }
242                    }
243    
244                    if (PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
245                            return layoutTemplate.getWapContent();
246                    }
247                    else {
248                            try {
249                                    return layoutTemplate.getUncachedWapContent();
250                            }
251                            catch (IOException ioe) {
252                                    throw new SystemException(ioe);
253                            }
254                    }
255            }
256    
257            public List<ObjectValuePair<String, Boolean>> init(
258                    ServletContext servletContext, String[] xmls,
259                    PluginPackage pluginPackage) {
260    
261                    return init(null, servletContext, xmls, pluginPackage);
262            }
263    
264            public List<ObjectValuePair<String, Boolean>> init(
265                    String servletContextName, ServletContext servletContext, String[] xmls,
266                    PluginPackage pluginPackage) {
267    
268                    List<ObjectValuePair<String, Boolean>> layoutTemplateIdOVPs =
269                            new ArrayList<ObjectValuePair<String, Boolean>>();
270    
271                    try {
272                            for (int i = 0; i < xmls.length; i++) {
273                                    Set<ObjectValuePair<String, Boolean>> curLayoutTemplateIdOVPs =
274                                            _readLayoutTemplates(
275                                                    servletContextName, servletContext, xmls[i],
276                                                    pluginPackage);
277    
278                                    for (ObjectValuePair<String, Boolean> layoutTemplateIdOVP :
279                                                    curLayoutTemplateIdOVPs) {
280    
281                                            if (!layoutTemplateIdOVPs.contains(layoutTemplateIdOVP)) {
282                                                    layoutTemplateIdOVPs.add(layoutTemplateIdOVP);
283                                            }
284                                    }
285                            }
286                    }
287                    catch (Exception e) {
288                            _log.error(e, e);
289                    }
290    
291                    return layoutTemplateIdOVPs;
292            }
293    
294            public void readLayoutTemplate(
295                    String servletContextName, ServletContext servletContext,
296                    Set<ObjectValuePair<String, Boolean>> layoutTemplateIdOVPs,
297                    Element element, boolean standard, String themeId,
298                    PluginPackage pluginPackage) {
299    
300                    Map<String, LayoutTemplate> layoutTemplates = null;
301    
302                    if (themeId != null) {
303                            if (standard) {
304                                    layoutTemplates = _getThemesStandard(themeId);
305                            }
306                            else {
307                                    layoutTemplates = _getThemesCustom(themeId);
308                            }
309                    }
310                    else if (servletContextName != null) {
311                            if (standard) {
312                                    layoutTemplates = _warStandard;
313                            }
314                            else {
315                                    layoutTemplates = _warCustom;
316                            }
317                    }
318                    else {
319                            if (standard) {
320                                    layoutTemplates = _portalStandard;
321                            }
322                            else {
323                                    layoutTemplates = _portalCustom;
324                            }
325                    }
326    
327                    List<Element> layoutTemplateElements = element.elements(
328                            "layout-template");
329    
330                    for (Element layoutTemplateElement : layoutTemplateElements) {
331                            String layoutTemplateId = layoutTemplateElement.attributeValue(
332                                    "id");
333    
334                            if (layoutTemplateIdOVPs != null) {
335                                    ObjectValuePair<String, Boolean> layoutTemplateIdOVP =
336                                            new ObjectValuePair<String, Boolean>(
337                                                    layoutTemplateId, standard);
338    
339                                    layoutTemplateIdOVPs.add(layoutTemplateIdOVP);
340                            }
341    
342                            LayoutTemplate layoutTemplateModel = layoutTemplates.get(
343                                    layoutTemplateId);
344    
345                            if (layoutTemplateModel == null) {
346                                    layoutTemplateModel = new LayoutTemplateImpl(layoutTemplateId);
347    
348                                    layoutTemplates.put(layoutTemplateId, layoutTemplateModel);
349                            }
350    
351                            PluginSetting pluginSetting =
352                                    pluginSettingLocalService.getDefaultPluginSetting();
353    
354                            layoutTemplateModel.setPluginPackage(pluginPackage);
355                            layoutTemplateModel.setServletContext(servletContext);
356    
357                            if (servletContextName != null) {
358                                    layoutTemplateModel.setServletContextName(servletContextName);
359                            }
360    
361                            layoutTemplateModel.setStandard(standard);
362                            layoutTemplateModel.setThemeId(themeId);
363                            layoutTemplateModel.setName(
364                                    GetterUtil.getString(
365                                            layoutTemplateElement.attributeValue("name"),
366                                            layoutTemplateModel.getName()));
367                            layoutTemplateModel.setTemplatePath(
368                                    GetterUtil.getString(
369                                            layoutTemplateElement.elementText("template-path"),
370                                            layoutTemplateModel.getTemplatePath()));
371                            layoutTemplateModel.setWapTemplatePath(
372                                    GetterUtil.getString(
373                                            layoutTemplateElement.elementText("wap-template-path"),
374                                            layoutTemplateModel.getWapTemplatePath()));
375                            layoutTemplateModel.setThumbnailPath(
376                                    GetterUtil.getString(
377                                            layoutTemplateElement.elementText("thumbnail-path"),
378                                            layoutTemplateModel.getThumbnailPath()));
379    
380                            String content = null;
381    
382                            try {
383                                    content = HttpUtil.URLtoString(
384                                            servletContext.getResource(
385                                                    layoutTemplateModel.getTemplatePath()));
386                            }
387                            catch (Exception e) {
388                                    _log.error(
389                                            "Unable to get content at template path " +
390                                                    layoutTemplateModel.getTemplatePath() + ": " +
391                                                            e.getMessage());
392                            }
393    
394                            if (Validator.isNull(content)) {
395                                    _log.error(
396                                            "No content found at template path " +
397                                                    layoutTemplateModel.getTemplatePath());
398                            }
399                            else {
400                                    StringBundler sb = new StringBundler(3);
401    
402                                    sb.append(themeId);
403    
404                                    if (standard) {
405                                            sb.append(LayoutTemplateConstants.STANDARD_SEPARATOR);
406                                    }
407                                    else {
408                                            sb.append(LayoutTemplateConstants.CUSTOM_SEPARATOR);
409                                    }
410    
411                                    sb.append(layoutTemplateId);
412    
413                                    String velocityTemplateId = sb.toString();
414    
415                                    layoutTemplateModel.setContent(content);
416                                    layoutTemplateModel.setColumns(
417                                            _getColumns(velocityTemplateId, content));
418                            }
419    
420                            if (Validator.isNull(layoutTemplateModel.getWapTemplatePath())) {
421                                    _log.error(
422                                            "The element wap-template-path is not defined for " +
423                                                    layoutTemplateId);
424                            }
425                            else {
426                                    String wapContent = null;
427    
428                                    try {
429                                            wapContent = HttpUtil.URLtoString(
430                                                    servletContext.getResource(
431                                                            layoutTemplateModel.getWapTemplatePath()));
432                                    }
433                                    catch (Exception e) {
434                                            _log.error(
435                                                    "Unable to get content at WAP template path " +
436                                                            layoutTemplateModel.getWapTemplatePath() + ": " +
437                                                                    e.getMessage());
438                                    }
439    
440                                    if (Validator.isNull(wapContent)) {
441                                            _log.error(
442                                                    "No content found at WAP template path " +
443                                                            layoutTemplateModel.getWapTemplatePath());
444                                    }
445                                    else {
446                                            layoutTemplateModel.setWapContent(wapContent);
447                                    }
448                            }
449    
450                            Element rolesElement = layoutTemplateElement.element("roles");
451    
452                            if (rolesElement != null) {
453                                    List<Element> roleNameElements = rolesElement.elements(
454                                            "role-name");
455    
456                                    for (Element roleNameElement : roleNameElements) {
457                                            pluginSetting.addRole(roleNameElement.getText());
458                                    }
459                            }
460    
461                            layoutTemplateModel.setDefaultPluginSetting(pluginSetting);
462                    }
463            }
464    
465            public void uninstallLayoutTemplate(
466                    String layoutTemplateId, boolean standard) {
467    
468                    String templateId = null;
469    
470                    try {
471                            if (standard) {
472                                    templateId =
473                                            "null" + LayoutTemplateConstants.STANDARD_SEPARATOR +
474                                                    layoutTemplateId;
475    
476                                    TemplateResourceLoaderUtil.clearCache(
477                                            TemplateManager.VELOCITY, templateId);
478    
479                                    _warStandard.remove(layoutTemplateId);
480                            }
481                            else {
482                                    templateId =
483                                            "null" + LayoutTemplateConstants.CUSTOM_SEPARATOR +
484                                                    layoutTemplateId;
485    
486                                    TemplateResourceLoaderUtil.clearCache(
487                                            TemplateManager.VELOCITY, templateId);
488    
489                                    _warCustom.remove(layoutTemplateId);
490                            }
491                    }
492                    catch (Exception e) {
493                            _log.error(
494                                    "Unable to uninstall layout template " + layoutTemplateId, e);
495                    }
496            }
497    
498            public void uninstallLayoutTemplates(String themeId) {
499                    Map<String, LayoutTemplate> _themesStandard = _getThemesStandard(
500                            themeId);
501    
502                    for (Map.Entry<String, LayoutTemplate> entry :
503                                    _themesStandard.entrySet()) {
504    
505                            LayoutTemplate layoutTemplate = entry.getValue();
506    
507                            String templateId =
508                                    themeId + LayoutTemplateConstants.STANDARD_SEPARATOR +
509                                            layoutTemplate.getLayoutTemplateId();
510    
511                            try {
512                                    TemplateResourceLoaderUtil.clearCache(
513                                            TemplateManager.VELOCITY, templateId);
514                            }
515                            catch (Exception e) {
516                                    _log.error(
517                                            "Unable to uninstall layout template " +
518                                                    layoutTemplate.getLayoutTemplateId(),
519                                            e);
520                            }
521                    }
522    
523                    _themesStandard.clear();
524    
525                    Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
526    
527                    for (Map.Entry<String, LayoutTemplate> entry :
528                                    _themesCustom.entrySet()) {
529    
530                            LayoutTemplate layoutTemplate = entry.getValue();
531    
532                            String templateId =
533                                    themeId + LayoutTemplateConstants.CUSTOM_SEPARATOR +
534                                            layoutTemplate.getLayoutTemplateId();
535    
536                            try {
537                                    TemplateResourceLoaderUtil.clearCache(
538                                            TemplateManager.VELOCITY, templateId);
539                            }
540                            catch (Exception e) {
541                                    _log.error(
542                                            "Unable to uninstall layout template " +
543                                                    layoutTemplate.getLayoutTemplateId(),
544                                            e);
545                            }
546                    }
547    
548                    _themesCustom.clear();
549            }
550    
551            private List<String> _getColumns(
552                    String velocityTemplateId, String velocityTemplateContent) {
553    
554                    try {
555                            InitColumnProcessor processor = new InitColumnProcessor();
556    
557                            Template template = TemplateManagerUtil.getTemplate(
558                                    TemplateManager.VELOCITY,
559                                    new StringTemplateResource(
560                                            velocityTemplateId, velocityTemplateContent),
561                                    TemplateContextType.STANDARD);
562    
563                            template.put("processor", processor);
564    
565                            template.processTemplate(new DummyWriter());
566    
567                            return ListUtil.sort(processor.getColumns());
568                    }
569                    catch (Exception e) {
570                            _log.error(e);
571    
572                            return new ArrayList<String>();
573                    }
574            }
575    
576            private Map<String, LayoutTemplate> _getThemesCustom(String themeId) {
577                    String key = themeId.concat(LayoutTemplateConstants.CUSTOM_SEPARATOR);
578    
579                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
580    
581                    if (layoutTemplates == null) {
582                            layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
583    
584                            _themes.put(key, layoutTemplates);
585                    }
586    
587                    return layoutTemplates;
588            }
589    
590            private Map<String, LayoutTemplate> _getThemesStandard(String themeId) {
591                    String key = themeId + LayoutTemplateConstants.STANDARD_SEPARATOR;
592    
593                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
594    
595                    if (layoutTemplates == null) {
596                            layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
597    
598                            _themes.put(key, layoutTemplates);
599                    }
600    
601                    return layoutTemplates;
602            }
603    
604            private Set<ObjectValuePair<String, Boolean>> _readLayoutTemplates(
605                            String servletContextName, ServletContext servletContext,
606                            String xml, PluginPackage pluginPackage)
607                    throws Exception {
608    
609                    Set<ObjectValuePair<String, Boolean>> layoutTemplateIdOVPs =
610                            new HashSet<ObjectValuePair<String, Boolean>>();
611    
612                    if (xml == null) {
613                            return layoutTemplateIdOVPs;
614                    }
615    
616                    Document document = SAXReaderUtil.read(xml, true);
617    
618                    Element rootElement = document.getRootElement();
619    
620                    Element standardElement = rootElement.element("standard");
621    
622                    if (standardElement != null) {
623                            readLayoutTemplate(
624                                    servletContextName, servletContext, layoutTemplateIdOVPs,
625                                    standardElement, true, null, pluginPackage);
626                    }
627    
628                    Element customElement = rootElement.element("custom");
629    
630                    if (customElement != null) {
631                            readLayoutTemplate(
632                                    servletContextName, servletContext, layoutTemplateIdOVPs,
633                                    customElement, false, null, pluginPackage);
634                    }
635    
636                    return layoutTemplateIdOVPs;
637            }
638    
639            private static Log _log = LogFactoryUtil.getLog(
640                    LayoutTemplateLocalServiceImpl.class);
641    
642            private static Map<String, LayoutTemplate> _portalCustom =
643                    new LinkedHashMap<String, LayoutTemplate>();
644            private static Map<String, LayoutTemplate> _portalStandard =
645                    new LinkedHashMap<String, LayoutTemplate>();
646    
647            private static Map<String, Map<String, LayoutTemplate>> _themes =
648                    new LinkedHashMap<String, Map<String, LayoutTemplate>>();
649    
650            private static Map<String, LayoutTemplate> _warCustom =
651                    new LinkedHashMap<String, LayoutTemplate>();
652            private static Map<String, LayoutTemplate> _warStandard =
653                    new LinkedHashMap<String, LayoutTemplate>();
654    
655    }