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.model.LayoutTemplate;
022    import com.liferay.portal.kernel.model.LayoutTemplateConstants;
023    import com.liferay.portal.kernel.model.PluginSetting;
024    import com.liferay.portal.kernel.plugin.PluginPackage;
025    import com.liferay.portal.kernel.template.StringTemplateResource;
026    import com.liferay.portal.kernel.template.Template;
027    import com.liferay.portal.kernel.template.TemplateConstants;
028    import com.liferay.portal.kernel.template.TemplateManagerUtil;
029    import com.liferay.portal.kernel.template.TemplateResourceLoaderUtil;
030    import com.liferay.portal.kernel.util.GetterUtil;
031    import com.liferay.portal.kernel.util.HttpUtil;
032    import com.liferay.portal.kernel.util.ListUtil;
033    import com.liferay.portal.kernel.util.StringBundler;
034    import com.liferay.portal.kernel.util.StringPool;
035    import com.liferay.portal.kernel.util.Validator;
036    import com.liferay.portal.kernel.xml.Document;
037    import com.liferay.portal.kernel.xml.Element;
038    import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
039    import com.liferay.portal.layoutconfiguration.util.velocity.InitColumnProcessor;
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 List<LayoutTemplate> init(
219                    ServletContext servletContext, String[] xmls,
220                    PluginPackage pluginPackage) {
221    
222                    return init(null, servletContext, xmls, pluginPackage);
223            }
224    
225            @Override
226            public List<LayoutTemplate> init(
227                    String servletContextName, ServletContext servletContext, String[] xmls,
228                    PluginPackage pluginPackage) {
229    
230                    Set<LayoutTemplate> layoutTemplates = new LinkedHashSet<>();
231    
232                    try {
233                            for (String xml : xmls) {
234                                    layoutTemplates.addAll(
235                                            _readLayoutTemplates(
236                                                    servletContextName, servletContext, xml,
237                                                    pluginPackage));
238                            }
239                    }
240                    catch (Exception e) {
241                            _log.error(e, e);
242                    }
243    
244                    return new ArrayList<>(layoutTemplates);
245            }
246    
247            @Override
248            public void readLayoutTemplate(
249                    String servletContextName, ServletContext servletContext,
250                    Set<LayoutTemplate> layoutTemplates, Element element, boolean standard,
251                    String themeId, PluginPackage pluginPackage) {
252    
253                    Map<String, LayoutTemplate> installedLayoutTemplates = null;
254    
255                    if (themeId != null) {
256                            if (standard) {
257                                    installedLayoutTemplates = _getThemesStandard(themeId);
258                            }
259                            else {
260                                    installedLayoutTemplates = _getThemesCustom(themeId);
261                            }
262                    }
263                    else if (servletContextName != null) {
264                            if (standard) {
265                                    installedLayoutTemplates = _warStandard;
266                            }
267                            else {
268                                    installedLayoutTemplates = _warCustom;
269                            }
270                    }
271                    else {
272                            if (standard) {
273                                    installedLayoutTemplates = _portalStandard;
274                            }
275                            else {
276                                    installedLayoutTemplates = _portalCustom;
277                            }
278                    }
279    
280                    List<Element> layoutTemplateElements = element.elements(
281                            "layout-template");
282    
283                    for (Element layoutTemplateElement : layoutTemplateElements) {
284                            String layoutTemplateId = layoutTemplateElement.attributeValue(
285                                    "id");
286    
287                            LayoutTemplate layoutTemplateModel = installedLayoutTemplates.get(
288                                    layoutTemplateId);
289    
290                            if (layoutTemplateModel == null) {
291                                    layoutTemplateModel = new LayoutTemplateImpl(layoutTemplateId);
292    
293                                    installedLayoutTemplates.put(
294                                            layoutTemplateId, layoutTemplateModel);
295                            }
296    
297                            PluginSetting pluginSetting =
298                                    pluginSettingLocalService.getDefaultPluginSetting();
299    
300                            layoutTemplateModel.setPluginPackage(pluginPackage);
301                            layoutTemplateModel.setServletContext(servletContext);
302    
303                            if (servletContextName != null) {
304                                    layoutTemplateModel.setServletContextName(servletContextName);
305                            }
306    
307                            layoutTemplateModel.setStandard(standard);
308                            layoutTemplateModel.setThemeId(themeId);
309    
310                            String templateName = GetterUtil.getString(
311                                    layoutTemplateElement.attributeValue("name"));
312    
313                            if (Validator.isNotNull(templateName)) {
314                                    layoutTemplateModel.setName(templateName);
315                            }
316    
317                            layoutTemplateModel.setTemplatePath(
318                                    GetterUtil.getString(
319                                            layoutTemplateElement.elementText("template-path"),
320                                            layoutTemplateModel.getTemplatePath()));
321                            layoutTemplateModel.setThumbnailPath(
322                                    GetterUtil.getString(
323                                            layoutTemplateElement.elementText("thumbnail-path"),
324                                            layoutTemplateModel.getThumbnailPath()));
325    
326                            String content = null;
327    
328                            try {
329                                    content = HttpUtil.URLtoString(
330                                            servletContext.getResource(
331                                                    layoutTemplateModel.getTemplatePath()));
332                            }
333                            catch (Exception e) {
334                                    _log.error(
335                                            "Unable to get content at template path " +
336                                                    layoutTemplateModel.getTemplatePath() + ": " +
337                                                            e.getMessage());
338                            }
339    
340                            if (Validator.isNull(content)) {
341                                    _log.error(
342                                            "No content found at template path " +
343                                                    layoutTemplateModel.getTemplatePath());
344                            }
345                            else {
346                                    StringBundler sb = new StringBundler(3);
347    
348                                    sb.append(themeId);
349    
350                                    if (standard) {
351                                            sb.append(LayoutTemplateConstants.STANDARD_SEPARATOR);
352                                    }
353                                    else {
354                                            sb.append(LayoutTemplateConstants.CUSTOM_SEPARATOR);
355                                    }
356    
357                                    sb.append(layoutTemplateId);
358    
359                                    String velocityTemplateId = sb.toString();
360    
361                                    layoutTemplateModel.setContent(content);
362                                    layoutTemplateModel.setColumns(
363                                            _getColumns(velocityTemplateId, content));
364                            }
365    
366                            Element rolesElement = layoutTemplateElement.element("roles");
367    
368                            if (rolesElement != null) {
369                                    List<Element> roleNameElements = rolesElement.elements(
370                                            "role-name");
371    
372                                    for (Element roleNameElement : roleNameElements) {
373                                            pluginSetting.addRole(roleNameElement.getText());
374                                    }
375                            }
376    
377                            layoutTemplateModel.setDefaultPluginSetting(pluginSetting);
378    
379                            if (layoutTemplates != null) {
380                                    layoutTemplates.add(layoutTemplateModel);
381                            }
382                    }
383            }
384    
385            @Override
386            public void uninstallLayoutTemplate(
387                    String layoutTemplateId, boolean standard) {
388    
389                    String templateId = null;
390    
391                    try {
392                            if (standard) {
393                                    templateId =
394                                            "null" + LayoutTemplateConstants.STANDARD_SEPARATOR +
395                                                    layoutTemplateId;
396    
397                                    TemplateResourceLoaderUtil.clearCache(
398                                            TemplateConstants.LANG_TYPE_VM, templateId);
399    
400                                    _warStandard.remove(layoutTemplateId);
401                            }
402                            else {
403                                    templateId =
404                                            "null" + LayoutTemplateConstants.CUSTOM_SEPARATOR +
405                                                    layoutTemplateId;
406    
407                                    TemplateResourceLoaderUtil.clearCache(
408                                            TemplateConstants.LANG_TYPE_VM, templateId);
409    
410                                    _warCustom.remove(layoutTemplateId);
411                            }
412                    }
413                    catch (Exception e) {
414                            _log.error(
415                                    "Unable to uninstall layout template " + layoutTemplateId, e);
416                    }
417            }
418    
419            @Override
420            public void uninstallLayoutTemplates(String themeId) {
421                    Map<String, LayoutTemplate> _themesStandard = _getThemesStandard(
422                            themeId);
423    
424                    for (Map.Entry<String, LayoutTemplate> entry :
425                                    _themesStandard.entrySet()) {
426    
427                            LayoutTemplate layoutTemplate = entry.getValue();
428    
429                            String templateId =
430                                    themeId + LayoutTemplateConstants.STANDARD_SEPARATOR +
431                                            layoutTemplate.getLayoutTemplateId();
432    
433                            try {
434                                    TemplateResourceLoaderUtil.clearCache(
435                                            TemplateConstants.LANG_TYPE_VM, templateId);
436                            }
437                            catch (Exception e) {
438                                    _log.error(
439                                            "Unable to uninstall layout template " +
440                                                    layoutTemplate.getLayoutTemplateId(),
441                                            e);
442                            }
443                    }
444    
445                    _themesStandard.clear();
446    
447                    Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
448    
449                    for (Map.Entry<String, LayoutTemplate> entry :
450                                    _themesCustom.entrySet()) {
451    
452                            LayoutTemplate layoutTemplate = entry.getValue();
453    
454                            String templateId =
455                                    themeId + LayoutTemplateConstants.CUSTOM_SEPARATOR +
456                                            layoutTemplate.getLayoutTemplateId();
457    
458                            try {
459                                    TemplateResourceLoaderUtil.clearCache(
460                                            TemplateConstants.LANG_TYPE_VM, templateId);
461                            }
462                            catch (Exception e) {
463                                    _log.error(
464                                            "Unable to uninstall layout template " +
465                                                    layoutTemplate.getLayoutTemplateId(),
466                                            e);
467                            }
468                    }
469    
470                    _themesCustom.clear();
471            }
472    
473            private List<String> _getColumns(
474                    String velocityTemplateId, String velocityTemplateContent) {
475    
476                    try {
477                            InitColumnProcessor processor = new InitColumnProcessor();
478    
479                            Template template = TemplateManagerUtil.getTemplate(
480                                    TemplateConstants.LANG_TYPE_VM,
481                                    new StringTemplateResource(
482                                            velocityTemplateId, velocityTemplateContent),
483                                    false);
484    
485                            template.put("processor", processor);
486    
487                            template.processTemplate(new DummyWriter());
488    
489                            return ListUtil.sort(processor.getColumns());
490                    }
491                    catch (Exception e) {
492                            _log.error(e);
493    
494                            return new ArrayList<>();
495                    }
496            }
497    
498            private Map<String, LayoutTemplate> _getThemesCustom(String themeId) {
499                    String key = themeId.concat(LayoutTemplateConstants.CUSTOM_SEPARATOR);
500    
501                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
502    
503                    if (layoutTemplates == null) {
504                            layoutTemplates = new LinkedHashMap<>();
505    
506                            _themes.put(key, layoutTemplates);
507                    }
508    
509                    return layoutTemplates;
510            }
511    
512            private Map<String, LayoutTemplate> _getThemesStandard(String themeId) {
513                    String key = themeId + LayoutTemplateConstants.STANDARD_SEPARATOR;
514    
515                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
516    
517                    if (layoutTemplates == null) {
518                            layoutTemplates = new LinkedHashMap<>();
519    
520                            _themes.put(key, layoutTemplates);
521                    }
522    
523                    return layoutTemplates;
524            }
525    
526            private Set<LayoutTemplate> _readLayoutTemplates(
527                            String servletContextName, ServletContext servletContext,
528                            String xml, PluginPackage pluginPackage)
529                    throws Exception {
530    
531                    Set<LayoutTemplate> layoutTemplates = new HashSet<>();
532    
533                    if (xml == null) {
534                            return layoutTemplates;
535                    }
536    
537                    Document document = UnsecureSAXReaderUtil.read(xml, true);
538    
539                    Element rootElement = document.getRootElement();
540    
541                    Element standardElement = rootElement.element("standard");
542    
543                    if (standardElement != null) {
544                            readLayoutTemplate(
545                                    servletContextName, servletContext, layoutTemplates,
546                                    standardElement, true, null, pluginPackage);
547                    }
548    
549                    Element customElement = rootElement.element("custom");
550    
551                    if (customElement != null) {
552                            readLayoutTemplate(
553                                    servletContextName, servletContext, layoutTemplates,
554                                    customElement, false, null, pluginPackage);
555                    }
556    
557                    return layoutTemplates;
558            }
559    
560            private static final Log _log = LogFactoryUtil.getLog(
561                    LayoutTemplateLocalServiceImpl.class);
562    
563            private static final Map<String, LayoutTemplate> _portalCustom =
564                    new LinkedHashMap<>();
565            private static final Map<String, LayoutTemplate> _portalStandard =
566                    new LinkedHashMap<>();
567            private static final Map<String, Map<String, LayoutTemplate>> _themes =
568                    new LinkedHashMap<>();
569            private static final Map<String, LayoutTemplate> _warCustom =
570                    new LinkedHashMap<>();
571            private static final Map<String, LayoutTemplate> _warStandard =
572                    new LinkedHashMap<>();
573    
574    }