001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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(
151                            ListUtil.fromCollection(_portalCustom.values()));
152    
153                    customLayoutTemplates.addAll(
154                            ListUtil.fromCollection(_warCustom.values()));
155    
156                    return customLayoutTemplates;
157            }
158    
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                    Iterator<Map.Entry<String, LayoutTemplate>> itr =
168                            _portalCustom.entrySet().iterator();
169    
170                    while (itr.hasNext()) {
171                            Map.Entry<String, LayoutTemplate> entry = itr.next();
172    
173                            String layoutTemplateId = entry.getKey();
174                            LayoutTemplate layoutTemplate = entry.getValue();
175    
176                            if (_themesCustom.containsKey(layoutTemplateId)) {
177                                    customLayoutTemplates.add(_themesCustom.get(layoutTemplateId));
178                            }
179                            else if (_warCustom.containsKey(layoutTemplateId)) {
180                                    customLayoutTemplates.add(_warCustom.get(layoutTemplateId));
181                            }
182                            else {
183                                    customLayoutTemplates.add(layoutTemplate);
184                            }
185                    }
186    
187                    itr = _warCustom.entrySet().iterator();
188    
189                    while (itr.hasNext()) {
190                            Map.Entry<String, LayoutTemplate> entry = itr.next();
191    
192                            String layoutTemplateId = entry.getKey();
193    
194                            if (!_portalCustom.containsKey(layoutTemplateId) &&
195                                    !_themesCustom.containsKey(layoutTemplateId)) {
196    
197                                    customLayoutTemplates.add(_warCustom.get(layoutTemplateId));
198                            }
199                    }
200    
201                    itr = _themesCustom.entrySet().iterator();
202    
203                    while (itr.hasNext()) {
204                            Map.Entry<String, LayoutTemplate> entry = itr.next();
205    
206                            String layoutTemplateId = entry.getKey();
207    
208                            if (!_portalCustom.containsKey(layoutTemplateId) &&
209                                    !_warCustom.containsKey(layoutTemplateId)) {
210    
211                                    customLayoutTemplates.add(_themesCustom.get(layoutTemplateId));
212                            }
213                    }
214    
215                    return customLayoutTemplates;
216            }
217    
218            public String getWapContent(
219                            String layoutTemplateId, boolean standard, String themeId)
220                    throws SystemException {
221    
222                    LayoutTemplate layoutTemplate = getLayoutTemplate(
223                            layoutTemplateId, standard, themeId);
224    
225                    if (layoutTemplate == null) {
226                            if (_log.isWarnEnabled()) {
227                                    _log.warn(
228                                            "Layout template " + layoutTemplateId + " does not exist");
229                            }
230    
231                            layoutTemplate = getLayoutTemplate(
232                                    PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID, standard, themeId);
233    
234                            if (layoutTemplate == null) {
235                                    _log.error(
236                                            "Layout template " + layoutTemplateId +
237                                                    " and default layout template " +
238                                                            PropsValues.DEFAULT_LAYOUT_TEMPLATE_ID +
239                                                                    " do not exist");
240    
241                                    return StringPool.BLANK;
242                            }
243                    }
244    
245                    if (PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED) {
246                            return layoutTemplate.getWapContent();
247                    }
248                    else {
249                            try {
250                                    return layoutTemplate.getUncachedWapContent();
251                            }
252                            catch (IOException ioe) {
253                                    throw new SystemException(ioe);
254                            }
255                    }
256            }
257    
258            public List<ObjectValuePair<String, Boolean>> init(
259                    ServletContext servletContext, String[] xmls,
260                    PluginPackage pluginPackage) {
261    
262                    return init(null, servletContext, xmls, pluginPackage);
263            }
264    
265            public List<ObjectValuePair<String, Boolean>> init(
266                    String servletContextName, ServletContext servletContext, String[] xmls,
267                    PluginPackage pluginPackage) {
268    
269                    List<ObjectValuePair<String, Boolean>> layoutTemplateIds =
270                            new ArrayList<ObjectValuePair<String, Boolean>>();
271    
272                    try {
273                            for (int i = 0; i < xmls.length; i++) {
274                                    Set<ObjectValuePair<String, Boolean>> curLayoutTemplateIds =
275                                            _readLayoutTemplates(
276                                                    servletContextName, servletContext, xmls[i],
277                                                    pluginPackage);
278    
279                                    Iterator<ObjectValuePair<String, Boolean>> itr =
280                                            curLayoutTemplateIds.iterator();
281    
282                                    while (itr.hasNext()) {
283                                            ObjectValuePair<String, Boolean> ovp = itr.next();
284    
285                                            if (!layoutTemplateIds.contains(ovp)) {
286                                                    layoutTemplateIds.add(ovp);
287                                            }
288                                    }
289                            }
290                    }
291                    catch (Exception e) {
292                            _log.error(e, e);
293                    }
294    
295                    return layoutTemplateIds;
296            }
297    
298            public void readLayoutTemplate(
299                    String servletContextName, ServletContext servletContext,
300                    Set<ObjectValuePair<String, Boolean>> layoutTemplateIds,
301                    com.liferay.portal.kernel.xml.Element el, boolean standard,
302                    String themeId, PluginPackage pluginPackage) {
303    
304                    Map<String, LayoutTemplate> layoutTemplates = null;
305    
306                    if (themeId != null) {
307                            if (standard) {
308                                    layoutTemplates = _getThemesStandard(themeId);
309                            }
310                            else {
311                                    layoutTemplates = _getThemesCustom(themeId);
312                            }
313                    }
314                    else if (servletContextName != null) {
315                            if (standard) {
316                                    layoutTemplates = _warStandard;
317                            }
318                            else {
319                                    layoutTemplates = _warCustom;
320                            }
321                    }
322                    else {
323                            if (standard) {
324                                    layoutTemplates = _portalStandard;
325                            }
326                            else {
327                                    layoutTemplates = _portalCustom;
328                            }
329                    }
330    
331                    Iterator<com.liferay.portal.kernel.xml.Element> itr = el.elements(
332                            "layout-template").iterator();
333    
334                    while (itr.hasNext()) {
335                            com.liferay.portal.kernel.xml.Element layoutTemplate = itr.next();
336    
337                            String layoutTemplateId = layoutTemplate.attributeValue("id");
338    
339                            if (layoutTemplateIds != null) {
340                                    ObjectValuePair<String, Boolean> ovp =
341                                            new ObjectValuePair<String, Boolean>(
342                                                    layoutTemplateId, standard);
343    
344                                    layoutTemplateIds.add(ovp);
345                            }
346    
347                            LayoutTemplate layoutTemplateModel = layoutTemplates.get(
348                                    layoutTemplateId);
349    
350                            if (layoutTemplateModel == null) {
351                                    layoutTemplateModel = new LayoutTemplateImpl(layoutTemplateId);
352    
353                                    layoutTemplates.put(layoutTemplateId, layoutTemplateModel);
354                            }
355    
356                            PluginSetting pluginSetting =
357                                    pluginSettingLocalService.getDefaultPluginSetting();
358    
359                            layoutTemplateModel.setPluginPackage(pluginPackage);
360                            layoutTemplateModel.setServletContext(servletContext);
361    
362                            if (servletContextName != null) {
363                                    layoutTemplateModel.setServletContextName(servletContextName);
364                            }
365    
366                            layoutTemplateModel.setStandard(standard);
367                            layoutTemplateModel.setThemeId(themeId);
368                            layoutTemplateModel.setName(GetterUtil.getString(
369                                    layoutTemplate.attributeValue("name"),
370                                    layoutTemplateModel.getName()));
371                            layoutTemplateModel.setTemplatePath(GetterUtil.getString(
372                                    layoutTemplate.elementText("template-path"),
373                                    layoutTemplateModel.getTemplatePath()));
374                            layoutTemplateModel.setWapTemplatePath(GetterUtil.getString(
375                                    layoutTemplate.elementText("wap-template-path"),
376                                    layoutTemplateModel.getWapTemplatePath()));
377                            layoutTemplateModel.setThumbnailPath(GetterUtil.getString(
378                                    layoutTemplate.elementText("thumbnail-path"),
379                                    layoutTemplateModel.getThumbnailPath()));
380    
381                            String content = null;
382    
383                            try {
384                                    content = HttpUtil.URLtoString(servletContext.getResource(
385                                            layoutTemplateModel.getTemplatePath()));
386                            }
387                            catch (Exception e) {
388                                    _log.error(
389                                            "Unable to get content at template path " +
390                                                    layoutTemplateModel.getTemplatePath() + ": " +
391                                                            e.getMessage());
392                            }
393    
394                            if (Validator.isNull(content)) {
395                                    _log.error(
396                                            "No content found at template path " +
397                                                    layoutTemplateModel.getTemplatePath());
398                            }
399                            else {
400                                    StringBundler sb = new StringBundler(3);
401    
402                                    sb.append(themeId);
403    
404                                    if (standard) {
405                                            sb.append(LayoutTemplateConstants.STANDARD_SEPARATOR);
406                                    }
407                                    else {
408                                            sb.append(LayoutTemplateConstants.CUSTOM_SEPARATOR);
409                                    }
410    
411                                    sb.append(layoutTemplateId);
412    
413                                    String velocityTemplateId = sb.toString();
414    
415                                    layoutTemplateModel.setContent(content);
416                                    layoutTemplateModel.setColumns(
417                                            _getColumns(velocityTemplateId, content));
418                            }
419    
420                            if (Validator.isNull(layoutTemplateModel.getWapTemplatePath())) {
421                                    _log.error(
422                                            "The element wap-template-path is not defined for " +
423                                                    layoutTemplateId);
424                            }
425                            else {
426                                    String wapContent = null;
427    
428                                    try {
429                                            wapContent = HttpUtil.URLtoString(
430                                                    servletContext.getResource(
431                                                            layoutTemplateModel.getWapTemplatePath()));
432                                    }
433                                    catch (Exception e) {
434                                            _log.error(
435                                                    "Unable to get content at WAP template path " +
436                                                            layoutTemplateModel.getWapTemplatePath() + ": " +
437                                                                    e.getMessage());
438                                    }
439    
440                                    if (Validator.isNull(wapContent)) {
441                                            _log.error(
442                                                    "No content found at WAP template path " +
443                                                            layoutTemplateModel.getWapTemplatePath());
444                                    }
445                                    else {
446                                            layoutTemplateModel.setWapContent(wapContent);
447                                    }
448                            }
449    
450                            com.liferay.portal.kernel.xml.Element rolesEl =
451                                    layoutTemplate.element("roles");
452    
453                            if (rolesEl != null) {
454                                    Iterator<com.liferay.portal.kernel.xml.Element> itr2 =
455                                            rolesEl.elements("role-name").iterator();
456    
457                                    while (itr2.hasNext()) {
458                                            com.liferay.portal.kernel.xml.Element roleNameEl =
459                                                    itr2.next();
460    
461                                            pluginSetting.addRole(roleNameEl.getText());
462                                    }
463                            }
464    
465                            layoutTemplateModel.setDefaultPluginSetting(pluginSetting);
466                    }
467            }
468    
469            public void uninstallLayoutTemplate(
470                    String layoutTemplateId, boolean standard) {
471    
472                    if (standard) {
473                            VelocityEngineUtil.flushTemplate(
474                                    "null" + LayoutTemplateConstants.STANDARD_SEPARATOR +
475                                            layoutTemplateId);
476    
477                            _warStandard.remove(layoutTemplateId);
478                    }
479                    else {
480                            VelocityEngineUtil.flushTemplate(
481                                    "null" + LayoutTemplateConstants.CUSTOM_SEPARATOR +
482                                            layoutTemplateId);
483    
484                            _warCustom.remove(layoutTemplateId);
485                    }
486            }
487    
488            public void uninstallLayoutTemplates(String themeId) {
489                    Map<String, LayoutTemplate> _themesStandard =
490                            _getThemesStandard(themeId);
491    
492                    for (Map.Entry<String, LayoutTemplate> entry :
493                                    _themesStandard.entrySet()) {
494    
495                            LayoutTemplate layoutTemplate = entry.getValue();
496    
497                            VelocityEngineUtil.flushTemplate(
498                                    themeId + LayoutTemplateConstants.STANDARD_SEPARATOR +
499                                            layoutTemplate.getLayoutTemplateId());
500                    }
501    
502                    _themesStandard.clear();
503    
504                    Map<String, LayoutTemplate> _themesCustom = _getThemesCustom(themeId);
505    
506                    for (Map.Entry<String, LayoutTemplate> entry :
507                                    _themesCustom.entrySet()) {
508    
509                            LayoutTemplate layoutTemplate = entry.getValue();
510    
511                            VelocityEngineUtil.flushTemplate(
512                                    themeId + LayoutTemplateConstants.CUSTOM_SEPARATOR +
513                                            layoutTemplate.getLayoutTemplateId());
514                    }
515    
516                    _themesCustom.clear();
517            }
518    
519            private List<String> _getColumns(
520                    String velocityTemplateId, String velocityTemplateContent) {
521    
522                    try {
523                            InitColumnProcessor processor = new InitColumnProcessor();
524    
525                            VelocityContext velocityContext =
526                                    VelocityEngineUtil.getStandardToolsContext();
527    
528                            velocityContext.put("processor", processor);
529    
530                            VelocityEngineUtil.mergeTemplate(
531                                    velocityTemplateId, velocityTemplateContent, velocityContext,
532                                    new DummyWriter());
533    
534                            return ListUtil.sort(processor.getColumns());
535                    }
536                    catch (Exception e) {
537                            _log.error(e);
538    
539                            return new ArrayList<String>();
540                    }
541            }
542    
543            private Set<ObjectValuePair<String, Boolean>> _readLayoutTemplates(
544                            String servletContextName, ServletContext servletContext,
545                            String xml, PluginPackage pluginPackage)
546                    throws Exception {
547    
548                    Set<ObjectValuePair<String, Boolean>> layoutTemplateIds =
549                            new HashSet<ObjectValuePair<String, Boolean>>();
550    
551                    if (xml == null) {
552                            return layoutTemplateIds;
553                    }
554    
555                    Document doc = SAXReaderUtil.read(xml, true);
556    
557                    Element root = doc.getRootElement();
558    
559                    Element standardEl = root.element("standard");
560    
561                    if (standardEl != null) {
562                            readLayoutTemplate(
563                                    servletContextName, servletContext, layoutTemplateIds,
564                                    standardEl, true, null, pluginPackage);
565                    }
566    
567                    Element customEl = root.element("custom");
568    
569                    if (customEl != null) {
570                            readLayoutTemplate(
571                                    servletContextName, servletContext, layoutTemplateIds,
572                                    customEl, false, null, pluginPackage);
573                    }
574    
575                    return layoutTemplateIds;
576            }
577    
578            private Map<String, LayoutTemplate> _getThemesCustom(String themeId) {
579                    String key = themeId + LayoutTemplateConstants.CUSTOM_SEPARATOR;
580    
581                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
582    
583                    if (layoutTemplates == null) {
584                            layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
585    
586                            _themes.put(key, layoutTemplates);
587                    }
588    
589                    return layoutTemplates;
590            }
591    
592            private Map<String, LayoutTemplate> _getThemesStandard(String themeId) {
593                    String key = themeId + LayoutTemplateConstants.STANDARD_SEPARATOR;
594    
595                    Map<String, LayoutTemplate> layoutTemplates = _themes.get(key);
596    
597                    if (layoutTemplates == null) {
598                            layoutTemplates = new LinkedHashMap<String, LayoutTemplate>();
599    
600                            _themes.put(key, layoutTemplates);
601                    }
602    
603                    return layoutTemplates;
604            }
605    
606            private static Log _log = LogFactoryUtil.getLog(
607                    LayoutTemplateLocalServiceImpl.class);
608    
609            private static Map<String, LayoutTemplate> _portalStandard =
610                    new LinkedHashMap<String, LayoutTemplate>();
611            private static Map<String, LayoutTemplate> _portalCustom =
612                    new LinkedHashMap<String, LayoutTemplate>();
613    
614            private static Map<String, LayoutTemplate> _warStandard =
615                    new LinkedHashMap<String, LayoutTemplate>();
616            private static Map<String, LayoutTemplate> _warCustom =
617                    new LinkedHashMap<String, LayoutTemplate>();
618    
619            private static Map<String, Map<String, LayoutTemplate>> _themes =
620                    new LinkedHashMap<String, Map<String, LayoutTemplate>>();
621    
622    }