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.cache.SingleVMPoolUtil;
019    import com.liferay.portal.kernel.template.TemplateException;
020    import com.liferay.portal.kernel.template.TemplateManager;
021    import com.liferay.portal.kernel.template.TemplateResource;
022    import com.liferay.portal.kernel.template.TemplateResourceLoaderUtil;
023    import com.liferay.portal.kernel.util.ReflectionUtil;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.template.TemplateResourceThreadLocal;
026    import com.liferay.portal.util.PropsValues;
027    
028    import freemarker.cache.TemplateCache;
029    
030    import freemarker.template.Configuration;
031    import freemarker.template.Template;
032    
033    import java.io.IOException;
034    
035    import java.lang.reflect.Method;
036    
037    import java.util.Locale;
038    
039    /**
040     * @author Tina Tian
041     */
042    public class LiferayTemplateCache extends TemplateCache {
043    
044            public LiferayTemplateCache(Configuration configuration)
045                    throws TemplateException {
046    
047                    _configuration = configuration;
048    
049                    try {
050                            _normalizeNameMethod = ReflectionUtil.getDeclaredMethod(
051                                    TemplateCache.class, "normalizeName", String.class);
052                    }
053                    catch (Exception e) {
054                            throw new TemplateException(e);
055                    }
056    
057                    String cacheName = TemplateResource.class.getName();
058    
059                    cacheName = cacheName.concat(StringPool.POUND).concat(
060                            TemplateManager.FREEMARKER);
061    
062                    _portalCache = SingleVMPoolUtil.getCache(cacheName);
063            }
064    
065            @Override
066            public Template getTemplate(
067                            String templateId, Locale locale, String encoding, boolean parse)
068                    throws IOException {
069    
070                    if (templateId == null) {
071                            throw new IllegalArgumentException(
072                                    "Argument \"name\" cannot be null");
073                    }
074    
075                    if (locale == null) {
076                            throw new IllegalArgumentException(
077                                    "Argument \"locale\" cannot be null");
078                    }
079    
080                    if (encoding == null) {
081                            throw new IllegalArgumentException(
082                                    "Argument \"encoding\" cannot be null");
083                    }
084    
085                    TemplateResource templateResource = null;
086    
087                    if (templateId.startsWith(
088                                    TemplateResource.TEMPLATE_RESOURCE_UUID_PREFIX)) {
089    
090                            templateResource = TemplateResourceThreadLocal.getTemplateResource(
091                                    TemplateManager.FREEMARKER);
092                    }
093                    else {
094                            try {
095                                    templateId = (String)_normalizeNameMethod.invoke(
096                                            this, templateId);
097    
098                                    templateResource =
099                                            TemplateResourceLoaderUtil.getTemplateResource(
100                                                    TemplateManager.FREEMARKER, templateId);
101                            }
102                            catch (Exception e) {
103                                    templateResource = null;
104                            }
105                    }
106    
107                    if (templateResource == null) {
108                            throw new IOException(
109                                    "Unable to find FreeMarker template with ID " + templateId);
110                    }
111    
112                    Object object = _portalCache.get(templateResource);
113    
114                    if ((object != null) && (object instanceof Template)) {
115                            return (Template)object;
116                    }
117    
118                    Template template = new Template(
119                            templateResource.getTemplateId(), templateResource.getReader(),
120                            _configuration, TemplateResource.DEFAUT_ENCODING);
121    
122                    if (PropsValues.
123                                    FREEMARKER_ENGINE_RESOURCE_MODIFICATION_CHECK_INTERVAL != 0) {
124    
125                            _portalCache.put(templateResource, template);
126                    }
127    
128                    return template;
129            }
130    
131            private Configuration _configuration;
132            private Method _normalizeNameMethod;
133            private PortalCache<TemplateResource, Object> _portalCache;
134    
135    }