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.freemarker;
016    
017    import com.liferay.portal.kernel.cache.PortalCache;
018    import com.liferay.portal.kernel.freemarker.FreeMarkerContext;
019    import com.liferay.portal.kernel.freemarker.FreeMarkerEngine;
020    import com.liferay.portal.kernel.freemarker.FreeMarkerVariablesUtil;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.util.StringPool;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.util.PropsValues;
026    
027    import freemarker.cache.ClassTemplateLoader;
028    import freemarker.cache.MultiTemplateLoader;
029    import freemarker.cache.TemplateLoader;
030    
031    import freemarker.template.Configuration;
032    import freemarker.template.Template;
033    
034    import java.io.IOException;
035    import java.io.Writer;
036    
037    /**
038     * @author Mika Koivisto
039     */
040    public class FreeMarkerEngineImpl implements FreeMarkerEngine {
041    
042            public void flushTemplate(String freeMarkerTemplateId) {
043                    if (_stringTemplateLoader != null) {
044                            _stringTemplateLoader.removeTemplate(freeMarkerTemplateId);
045                    }
046    
047                    PortalCache portalCache = LiferayCacheStorage.getPortalCache();
048    
049                    portalCache.remove(freeMarkerTemplateId);
050            }
051    
052            public FreeMarkerContext getWrappedRestrictedToolsContext() {
053                    return new FreeMarkerContextImpl(
054                            _restrictedToolsContext.getWrappedContext());
055            }
056    
057            public FreeMarkerContext getWrappedStandardToolsContext() {
058                    return new FreeMarkerContextImpl(
059                            _standardToolsContext.getWrappedContext());
060            }
061    
062            public void init() throws Exception {
063                    if (_configuration != null) {
064                            return;
065                    }
066    
067                    LiferayTemplateLoader liferayTemplateLoader =
068                            new LiferayTemplateLoader();
069    
070                    liferayTemplateLoader.setTemplateLoaders(
071                            PropsValues.FREEMARKER_ENGINE_TEMPLATE_LOADERS);
072    
073                    _stringTemplateLoader = new StringTemplateLoader();
074    
075                    MultiTemplateLoader multiTemplateLoader =
076                            new MultiTemplateLoader(
077                                    new TemplateLoader[] {
078                                            new ClassTemplateLoader(getClass(), StringPool.SLASH),
079                                            _stringTemplateLoader, liferayTemplateLoader
080                                    });
081    
082                    _configuration = new Configuration();
083    
084                    _configuration.setDefaultEncoding(StringPool.UTF8);
085                    _configuration.setLocalizedLookup(
086                            PropsValues.FREEMARKER_ENGINE_LOCALIZED_LOOKUP);
087                    _configuration.setObjectWrapper(new LiferayObjectWrapper());
088                    _configuration.setSetting(
089                            "auto_import", PropsValues.FREEMARKER_ENGINE_MACRO_LIBRARY);
090                    _configuration.setSetting(
091                            "cache_storage", PropsValues.FREEMARKER_ENGINE_CACHE_STORAGE);
092                    _configuration.setSetting(
093                            "template_exception_handler",
094                            PropsValues.FREEMARKER_ENGINE_TEMPLATE_EXCEPTION_HANDLER);
095                    _configuration.setTemplateLoader(multiTemplateLoader);
096                    _configuration.setTemplateUpdateDelay(
097                            PropsValues.FREEMARKER_ENGINE_MODIFICATION_CHECK_INTERVAL);
098    
099                    _restrictedToolsContext = new FreeMarkerContextImpl();
100    
101                    FreeMarkerVariablesUtil.insertHelperUtilities(
102                            _restrictedToolsContext,
103                            PropsValues.JOURNAL_TEMPLATE_FREEMARKER_RESTRICTED_VARIABLES);
104    
105                    _standardToolsContext = new FreeMarkerContextImpl();
106    
107                    FreeMarkerVariablesUtil.insertHelperUtilities(
108                            _standardToolsContext, null);
109            }
110    
111            public boolean mergeTemplate(
112                            String freeMarkerTemplateId, FreeMarkerContext freeMarkerContext,
113                            Writer writer)
114                    throws Exception {
115    
116                    return mergeTemplate(
117                            freeMarkerTemplateId, null, freeMarkerContext, writer);
118            }
119    
120            public boolean mergeTemplate(
121                            String freeMarkerTemplateId, String freemarkerTemplateContent,
122                            FreeMarkerContext freeMarkerContext, Writer writer)
123                    throws Exception {
124    
125                    if (Validator.isNotNull(freemarkerTemplateContent) &&
126                            (!PropsValues.LAYOUT_TEMPLATE_CACHE_ENABLED ||
127                             !stringTemplateExists(freeMarkerTemplateId))) {
128    
129                            _stringTemplateLoader.putTemplate(
130                                    freeMarkerTemplateId, freemarkerTemplateContent);
131    
132                            if (_log.isDebugEnabled()) {
133                                    _log.debug(
134                                            "Added " + freeMarkerTemplateId +
135                                                    " to the string based FreeMarker template repository");
136                            }
137                    }
138    
139                    FreeMarkerContextImpl freeMarkerContextImpl =
140                            (FreeMarkerContextImpl)freeMarkerContext;
141    
142                    Template template = _configuration.getTemplate(
143                            freeMarkerTemplateId, StringPool.UTF8);
144    
145                    template.process(freeMarkerContextImpl.getWrappedContext(), writer);
146    
147                    return true;
148            }
149    
150            public boolean resourceExists(String resource) {
151                    try {
152                            Template template = _configuration.getTemplate(resource);
153    
154                            if (template != null) {
155                                    return true;
156                            }
157                            else {
158                                    return false;
159                            }
160                    }
161                    catch (IOException ioe) {
162                            if (_log.isWarnEnabled()) {
163                                    _log.warn(ioe, ioe);
164                            }
165    
166                            return false;
167                    }
168            }
169    
170            protected boolean stringTemplateExists(String freeMarkerTemplateId) {
171                    Object templateSource = _stringTemplateLoader.findTemplateSource(
172                            freeMarkerTemplateId);
173    
174                    if (templateSource == null) {
175                            return false;
176                    }
177    
178                    return true;
179            }
180    
181            private static Log _log = LogFactoryUtil.getLog(FreeMarkerEngineImpl.class);
182    
183            private Configuration _configuration;
184            private FreeMarkerContextImpl _restrictedToolsContext;
185            private FreeMarkerContextImpl _standardToolsContext;
186            private StringTemplateLoader _stringTemplateLoader;
187    
188    }