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