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.UnsecureSAXReaderUtil;
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 = new ArrayList<>(
150                            _portalCustom.size() + _warCustom.size());
151    
152                    customLayoutTemplates.addAll(ListUtil.fromMapValues(_portalCustom));
153                    customLayoutTemplates.addAll(ListUtil.fromMapValues(_warCustom));
154    
155                    return customLayoutTemplates;
156            }
157    
158            @Override
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            @Override
218            public String getWapContent(
219                    String layoutTemplateId, boolean standard, String themeId) {
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    
248                    try {
249                            return layoutTemplate.getUncachedWapContent();
250                    }
251                    catch (IOException ioe) {
252                            throw new SystemException(ioe);
253                    }
254            }
255    
256            @Override
257            public List<LayoutTemplate> init(
258                    ServletContext servletContext, String[] xmls,
259                    PluginPackage pluginPackage) {
260    
261                    return init(null, servletContext, xmls, pluginPackage);
262            }
263    
264            @Override
265            public List<LayoutTemplate> init(
266                    String servletContextName, ServletContext servletContext, String[] xmls,
267                    PluginPackage pluginPackage) {
268    
269                    Set<LayoutTemplate> layoutTemplates = new LinkedHashSet<>();
270    
271                    try {
272                            for (String xml : xmls) {
273                                    layoutTemplates.addAll(
274                                            _readLayoutTemplates(
275                                                    servletContextName, servletContext, xml,
276                                                    pluginPackage));
277                            }
278                    }
279                    catch (Exception e) {
280                            _log.error(e, e);
281                    }
282    
283                    return new ArrayList<>(layoutTemplates);
284            }
285    
286            @Override
287            public void readLayoutTemplate(
288                    String servletContextName, ServletContext servletContext,
289                    Set<LayoutTemplate> layoutTemplates, Element element, boolean standard,
290                    String themeId, PluginPackage pluginPackage) {
291    
292                    Map<String, LayoutTemplate> installedLayoutTemplates = null;
293    
294                    if (themeId != null) {
295                            if (standard) {
296                                    installedLayoutTemplates = _getThemesStandard(themeId);
297                            }
298                            else {
299                                    installedLayoutTemplates = _getThemesCustom(themeId);
300                            }
301                    }
302                    else if (servletContextName != null) {
303                            if (standard) {
304                                    installedLayoutTemplates = _warStandard;
305                            }
306                            else {
307                                    installedLayoutTemplates = _warCustom;
308                            }
309                    }
310                    else {
311                            if (standard) {
312                                    installedLayoutTemplates = _portalStandard;
313                            }
314                            else {
315                                    installedLayoutTemplates = _portalCustom;
316                            }
317                    }
318    
319                    List<Element> layoutTemplateElements = element.elements(
320                            "layout-template");
321    
322                    for (Element layoutTemplateElement : layoutTemplateElements) {
323                            String layoutTemplateId = layoutTemplateElement.attributeValue(
324                                    "id");
325    
326                            LayoutTemplate layoutTemplateModel = installedLayoutTemplates.get(
327                                    layoutTemplateId);
328    
329                            if (layoutTemplateModel == null) {
330                                    layoutTemplateModel = new LayoutTemplateImpl(layoutTemplateId);
331    
332                                    installedLayoutTemplates.put(
333                                            layoutTemplateId, layoutTemplateModel);
334                            }
335    
336                            PluginSetting pluginSetting =
337                                    pluginSettingLocalService.getDefaultPluginSetting();
338    
339                            layoutTemplateModel.setPluginPackage(pluginPackage);
340                            layoutTemplateModel.setServletContext(servletContext);
341    
342                            if (servletContextName != null) {
343                                    layoutTemplateModel.setServletContextName(servletContextName);
344                            }
345    
346                            layoutTemplateModel.setStandard(standard);
347                            layoutTemplateModel.setThemeId(themeId);
348    
349                            String templateName = GetterUtil.getString(
350                                    layoutTemplateElement.attributeValue("name"));
351    
352                            if (Validator.isNotNull(templateName)) {
353                                    layoutTemplateModel.setName(templateName);
354                            }
355    
356                            layoutTemplateModel.setTemplatePath(
357                                    GetterUtil.getString(
358                                            layoutTemplateElement.elementText("template-path"),
359                                            layoutTemplateModel.getTemplatePath()));
360                            layoutTemplateModel.setWapTemplatePath(
361                                    GetterUtil.getString(
362                                            layoutTemplateElement.elementText("wap-template-path"),
363                                            layoutTemplateModel.getWapTemplatePath()));
364                            layoutTemplateModel.setThumbnailPath(
365                                    GetterUtil.getString(
366                                            layoutTemplateElement.elementText("thumbnail-path"),
367                                            layoutTemplateModel.getThumbnailPath()));
368    
369                            String content = null;
370    
371                            try {
372                                    content = HttpUtil.URLtoString(
373                                            servletContext.getResource(
374                                                    layoutTemplateModel.getTemplatePath()));
375                            }
376                            catch (Exception e) {
377                                    _log.error(
378                                            "Unable to get content at template path " +
379                                                    layoutTemplateModel.getTemplatePath() + ": " +
380                                                            e.getMessage());
381                            }
382    
383                            if (Validator.isNull(content)) {
384                                    _log.error(
385                                            "No content found at template path " +
386                                                    layoutTemplateModel.getTemplatePath());
387                            }
388                            else {
389                                    StringBundler sb = new StringBundler(3);
390    
391                                    sb.append(themeId);
392    
393                                    if (standard) {
394                                            sb.append(LayoutTemplateConstants.STANDARD_SEPARATOR);
395                                    }
396                                    else {
397                                            sb.append(LayoutTemplateConstants.CUSTOM_SEPARATOR);
398                                    }
399    
400                                    sb.append(layoutTemplateId);
401    
402                                    String velocityTemplateId = sb.toString();
403    
404                                    layoutTemplateModel.setContent(content);
405                                    layoutTemplateModel.setColumns(
406                                            _getColumns(velocityTemplateId, content));
407                            }
408    
409                            if (Validator.isNull(layoutTemplateModel.getWapTemplatePath())) {
410                                    _log.error(
411                                            "The element wap-template-path is not defined for " +
412                                                    layoutTemplateId);
413                            }
414                            else {
415                                    String wapContent = null;
416    
417                                    try {
418                                            wapContent = HttpUtil.URLtoString(
419                                                    servletContext.getResource(
420                                                            layoutTemplateModel.getWapTemplatePath()));
421                                    }
422                                    catch (Exception e) {
423                                            _log.error(
424                                                    "Unable to get content at WAP template path " +
425                                                            layoutTemplateModel.getWapTemplatePath() + ": " +
426                                                                    e.getMessage());
427                                    }
428    
429                                    if (Validator.isNull(wapContent)) {
430                                            _log.error(
431                                                    "No content found at WAP template path " +
432                                                            layoutTemplateModel.getWapTemplatePath());
433                                    }
434                                    else {
435                                            layoutTemplateModel.setWapContent(wapContent);
436                                    }
437                            }
438    
439                            Element rolesElement = layoutTemplateElement.element("roles");
440    
441                            if (rolesElement != null) {
442                                    List<Element> roleNameElements = rolesElement.elements(
443                                            "role-name");
444    
445                                    for (Element roleNameElement : roleNameElements) {
446                                            pluginSetting.addRole(roleNameElement.getText());
447                                    }
448                            }
449    
450                            layoutTemplateModel.setDefaultPluginSetting(pluginSetting);
451    
452                            if (layoutTemplates != null) {
453                                    layoutTemplates.add(layoutTemplateModel);
454                            }
455                    }
456            }
457    
458            @Override
459            public void uninstallLayoutTemplate(
460                    String layoutTemplateId, boolean standard) {
461    
462                    String templateId = null;
463    
464                    try {
465                            if (standard) {
466                                    templateId =
467                                            "null" + LayoutTemplateConstants.STANDARD_SEPARATOR +
468                                                    layoutTemplateId;
469    
470                                    TemplateResourceLoaderUtil.clearCache(
471                                            TemplateConstants.LANG_TYPE_VM, templateId);
472    
473                                    _warStandard.remove(layoutTemplateId);
474                            }
475                            else {
476                                    templateId =
477                                            "null" + LayoutTemplateConstants.CUSTOM_SEPARATOR +
478                                                    layoutTemplateId;
479    
480                                    TemplateResourceLoaderUtil.clearCache(
481                                            TemplateConstants.LANG_TYPE_VM, templateId);
482    
483                                    _warCustom.remove(layoutTemplateId);
484                            }
485                    }
486                    catch (Exception e) {
487                            _log.error(
488                                    "Unable to uninstall layout template " + layoutTemplateId, e);
489                    }
490            }
491    
492            @Override
493            public void uninstallLayoutTemplates(String themeId) {
494                    Map<String, LayoutTemplate> _themesStandard = _getThemesStandard(
495                            themeId);
496    
497                    for (Map.Entry<String, LayoutTemplate> entry :
498                                    _themesStandard.entrySet()) {
499    
500                            LayoutTemplate layoutTemplate = entry.getValue();
501    
502                            String templateId =
503                                    themeId + LayoutTemplateConstants.STANDARD_SEPARATOR +
504                                            layoutTemplate.getLayoutTemplateId();
505    
506                            try {
507                                    TemplateResourceLoaderUtil.clearCache(
508                                            TemplateConstants.LANG_TYPE_VM, templateId);
509                            }
510                            catch (Exception e) {
511                                    _log.error(
512                                            "Unable to uninstall layout template " +
513                                                    layoutTemplate.getLayoutTemplateId(),
514                                            e);
515                            }
516                    }
517    
518                    _themesStandard.clear();
519    
520                    Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
521    
522                    for (Map.Entry<String, LayoutTemplate> entry :
523                                    _themesCustom.entrySet()) {
524    
525                            LayoutTemplate layoutTemplate = entry.getValue();
526    
527                            String templateId =
528                                    themeId + LayoutTemplateConstants.CUSTOM_SEPARATOR +
529                                            layoutTemplate.getLayoutTemplateId();
530    
531                            try {
532                                    TemplateResourceLoaderUtil.clearCache(
533                                            TemplateConstants.LANG_TYPE_VM, templateId);
534                            }
535                            catch (Exception e) {
536                                    _log.error(
537                                            "Unable to uninstall layout template " +
538                                                    layoutTemplate.getLayoutTemplateId(),
539                                            e);
540                            }
541                    }
542    
543                    _themesCustom.clear();
544            }
545    
546            private List<String> _getColumns(
547                    String velocityTemplateId, String velocityTemplateContent) {
548    
549                    try {
550                            InitColumnProcessor processor = new InitColumnProcessor();
551    
552                            Template template = TemplateManagerUtil.getTemplate(
553                                    TemplateConstants.LANG_TYPE_VM,
554                                    new StringTemplateResource(
555                                            velocityTemplateId, velocityTemplateContent),
556                                    false);
557    
558                            template.put("processor", processor);
559    
560                            template.processTemplate(new DummyWriter());
561    
562                            return ListUtil.sort(processor.getColumns());
563                    }
564                    catch (Exception e) {
565                            _log.error(e);
566    
567                            return new ArrayList<>();
568                    }
569            }
570    
571            private Map<String, LayoutTemplate> _getThemesCustom(String themeId) {
572                    String key = themeId.concat(LayoutTemplateConstants.CUSTOM_SEPARATOR);
573    
574                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
575    
576                    if (layoutTemplates == null) {
577                            layoutTemplates = new LinkedHashMap<>();
578    
579                            _themes.put(key, layoutTemplates);
580                    }
581    
582                    return layoutTemplates;
583            }
584    
585            private Map<String, LayoutTemplate> _getThemesStandard(String themeId) {
586                    String key = themeId + LayoutTemplateConstants.STANDARD_SEPARATOR;
587    
588                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
589    
590                    if (layoutTemplates == null) {
591                            layoutTemplates = new LinkedHashMap<>();
592    
593                            _themes.put(key, layoutTemplates);
594                    }
595    
596                    return layoutTemplates;
597            }
598    
599            private Set<LayoutTemplate> _readLayoutTemplates(
600                            String servletContextName, ServletContext servletContext,
601                            String xml, PluginPackage pluginPackage)
602                    throws Exception {
603    
604                    Set<LayoutTemplate> layoutTemplates = new HashSet<>();
605    
606                    if (xml == null) {
607                            return layoutTemplates;
608                    }
609    
610                    Document document = UnsecureSAXReaderUtil.read(xml, true);
611    
612                    Element rootElement = document.getRootElement();
613    
614                    Element standardElement = rootElement.element("standard");
615    
616                    if (standardElement != null) {
617                            readLayoutTemplate(
618                                    servletContextName, servletContext, layoutTemplates,
619                                    standardElement, true, null, pluginPackage);
620                    }
621    
622                    Element customElement = rootElement.element("custom");
623    
624                    if (customElement != null) {
625                            readLayoutTemplate(
626                                    servletContextName, servletContext, layoutTemplates,
627                                    customElement, false, null, pluginPackage);
628                    }
629    
630                    return layoutTemplates;
631            }
632    
633            private static final Log _log = LogFactoryUtil.getLog(
634                    LayoutTemplateLocalServiceImpl.class);
635    
636            private static final Map<String, LayoutTemplate> _portalCustom =
637                    new LinkedHashMap<>();
638            private static final Map<String, LayoutTemplate> _portalStandard =
639                    new LinkedHashMap<>();
640            private static final Map<String, Map<String, LayoutTemplate>> _themes =
641                    new LinkedHashMap<>();
642            private static final Map<String, LayoutTemplate> _warCustom =
643                    new LinkedHashMap<>();
644            private static final Map<String, LayoutTemplate> _warStandard =
645                    new LinkedHashMap<>();
646    
647    }