001
014
015 package com.liferay.portal.velocity;
016
017 import com.liferay.portal.kernel.log.Log;
018 import com.liferay.portal.kernel.log.LogFactoryUtil;
019 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
020 import com.liferay.portal.kernel.security.pacl.NotPrivileged;
021 import com.liferay.portal.kernel.util.PropsKeys;
022 import com.liferay.portal.kernel.util.StringPool;
023 import com.liferay.portal.kernel.util.StringUtil;
024 import com.liferay.portal.kernel.util.Validator;
025 import com.liferay.portal.kernel.velocity.VelocityContext;
026 import com.liferay.portal.kernel.velocity.VelocityEngine;
027 import com.liferay.portal.kernel.velocity.VelocityVariablesUtil;
028 import com.liferay.portal.template.TemplateControlContext;
029 import com.liferay.portal.util.ClassLoaderUtil;
030 import com.liferay.portal.util.PropsUtil;
031 import com.liferay.portal.util.PropsValues;
032
033 import java.io.Writer;
034
035 import java.security.AccessControlContext;
036 import java.security.AccessController;
037 import java.security.PrivilegedAction;
038 import java.security.PrivilegedExceptionAction;
039
040 import java.util.Map;
041 import java.util.concurrent.ConcurrentHashMap;
042
043 import org.apache.commons.collections.ExtendedProperties;
044 import org.apache.velocity.Template;
045 import org.apache.velocity.runtime.RuntimeConstants;
046 import org.apache.velocity.runtime.resource.ResourceManager;
047 import org.apache.velocity.runtime.resource.loader.StringResourceLoader;
048 import org.apache.velocity.runtime.resource.util.StringResourceRepository;
049
050
053 @DoPrivileged
054 public class VelocityEngineImpl implements VelocityEngine {
055
056 public VelocityEngineImpl() {
057 }
058
059 @Override
060 public void clearClassLoader(ClassLoader classLoader) {
061 _classLoaderToolsContextsMap.remove(classLoader);
062 }
063
064 @Override
065 public void flushTemplate(String velocityTemplateId) {
066 StringResourceRepository stringResourceRepository =
067 StringResourceLoader.getRepository();
068
069 if (stringResourceRepository != null) {
070 stringResourceRepository.removeStringResource(velocityTemplateId);
071 }
072
073 LiferayResourceCacheUtil.remove(
074 _getResourceCacheKey(velocityTemplateId));
075 }
076
077 @NotPrivileged
078 @Override
079 public VelocityContext getEmptyContext() {
080 return new VelocityContextImpl();
081 }
082
083 @NotPrivileged
084 @Override
085 public VelocityContext getRestrictedToolsContext() {
086 return _getToolsContext(_RESTRICTED);
087 }
088
089 @NotPrivileged
090 @Override
091 public VelocityContext getStandardToolsContext() {
092 return _getToolsContext(_STANDARD);
093 }
094
095 public TemplateControlContext getTemplateControlContext() {
096 return _pacl.getTemplateControlContext();
097 }
098
099 @NotPrivileged
100 @Override
101 public VelocityContext getWrappedClassLoaderToolsContext() {
102 return new VelocityContextImpl(_getToolsContext(_STANDARD));
103 }
104
105 @NotPrivileged
106 @Override
107 public VelocityContext getWrappedRestrictedToolsContext() {
108 return new VelocityContextImpl(_getToolsContext(_RESTRICTED));
109 }
110
111 @NotPrivileged
112 @Override
113 public VelocityContext getWrappedStandardToolsContext() {
114 return new VelocityContextImpl(_getToolsContext(_STANDARD));
115 }
116
117 @Override
118 public void init() throws Exception {
119 if (_velocityEngine != null) {
120 return;
121 }
122
123 _velocityEngine = new org.apache.velocity.app.VelocityEngine();
124
125 LiferayResourceLoader.setVelocityResourceListeners(
126 PropsValues.VELOCITY_ENGINE_RESOURCE_LISTENERS);
127
128 ExtendedProperties extendedProperties = new FastExtendedProperties();
129
130 extendedProperties.setProperty(
131 org.apache.velocity.app.VelocityEngine.EVENTHANDLER_METHODEXCEPTION,
132 LiferayMethodExceptionEventHandler.class.getName());
133
134 extendedProperties.setProperty(
135 RuntimeConstants.INTROSPECTOR_RESTRICT_CLASSES,
136 StringUtil.merge(PropsValues.VELOCITY_ENGINE_RESTRICTED_CLASSES));
137
138 extendedProperties.setProperty(
139 RuntimeConstants.INTROSPECTOR_RESTRICT_PACKAGES,
140 StringUtil.merge(PropsValues.VELOCITY_ENGINE_RESTRICTED_PACKAGES));
141
142 extendedProperties.setProperty(_RESOURCE_LOADER, "string,servlet");
143
144 extendedProperties.setProperty(
145 "string." + _RESOURCE_LOADER + ".cache",
146 String.valueOf(
147 PropsValues.VELOCITY_ENGINE_RESOURCE_MANAGER_CACHE_ENABLED));
148
149 extendedProperties.setProperty(
150 "string." + _RESOURCE_LOADER + ".class",
151 StringResourceLoader.class.getName());
152
153 extendedProperties.setProperty(
154 "string." + _RESOURCE_LOADER + ".repository.class",
155 StringResourceRepositoryImpl.class.getName());
156
157 extendedProperties.setProperty(
158 "servlet." + _RESOURCE_LOADER + ".cache",
159 String.valueOf(
160 PropsValues.VELOCITY_ENGINE_RESOURCE_MANAGER_CACHE_ENABLED));
161
162 extendedProperties.setProperty(
163 "servlet." + _RESOURCE_LOADER + ".class",
164 LiferayResourceLoader.class.getName());
165
166 extendedProperties.setProperty(
167 org.apache.velocity.app.VelocityEngine.RESOURCE_MANAGER_CLASS,
168 PropsUtil.get(PropsKeys.VELOCITY_ENGINE_RESOURCE_MANAGER));
169
170 extendedProperties.setProperty(
171 org.apache.velocity.app.VelocityEngine.RESOURCE_MANAGER_CACHE_CLASS,
172 PropsUtil.get(PropsKeys.VELOCITY_ENGINE_RESOURCE_MANAGER_CACHE));
173
174 extendedProperties.setProperty(
175 org.apache.velocity.app.VelocityEngine.VM_LIBRARY,
176 PropsUtil.get(PropsKeys.VELOCITY_ENGINE_VELOCIMACRO_LIBRARY));
177
178 extendedProperties.setProperty(
179 org.apache.velocity.app.VelocityEngine.VM_LIBRARY_AUTORELOAD,
180 String.valueOf(
181 !PropsValues.VELOCITY_ENGINE_RESOURCE_MANAGER_CACHE_ENABLED));
182
183 extendedProperties.setProperty(
184 org.apache.velocity.app.VelocityEngine.
185 VM_PERM_ALLOW_INLINE_REPLACE_GLOBAL,
186 String.valueOf(
187 !PropsValues.VELOCITY_ENGINE_RESOURCE_MANAGER_CACHE_ENABLED));
188
189 extendedProperties.setProperty(
190 org.apache.velocity.app.VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS,
191 PropsUtil.get(PropsKeys.VELOCITY_ENGINE_LOGGER));
192
193 extendedProperties.setProperty(
194 org.apache.velocity.app.VelocityEngine.RUNTIME_LOG_LOGSYSTEM +
195 ".log4j.category",
196 PropsUtil.get(PropsKeys.VELOCITY_ENGINE_LOGGER_CATEGORY));
197
198 _velocityEngine.setExtendedProperties(extendedProperties);
199
200 _velocityEngine.init();
201
202 _restrictedToolsContext = new VelocityContextImpl();
203
204 VelocityVariablesUtil.insertHelperUtilities(
205 _restrictedToolsContext,
206 PropsValues.JOURNAL_TEMPLATE_VELOCITY_RESTRICTED_VARIABLES);
207
208 _standardToolsContext = new VelocityContextImpl();
209
210 VelocityVariablesUtil.insertHelperUtilities(
211 _standardToolsContext, null);
212 }
213
214 @NotPrivileged
215 @Override
216 public boolean mergeTemplate(
217 String velocityTemplateId, String velocityTemplateContent,
218 VelocityContext velocityContext, Writer writer)
219 throws Exception {
220
221 Template template = AccessController.doPrivileged(
222 new DoGetTemplatePrivilegedAction(
223 velocityTemplateId, velocityTemplateContent, StringPool.UTF8));
224
225 VelocityContextImpl velocityContextImpl =
226 (VelocityContextImpl)velocityContext;
227
228 template.merge(velocityContextImpl.getWrappedVelocityContext(), writer);
229
230 return true;
231 }
232
233 @NotPrivileged
234 @Override
235 public boolean mergeTemplate(
236 String velocityTemplateId, VelocityContext velocityContext,
237 Writer writer)
238 throws Exception {
239
240 return mergeTemplate(velocityTemplateId, null, velocityContext, writer);
241 }
242
243 @NotPrivileged
244 @Override
245 public boolean resourceExists(String resource) {
246 return _velocityEngine.resourceExists(resource);
247 }
248
249 private VelocityContextImpl _doGetToolsContext(
250 ClassLoader classLoader, String templateContextType) {
251
252 Map<String, VelocityContextImpl> toolsContextMap =
253 _classLoaderToolsContextsMap.get(classLoader);
254
255 if (toolsContextMap == null) {
256 toolsContextMap =
257 new ConcurrentHashMap<String, VelocityContextImpl>();
258
259 _classLoaderToolsContextsMap.put(classLoader, toolsContextMap);
260 }
261
262 VelocityContextImpl velocityContextImpl = toolsContextMap.get(
263 templateContextType);
264
265 if (velocityContextImpl != null) {
266 return velocityContextImpl;
267 }
268
269 velocityContextImpl = new VelocityContextImpl();
270
271 if (_RESTRICTED.equals(templateContextType)) {
272 VelocityVariablesUtil.insertHelperUtilities(
273 velocityContextImpl,
274 PropsValues.JOURNAL_TEMPLATE_VELOCITY_RESTRICTED_VARIABLES);
275 }
276 else {
277 VelocityVariablesUtil.insertHelperUtilities(
278 velocityContextImpl, null);
279 }
280
281 toolsContextMap.put(templateContextType, velocityContextImpl);
282
283 return velocityContextImpl;
284 }
285
286 private String _getResourceCacheKey(String velocityTemplateId) {
287 return _RESOURCE_TEMPLATE_NAME_SPACE.concat(velocityTemplateId);
288 }
289
290 private VelocityContextImpl _getToolsContext(String templateContextType) {
291 TemplateControlContext templateControlContext =
292 getTemplateControlContext();
293
294 AccessControlContext accessControlContext =
295 templateControlContext.getAccessControlContext();
296 ClassLoader classLoader = templateControlContext.getClassLoader();
297
298 if (accessControlContext == null) {
299 return _doGetToolsContext(classLoader, templateContextType);
300 }
301
302 return AccessController.doPrivileged(
303 new DoGetToolsContextPrivilegedAction(
304 classLoader, templateContextType),
305 accessControlContext);
306 }
307
308 private static final String _RESOURCE_LOADER =
309 org.apache.velocity.app.VelocityEngine.RESOURCE_LOADER;
310
311 private static final String _RESOURCE_TEMPLATE_NAME_SPACE = String.valueOf(
312 ResourceManager.RESOURCE_TEMPLATE);
313
314 private static final String _RESTRICTED = "RESTRICTED";
315
316 private static final String _STANDARD = "STANDARD";
317
318 private static Log _log = LogFactoryUtil.getLog(VelocityEngineImpl.class);
319
320 private static PACL _pacl = new NoPACL();
321
322 private Map<ClassLoader, Map<String, VelocityContextImpl>>
323 _classLoaderToolsContextsMap = new ConcurrentHashMap
324 <ClassLoader, Map<String, VelocityContextImpl>>();
325 private VelocityContextImpl _restrictedToolsContext;
326 private VelocityContextImpl _standardToolsContext;
327 private org.apache.velocity.app.VelocityEngine _velocityEngine;
328
329 private static class NoPACL implements PACL {
330
331 public TemplateControlContext getTemplateControlContext() {
332 ClassLoader contextClassLoader =
333 ClassLoaderUtil.getContextClassLoader();
334
335 return new TemplateControlContext(null, contextClassLoader);
336 }
337
338 }
339
340 public static interface PACL {
341
342 public TemplateControlContext getTemplateControlContext();
343
344 }
345
346 private class DoGetTemplatePrivilegedAction
347 implements PrivilegedExceptionAction<Template> {
348
349 public DoGetTemplatePrivilegedAction(
350 String velocityTemplateId, String velocityTemplateContent,
351 String encoding) {
352
353 _velocityTemplateId = velocityTemplateId;
354 _velocityTemplateContent = velocityTemplateContent;
355 _encoding = encoding;
356 }
357
358 public Template run() throws Exception {
359 if (Validator.isNotNull(_velocityTemplateContent)) {
360 LiferayResourceCacheUtil.remove(
361 _getResourceCacheKey(_velocityTemplateId));
362
363 StringResourceRepository stringResourceRepository =
364 StringResourceLoader.getRepository();
365
366 stringResourceRepository.putStringResource(
367 _velocityTemplateId, _velocityTemplateContent);
368
369 if (_log.isDebugEnabled()) {
370 _log.debug(
371 "Added " + _velocityTemplateId +
372 " to the Velocity template repository");
373 }
374 }
375
376 return _velocityEngine.getTemplate(_velocityTemplateId, _encoding);
377 }
378
379 private String _encoding;
380 private String _velocityTemplateContent;
381 private String _velocityTemplateId;
382
383 }
384
385 private class DoGetToolsContextPrivilegedAction
386 implements PrivilegedAction<VelocityContextImpl> {
387
388 public DoGetToolsContextPrivilegedAction(
389 ClassLoader classLoader, String templateContextType) {
390
391 _classLoader = classLoader;
392 _templateContextType = templateContextType;
393 }
394
395 public VelocityContextImpl run() {
396 return _doGetToolsContext(_classLoader, _templateContextType);
397 }
398
399 private ClassLoader _classLoader;
400 private String _templateContextType;
401
402 }
403
404 }