001
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.TemplateConstants;
020 import com.liferay.portal.kernel.template.TemplateException;
021 import com.liferay.portal.kernel.template.TemplateResource;
022 import com.liferay.portal.kernel.template.TemplateResourceLoaderUtil;
023 import com.liferay.portal.kernel.util.PropsKeys;
024 import com.liferay.portal.kernel.util.ReflectionUtil;
025 import com.liferay.portal.kernel.util.StringPool;
026 import com.liferay.portal.template.TemplateResourceThreadLocal;
027 import com.liferay.portal.util.PropsUtil;
028 import com.liferay.portal.util.PropsValues;
029
030 import freemarker.cache.TemplateCache;
031
032 import freemarker.template.Configuration;
033 import freemarker.template.Template;
034
035 import java.io.IOException;
036
037 import java.lang.reflect.Method;
038
039 import java.security.AccessController;
040 import java.security.PrivilegedActionException;
041 import java.security.PrivilegedExceptionAction;
042
043 import java.util.Locale;
044
045
048 public class LiferayTemplateCache extends TemplateCache {
049
050 public LiferayTemplateCache(Configuration configuration)
051 throws TemplateException {
052
053 _configuration = configuration;
054
055 try {
056 _normalizeNameMethod = ReflectionUtil.getDeclaredMethod(
057 TemplateCache.class, "normalizeName", String.class);
058 }
059 catch (Exception e) {
060 throw new TemplateException(e);
061 }
062
063 String cacheName = TemplateResource.class.getName();
064
065 cacheName = cacheName.concat(StringPool.POUND).concat(
066 TemplateConstants.LANG_TYPE_FTL);
067
068 _portalCache = SingleVMPoolUtil.getCache(cacheName);
069 }
070
071 @Override
072 public Template getTemplate(
073 String templateId, Locale locale, String encoding, boolean parse)
074 throws IOException {
075
076 String[] macroTemplateIds = PropsUtil.getArray(
077 PropsKeys.FREEMARKER_ENGINE_MACRO_LIBRARY);
078
079 for (String macroTemplateId : macroTemplateIds) {
080 int pos = macroTemplateId.indexOf(" as ");
081
082 if (pos != -1) {
083 macroTemplateId = macroTemplateId.substring(0, pos);
084 }
085
086 if (templateId.equals(macroTemplateId)) {
087
088
089
090
091 try {
092 return AccessController.doPrivileged(
093 new TemplatePrivilegedExceptionAction(
094 macroTemplateId, locale, encoding, parse));
095 }
096 catch (PrivilegedActionException pae) {
097 throw (IOException)pae.getException();
098 }
099 }
100 }
101
102 return doGetTemplate(templateId, locale, encoding, parse);
103 }
104
105 private Template doGetTemplate(
106 String templateId, Locale locale, String encoding, boolean parse)
107 throws IOException {
108
109 if (templateId == null) {
110 throw new IllegalArgumentException("Argument \"name\" is null");
111 }
112
113 if (locale == null) {
114 throw new IllegalArgumentException("Argument \"locale\" is null");
115 }
116
117 if (encoding == null) {
118 throw new IllegalArgumentException("Argument \"encoding\" is null");
119 }
120
121 TemplateResource templateResource = null;
122
123 if (templateId.startsWith(
124 TemplateConstants.TEMPLATE_RESOURCE_UUID_PREFIX)) {
125
126 templateResource = TemplateResourceThreadLocal.getTemplateResource(
127 TemplateConstants.LANG_TYPE_FTL);
128 }
129 else {
130 try {
131 templateId = (String)_normalizeNameMethod.invoke(
132 this, templateId);
133
134 templateResource =
135 TemplateResourceLoaderUtil.getTemplateResource(
136 TemplateConstants.LANG_TYPE_FTL, templateId);
137 }
138 catch (Exception e) {
139 templateResource = null;
140 }
141 }
142
143 if (templateResource == null) {
144 throw new IOException(
145 "Unable to find FreeMarker template with ID " + templateId);
146 }
147
148 Object object = _portalCache.get(templateResource);
149
150 if ((object != null) && (object instanceof Template)) {
151 return (Template)object;
152 }
153
154 Template template = new Template(
155 templateResource.getTemplateId(), templateResource.getReader(),
156 _configuration, TemplateConstants.DEFAUT_ENCODING);
157
158 if (PropsValues.
159 FREEMARKER_ENGINE_RESOURCE_MODIFICATION_CHECK_INTERVAL != 0) {
160
161 _portalCache.put(templateResource, template);
162 }
163
164 return template;
165 }
166
167 private Configuration _configuration;
168 private Method _normalizeNameMethod;
169 private PortalCache<TemplateResource, Object> _portalCache;
170
171 private class TemplatePrivilegedExceptionAction
172 implements PrivilegedExceptionAction<Template> {
173
174 public TemplatePrivilegedExceptionAction(
175 String templateId, Locale locale, String encoding, boolean parse) {
176
177 _templateId = templateId;
178 _locale = locale;
179 _encoding = encoding;
180 _parse = parse;
181 }
182
183 @Override
184 public Template run() throws Exception {
185 return doGetTemplate(_templateId, _locale, _encoding, _parse);
186 }
187
188 private String _encoding;
189 private Locale _locale;
190 private boolean _parse;
191 private String _templateId;
192
193 }
194
195 }