/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. */ package com.liferay.portal.template.velocity.internal; import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil; import com.liferay.portal.kernel.cache.SingleVMPool; import com.liferay.portal.kernel.model.Layout; import com.liferay.portal.kernel.template.Template; import com.liferay.portal.kernel.template.TemplateConstants; import com.liferay.portal.kernel.template.TemplateException; import com.liferay.portal.kernel.template.TemplateManager; import com.liferay.portal.kernel.template.TemplateResource; import com.liferay.portal.kernel.template.TemplateResourceLoader; import com.liferay.portal.kernel.util.StringUtil; import com.liferay.portal.template.BaseSingleTemplateManager; import com.liferay.portal.template.RestrictedTemplate; import com.liferay.portal.template.TemplateContextHelper; import com.liferay.portal.template.velocity.configuration.VelocityEngineConfiguration; import com.liferay.taglib.util.VelocityTaglib; import com.liferay.taglib.util.VelocityTaglibImpl; import java.lang.reflect.Method; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.collections.ExtendedProperties; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; import org.apache.velocity.util.introspection.SecureUberspector; import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.ConfigurationPolicy; import org.osgi.service.component.annotations.Modified; import org.osgi.service.component.annotations.Reference; /** * @author Raymond Augé * @author Peter Fellwock */ @Component( configurationPid = "com.liferay.portal.template.velocity.configuration.VelocityEngineConfiguration", configurationPolicy = ConfigurationPolicy.OPTIONAL, immediate = true, property = {"language.type=" + TemplateConstants.LANG_TYPE_VM}, service = TemplateManager.class ) public class VelocityManager extends BaseSingleTemplateManager { @Override public void addTaglibTheme( Map<String, Object> contextObjects, String themeName, HttpServletRequest request, HttpServletResponse response) { VelocityTaglib velocityTaglib = new VelocityTaglibImpl( request.getServletContext(), request, response, contextObjects); contextObjects.put(themeName, velocityTaglib); contextObjects.put("velocityTaglib_layoutIcon", _layoutIconMethod); // Legacy support contextObjects.put("theme", velocityTaglib); } @Override public void destroy() { if (_velocityEngine == null) { return; } _velocityEngine = null; templateContextHelper.removeAllHelperUtilities(); templateContextHelper = null; } @Override public void destroy(ClassLoader classLoader) { templateContextHelper.removeHelperUtilities(classLoader); } @Override public String getName() { return TemplateConstants.LANG_TYPE_VM; } @Override public String[] getRestrictedVariables() { return _velocityEngineConfiguration.restrictedVariables(); } @Override public void init() throws TemplateException { if (_velocityEngine != null) { return; } Thread currentThread = Thread.currentThread(); ClassLoader contextClassLoader = currentThread.getContextClassLoader(); Class<?> clazz = getClass(); currentThread.setContextClassLoader(clazz.getClassLoader()); try { _velocityEngine = new VelocityEngine(); ExtendedProperties extendedProperties = new FastExtendedProperties(); extendedProperties.setProperty( VelocityEngine.DIRECTIVE_IF_TOSTRING_NULLCHECK, String.valueOf( _velocityEngineConfiguration. directiveIfToStringNullCheck())); extendedProperties.setProperty( VelocityEngine.EVENTHANDLER_METHODEXCEPTION, LiferayMethodExceptionEventHandler.class.getName()); extendedProperties.setProperty( RuntimeConstants.INTROSPECTOR_RESTRICT_CLASSES, StringUtil.merge( _velocityEngineConfiguration.restrictedClasses())); extendedProperties.setProperty( RuntimeConstants.INTROSPECTOR_RESTRICT_PACKAGES, StringUtil.merge( _velocityEngineConfiguration.restrictedPackages())); extendedProperties.setProperty( RuntimeConstants.PARSER_POOL_CLASS, VelocityParserPool.class.getName()); extendedProperties.setProperty( VelocityEngine.RESOURCE_LOADER, "liferay"); extendedProperties.setProperty( "liferay." + VelocityEngine.RESOURCE_LOADER + "." + VelocityTemplateResourceLoader.class.getName(), templateResourceLoader); boolean cacheEnabled = false; if (_velocityEngineConfiguration. resourceModificationCheckInterval() != 0) { cacheEnabled = true; } extendedProperties.setProperty( "liferay." + VelocityEngine.RESOURCE_LOADER + ".cache", String.valueOf(cacheEnabled)); extendedProperties.setProperty( "liferay." + VelocityEngine.RESOURCE_LOADER + ".class", LiferayResourceLoader.class.getName()); extendedProperties.setProperty( "liferay." + VelocityEngine.RESOURCE_LOADER + ".resourceModificationCheckInterval", _velocityEngineConfiguration. resourceModificationCheckInterval() + ""); extendedProperties.setProperty( VelocityEngine.RESOURCE_MANAGER_CLASS, LiferayResourceManager.class.getName()); extendedProperties.setProperty( "liferay." + VelocityEngine.RESOURCE_MANAGER_CLASS + ".resourceModificationCheckInterval", _velocityEngineConfiguration. resourceModificationCheckInterval() + ""); extendedProperties.setProperty( VelocityTemplateResourceLoader.class.getName(), templateResourceLoader); extendedProperties.setProperty( VelocityEngine.RUNTIME_LOG_LOGSYSTEM_CLASS, _velocityEngineConfiguration.logger()); extendedProperties.setProperty( VelocityEngine.RUNTIME_LOG_LOGSYSTEM + ".log4j.category", _velocityEngineConfiguration.loggerCategory()); extendedProperties.setProperty( RuntimeConstants.UBERSPECT_CLASSNAME, SecureUberspector.class.getName()); extendedProperties.setProperty( VelocityEngine.VM_LIBRARY, StringUtil.merge( _velocityEngineConfiguration.velocimacroLibrary())); extendedProperties.setProperty( VelocityEngine.VM_LIBRARY_AUTORELOAD, String.valueOf(!cacheEnabled)); extendedProperties.setProperty( VelocityEngine.VM_PERM_ALLOW_INLINE_REPLACE_GLOBAL, String.valueOf(!cacheEnabled)); _velocityEngine.setExtendedProperties(extendedProperties); _velocityEngine.init(); } catch (Exception e) { throw new TemplateException(e); } finally { currentThread.setContextClassLoader(contextClassLoader); } } @Override @Reference(service = VelocityTemplateContextHelper.class, unbind = "-") public void setTemplateContextHelper( TemplateContextHelper templateContextHelper) { super.setTemplateContextHelper(templateContextHelper); } @Override @Reference(service = VelocityTemplateResourceLoader.class, unbind = "-") public void setTemplateResourceLoader( TemplateResourceLoader templateResourceLoader) { super.setTemplateResourceLoader(templateResourceLoader); } @Activate @Modified protected void activate(Map<String, Object> properties) { _velocityEngineConfiguration = ConfigurableUtil.createConfigurable( VelocityEngineConfiguration.class, properties); } @Override protected Template doGetTemplate( TemplateResource templateResource, TemplateResource errorTemplateResource, boolean restricted, Map<String, Object> helperUtilities, boolean privileged) { Template template = new VelocityTemplate( templateResource, errorTemplateResource, helperUtilities, _velocityEngine, templateContextHelper, _velocityEngineConfiguration.resourceModificationCheckInterval(), privileged); if (restricted) { template = new RestrictedTemplate( template, templateContextHelper.getRestrictedVariables()); } return template; } @Reference(unbind = "-") protected void setSingleVMPool(SingleVMPool singleVMPool) { } private static final Method _layoutIconMethod; private static volatile VelocityEngineConfiguration _velocityEngineConfiguration; static { try { _layoutIconMethod = VelocityTaglib.class.getMethod( "layoutIcon", new Class<?>[] {Layout.class}); } catch (NoSuchMethodException nsme) { throw new ExceptionInInitializerError(nsme); } } private VelocityEngine _velocityEngine; }