001    /**
002     * Copyright (c) 2000-2012 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.service.impl;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.io.DummyWriter;
019    import com.liferay.portal.kernel.log.Log;
020    import com.liferay.portal.kernel.log.LogFactoryUtil;
021    import com.liferay.portal.kernel.plugin.PluginPackage;
022    import com.liferay.portal.kernel.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            public String getContent(
064                            String layoutTemplateId, boolean standard, String themeId)
065                    throws SystemException {
066    
067                    LayoutTemplate layoutTemplate = getLayoutTemplate(
068                            layoutTemplateId, standard, themeId);
069    
070                    if (layoutTemplate == null) {
071                            if (_log.isWarnEnabled()) {
072                                    _log.warn(
073                                            "Layout template " + layoutTemplateId + " does not exist");
074                            }
075    
076                            layoutTemplate = getLayoutTemplate(
077                                    PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID, standard, themeId);
078    
079                            if (layoutTemplate == null) {
080                                    _log.error(
081                                            "Layout template " + layoutTemplateId +
082                                                    " and default layout template " +
083                                                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
084                                                                    " do not exist");
085    
086                                    return StringPool.BLANK;
087                            }
088                    }
089    
090                    if (PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
091                            return layoutTemplate.getContent();
092                    }
093                    else {
094                            try {
095                                    return layoutTemplate.getUncachedContent();
096                            }
097                            catch (IOException ioe) {
098                                    throw new SystemException(ioe);
099                            }
100                    }
101            }
102    
103            public LayoutTemplate getLayoutTemplate(
104                    String layoutTemplateId, boolean standard, String themeId) {
105    
106                    if (Validator.isNull(layoutTemplateId)) {
107                            return null;
108                    }
109    
110                    LayoutTemplate layoutTemplate = null;
111    
112                    if (themeId != null) {
113                            if (standard) {
114                                    layoutTemplate = _getThemesStandard(themeId).get(
115                                            layoutTemplateId);
116                            }
117                            else {
118                                    layoutTemplate = _getThemesCustom(themeId).get(
119                                            layoutTemplateId);
120                            }
121    
122                            if (layoutTemplate != null) {
123                                    return layoutTemplate;
124                            }
125                    }
126    
127                    if (standard) {
128                            layoutTemplate = _warStandard.get(layoutTemplateId);
129    
130                            if (layoutTemplate == null) {
131                                    layoutTemplate = _portalStandard.get(layoutTemplateId);
132                            }
133                    }
134                    else {
135                            layoutTemplate = _warCustom.get(layoutTemplateId);
136    
137                            if (layoutTemplate == null) {
138                                    layoutTemplate = _portalCustom.get(layoutTemplateId);
139                            }
140                    }
141    
142                    return layoutTemplate;
143            }
144    
145            public List<LayoutTemplate> getLayoutTemplates() {
146                    List<LayoutTemplate> customLayoutTemplates =
147                            new ArrayList<LayoutTemplate>(
148                                                            _portalCustom.size() + _warCustom.size());
149    
150                    customLayoutTemplates.addAll(ListUtil.fromMapValues(_portalCustom));
151                    customLayoutTemplates.addAll(ListUtil.fromMapValues(_warCustom));
152    
153                    return customLayoutTemplates;
154            }
155    
156            public List<LayoutTemplate> getLayoutTemplates(String themeId) {
157                    Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
158    
159                    List<LayoutTemplate> customLayoutTemplates =
160                            new ArrayList<LayoutTemplate>(
161                                    _portalCustom.size() + _warCustom.size() +
162                                            _themesCustom.size());
163    
164                    Iterator<Map.Entry<String, LayoutTemplate>> itr =
165                            _portalCustom.entrySet().iterator();
166    
167                    while (itr.hasNext()) {
168                            Map.Entry<String, LayoutTemplate> entry = itr.next();
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                    itr = _warCustom.entrySet().iterator();
193    
194                    while (itr.hasNext()) {
195                            Map.Entry<String, LayoutTemplate> entry = itr.next();
196    
197                            String layoutTemplateId = entry.getKey();
198    
199                            if (!_portalCustom.containsKey(layoutTemplateId) &&
200                                    !_themesCustom.containsKey(layoutTemplateId)) {
201    
202                                    customLayoutTemplates.add(_warCustom.get(layoutTemplateId));
203                            }
204                    }
205    
206                    itr = _themesCustom.entrySet().iterator();
207    
208                    while (itr.hasNext()) {
209                            Map.Entry<String, LayoutTemplate> entry = itr.next();
210    
211                            String layoutTemplateId = entry.getKey();
212    
213                            if (!_portalCustom.containsKey(layoutTemplateId) &&
214                                    !_warCustom.containsKey(layoutTemplateId)) {
215    
216                                    customLayoutTemplates.add(_themesCustom.get(layoutTemplateId));
217                            }
218                    }
219    
220                    return customLayoutTemplates;
221            }
222    
223            public String getWapContent(
224                            String layoutTemplateId, boolean standard, String themeId)
225                    throws SystemException {
226    
227                    LayoutTemplate layoutTemplate = getLayoutTemplate(
228                            layoutTemplateId, standard, themeId);
229    
230                    if (layoutTemplate == null) {
231                            if (_log.isWarnEnabled()) {
232                                    _log.warn(
233                                            "Layout template " + layoutTemplateId + " does not exist");
234                            }
235    
236                            layoutTemplate = getLayoutTemplate(
237                                    PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID, standard, themeId);
238    
239                            if (layoutTemplate == null) {
240                                    _log.error(
241                                            "Layout template " + layoutTemplateId +
242                                                    " and default layout template " +
243                                                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
244                                                                    " do not exist");
245    
246                                    return StringPool.BLANK;
247                            }
248                    }
249    
250                    if (PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
251                            return layoutTemplate.getWapContent();
252                    }
253                    else {
254                            try {
255                                    return layoutTemplate.getUncachedWapContent();
256                            }
257                            catch (IOException ioe) {
258                                    throw new SystemException(ioe);
259                            }
260                    }
261            }
262    
263            public List<ObjectValuePair<String, Boolean>> init(
264                    ServletContext servletContext, String[] xmls,
265                    PluginPackage pluginPackage) {
266    
267                    return init(null, servletContext, xmls, pluginPackage);
268            }
269    
270            public List<ObjectValuePair<String, Boolean>> init(
271                    String servletContextName, ServletContext servletContext, String[] xmls,
272                    PluginPackage pluginPackage) {
273    
274                    List<ObjectValuePair<String, Boolean>> layoutTemplateIds =
275                            new ArrayList<ObjectValuePair<String, Boolean>>();
276    
277                    try {
278                            for (int i = 0; i < xmls.length; i++) {
279                                    Set<ObjectValuePair<String, Boolean>> curLayoutTemplateIds =
280                                            _readLayoutTemplates(
281                                                    servletContextName, servletContext, xmls[i],
282                                                    pluginPackage);
283    
284                                    Iterator<ObjectValuePair<String, Boolean>> itr =
285                                            curLayoutTemplateIds.iterator();
286    
287                                    while (itr.hasNext()) {
288                                            ObjectValuePair<String, Boolean> ovp = itr.next();
289    
290                                            if (!layoutTemplateIds.contains(ovp)) {
291                                                    layoutTemplateIds.add(ovp);
292                                            }
293                                    }
294                            }
295                    }
296                    catch (Exception e) {
297                            _log.error(e, e);
298                    }
299    
300                    return layoutTemplateIds;
301            }
302    
303            public void readLayoutTemplate(
304                    String servletContextName, ServletContext servletContext,
305                    Set<ObjectValuePair<String, Boolean>> layoutTemplateIds,
306                    com.liferay.portal.kernel.xml.Element el, boolean standard,
307                    String themeId, PluginPackage pluginPackage) {
308    
309                    Map<String, LayoutTemplate> layoutTemplates = null;
310    
311                    if (themeId != null) {
312                            if (standard) {
313                                    layoutTemplates = _getThemesStandard(themeId);
314                            }
315                            else {
316                                    layoutTemplates = _getThemesCustom(themeId);
317                            }
318                    }
319                    else if (servletContextName != null) {
320                            if (standard) {
321                                    layoutTemplates = _warStandard;
322                            }
323                            else {
324                                    layoutTemplates = _warCustom;
325                            }
326                    }
327                    else {
328                            if (standard) {
329                                    layoutTemplates = _portalStandard;
330                            }
331                            else {
332                                    layoutTemplates = _portalCustom;
333                            }
334                    }
335    
336                    Iterator<com.liferay.portal.kernel.xml.Element> itr = el.elements(
337                            "layout-template").iterator();
338    
339                    while (itr.hasNext()) {
340                            com.liferay.portal.kernel.xml.Element layoutTemplate = itr.next();
341    
342                            String layoutTemplateId = layoutTemplate.attributeValue("id");
343    
344                            if (layoutTemplateIds != null) {
345                                    ObjectValuePair<String, Boolean> ovp =
346                                            new ObjectValuePair<String, Boolean>(
347                                                    layoutTemplateId, standard);
348    
349                                    layoutTemplateIds.add(ovp);
350                            }
351    
352                            LayoutTemplate layoutTemplateModel = layoutTemplates.get(
353                                    layoutTemplateId);
354    
355                            if (layoutTemplateModel == null) {
356                                    layoutTemplateModel = new LayoutTemplateImpl(layoutTemplateId);
357    
358                                    layoutTemplates.put(layoutTemplateId, layoutTemplateModel);
359                            }
360    
361                            PluginSetting pluginSetting =
362                                    pluginSettingLocalService.getDefaultPluginSetting();
363    
364                            layoutTemplateModel.setPluginPackage(pluginPackage);
365                            layoutTemplateModel.setServletContext(servletContext);
366    
367                            if (servletContextName != null) {
368                                    layoutTemplateModel.setServletContextName(servletContextName);
369                            }
370    
371                            layoutTemplateModel.setStandard(standard);
372                            layoutTemplateModel.setThemeId(themeId);
373                            layoutTemplateModel.setName(GetterUtil.getString(
374                                    layoutTemplate.attributeValue("name"),
375                                    layoutTemplateModel.getName()));
376                            layoutTemplateModel.setTemplatePath(GetterUtil.getString(
377                                    layoutTemplate.elementText("template-path"),
378                                    layoutTemplateModel.getTemplatePath()));
379                            layoutTemplateModel.setWapTemplatePath(GetterUtil.getString(
380                                    layoutTemplate.elementText("wap-template-path"),
381                                    layoutTemplateModel.getWapTemplatePath()));
382                            layoutTemplateModel.setThumbnailPath(GetterUtil.getString(
383                                    layoutTemplate.elementText("thumbnail-path"),
384                                    layoutTemplateModel.getThumbnailPath()));
385    
386                            String content = null;
387    
388                            try {
389                                    content = HttpUtil.URLtoString(servletContext.getResource(
390                                            layoutTemplateModel.getTemplatePath()));
391                            }
392                            catch (Exception e) {
393                                    _log.error(
394                                            "Unable to get content at template path " +
395                                                    layoutTemplateModel.getTemplatePath() + ": " +
396                                                            e.getMessage());
397                            }
398    
399                            if (Validator.isNull(content)) {
400                                    _log.error(
401                                            "No content found at template path " +
402                                                    layoutTemplateModel.getTemplatePath());
403                            }
404                            else {
405                                    StringBundler sb = new StringBundler(3);
406    
407                                    sb.append(themeId);
408    
409                                    if (standard) {
410                                            sb.append(LayoutTemplateConstants.STANDARD_SEPARATOR);
411                                    }
412                                    else {
413                                            sb.append(LayoutTemplateConstants.CUSTOM_SEPARATOR);
414                                    }
415    
416                                    sb.append(layoutTemplateId);
417    
418                                    String velocityTemplateId = sb.toString();
419    
420                                    layoutTemplateModel.setContent(content);
421                                    layoutTemplateModel.setColumns(
422                                            _getColumns(velocityTemplateId, content));
423                            }
424    
425                            if (Validator.isNull(layoutTemplateModel.getWapTemplatePath())) {
426                                    _log.error(
427                                            "The element wap-template-path is not defined for " +
428                                                    layoutTemplateId);
429                            }
430                            else {
431                                    String wapContent = null;
432    
433                                    try {
434                                            wapContent = HttpUtil.URLtoString(
435                                                    servletContext.getResource(
436                                                            layoutTemplateModel.getWapTemplatePath()));
437                                    }
438                                    catch (Exception e) {
439                                            _log.error(
440                                                    "Unable to get content at WAP template path " +
441                                                            layoutTemplateModel.getWapTemplatePath() + ": " +
442                                                                    e.getMessage());
443                                    }
444    
445                                    if (Validator.isNull(wapContent)) {
446                                            _log.error(
447                                                    "No content found at WAP template path " +
448                                                            layoutTemplateModel.getWapTemplatePath());
449                                    }
450                                    else {
451                                            layoutTemplateModel.setWapContent(wapContent);
452                                    }
453                            }
454    
455                            com.liferay.portal.kernel.xml.Element rolesEl =
456                                    layoutTemplate.element("roles");
457    
458                            if (rolesEl != null) {
459                                    Iterator<com.liferay.portal.kernel.xml.Element> itr2 =
460                                            rolesEl.elements("role-name").iterator();
461    
462                                    while (itr2.hasNext()) {
463                                            com.liferay.portal.kernel.xml.Element roleNameEl =
464                                                    itr2.next();
465    
466                                            pluginSetting.addRole(roleNameEl.getText());
467                                    }
468                            }
469    
470                            layoutTemplateModel.setDefaultPluginSetting(pluginSetting);
471                    }
472            }
473    
474            public void uninstallLayoutTemplate(
475                    String layoutTemplateId, boolean standard) {
476    
477                    if (standard) {
478                            VelocityEngineUtil.flushTemplate(
479                                    "null" + LayoutTemplateConstants.STANDARD_SEPARATOR +
480                                            layoutTemplateId);
481    
482                            _warStandard.remove(layoutTemplateId);
483                    }
484                    else {
485                            VelocityEngineUtil.flushTemplate(
486                                    "null" + LayoutTemplateConstants.CUSTOM_SEPARATOR +
487                                            layoutTemplateId);
488    
489                            _warCustom.remove(layoutTemplateId);
490                    }
491            }
492    
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                            VelocityEngineUtil.flushTemplate(
503                                    themeId + LayoutTemplateConstants.STANDARD_SEPARATOR +
504                                            layoutTemplate.getLayoutTemplateId());
505                    }
506    
507                    _themesStandard.clear();
508    
509                    Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
510    
511                    for (Map.Entry<String, LayoutTemplate> entry :
512                                    _themesCustom.entrySet()) {
513    
514                            LayoutTemplate layoutTemplate = entry.getValue();
515    
516                            VelocityEngineUtil.flushTemplate(
517                                    themeId + LayoutTemplateConstants.CUSTOM_SEPARATOR +
518                                            layoutTemplate.getLayoutTemplateId());
519                    }
520    
521                    _themesCustom.clear();
522            }
523    
524            private List<String> _getColumns(
525                    String velocityTemplateId, String velocityTemplateContent) {
526    
527                    try {
528                            InitColumnProcessor processor = new InitColumnProcessor();
529    
530                            VelocityContext velocityContext =
531                                    VelocityEngineUtil.getStandardToolsContext();
532    
533                            velocityContext.put("processor", processor);
534    
535                            VelocityEngineUtil.mergeTemplate(
536                                    velocityTemplateId, velocityTemplateContent, velocityContext,
537                                    new DummyWriter());
538    
539                            return ListUtil.sort(processor.getColumns());
540                    }
541                    catch (Exception e) {
542                            _log.error(e);
543    
544                            return new ArrayList<String>();
545                    }
546            }
547    
548            private Map<String, LayoutTemplate> _getThemesCustom(String themeId) {
549                    String key = themeId.concat(LayoutTemplateConstants.CUSTOM_SEPARATOR);
550    
551                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
552    
553                    if (layoutTemplates == null) {
554                            layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
555    
556                            _themes.put(key, layoutTemplates);
557                    }
558    
559                    return layoutTemplates;
560            }
561    
562            private Map<String, LayoutTemplate> _getThemesStandard(String themeId) {
563                    String key = themeId + LayoutTemplateConstants.STANDARD_SEPARATOR;
564    
565                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
566    
567                    if (layoutTemplates == null) {
568                            layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
569    
570                            _themes.put(key, layoutTemplates);
571                    }
572    
573                    return layoutTemplates;
574            }
575    
576            private Set<ObjectValuePair<String, Boolean>> _readLayoutTemplates(
577                            String servletContextName, ServletContext servletContext,
578                            String xml, PluginPackage pluginPackage)
579                    throws Exception {
580    
581                    Set<ObjectValuePair<String, Boolean>> layoutTemplateIds =
582                            new HashSet<ObjectValuePair<String, Boolean>>();
583    
584                    if (xml == null) {
585                            return layoutTemplateIds;
586                    }
587    
588                    Document doc = SAXReaderUtil.read(xml, true);
589    
590                    Element root = doc.getRootElement();
591    
592                    Element standardEl = root.element("standard");
593    
594                    if (standardEl != null) {
595                            readLayoutTemplate(
596                                    servletContextName, servletContext, layoutTemplateIds,
597                                    standardEl, true, null, pluginPackage);
598                    }
599    
600                    Element customEl = root.element("custom");
601    
602                    if (customEl != null) {
603                            readLayoutTemplate(
604                                    servletContextName, servletContext, layoutTemplateIds, customEl,
605                                    false, null, pluginPackage);
606                    }
607    
608                    return layoutTemplateIds;
609            }
610    
611            private static Log _log = LogFactoryUtil.getLog(
612                    LayoutTemplateLocalServiceImpl.class);
613    
614            private static Map<String, LayoutTemplate> _portalCustom =
615                    new LinkedHashMap<String, LayoutTemplate>();
616            private static Map<String, LayoutTemplate> _portalStandard =
617                    new LinkedHashMap<String, LayoutTemplate>();
618    
619            private static Map<String, Map<String, LayoutTemplate>> _themes =
620                    new LinkedHashMap<String, Map<String, LayoutTemplate>>();
621    
622            private static Map<String, LayoutTemplate> _warCustom =
623                    new LinkedHashMap<String, LayoutTemplate>();
624            private static Map<String, LayoutTemplate> _warStandard =
625                    new LinkedHashMap<String, LayoutTemplate>();
626    
627    }