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(
111 "Argument \"name\" cannot be null");
112 }
113
114 if (locale == null) {
115 throw new IllegalArgumentException(
116 "Argument \"locale\" cannot be null");
117 }
118
119 if (encoding == null) {
120 throw new IllegalArgumentException(
121 "Argument \"encoding\" cannot be null");
122 }
123
124 TemplateResource templateResource = null;
125
126 if (templateId.startsWith(
127 TemplateConstants.TEMPLATE_RESOURCE_UUID_PREFIX)) {
128
129 templateResource = TemplateResourceThreadLocal.getTemplateResource(
130 TemplateConstants.LANG_TYPE_FTL);
131 }
132 else {
133 try {
134 templateId = (String)_normalizeNameMethod.invoke(
135 this, templateId);
136
137 templateResource =
138 TemplateResourceLoaderUtil.getTemplateResource(
139 TemplateConstants.LANG_TYPE_FTL, templateId);
140 }
141 catch (Exception e) {
142 templateResource = null;
143 }
144 }
145
146 if (templateResource == null) {
147 throw new IOException(
148 "Unable to find FreeMarker template with ID " + templateId);
149 }
150
151 Object object = _portalCache.get(templateResource);
152
153 if ((object != null) && (object instanceof Template)) {
154 return (Template)object;
155 }
156
157 Template template = new Template(
158 templateResource.getTemplateId(), templateResource.getReader(),
159 _configuration, TemplateConstants.DEFAUT_ENCODING);
160
161 if (PropsValues.
162 FREEMARKER_ENGINE_RESOURCE_MODIFICATION_CHECK_INTERVAL != 0) {
163
164 _portalCache.put(templateResource, template);
165 }
166
167 return template;
168 }
169
170 private Configuration _configuration;
171 private Method _normalizeNameMethod;
172 private PortalCache<TemplateResource, Object> _portalCache;
173
174 private class TemplatePrivilegedExceptionAction
175 implements PrivilegedExceptionAction<Template> {
176
177 public TemplatePrivilegedExceptionAction(
178 String templateId, Locale locale, String encoding, boolean parse) {
179
180 _templateId = templateId;
181 _locale = locale;
182 _encoding = encoding;
183 _parse = parse;
184 }
185
186 @Override
187 public Template run() throws Exception {
188 return doGetTemplate(_templateId, _locale, _encoding, _parse);
189 }
190
191 private String _encoding;
192 private Locale _locale;
193 private boolean _parse;
194 private String _templateId;
195
196 }
197
198 }