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