/*
* Copyright 2002-2008 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.web.servlet.view.velocity;
import java.io.IOException;
import javax.servlet.ServletContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.VelocityException;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.ui.velocity.VelocityEngineFactory;
import org.springframework.web.context.ServletContextAware;
/**
* JavaBean to configure Velocity for web usage, via the "configLocation"
* and/or "velocityProperties" and/or "resourceLoaderPath" bean properties.
* The simplest way to use this class is to specify just a "resourceLoaderPath";
* you do not need any further configuration then.
*
* <pre class="code">
* <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
* <property name="resourceLoaderPath"><value>/WEB-INF/velocity/</value></property>
* </bean></pre>
*
* This bean must be included in the application context of any application
* using Spring's {@link VelocityView} for web MVC. It exists purely to configure
* Velocity; it is not meant to be referenced by application components (just
* internally by VelocityView). This class implements {@link VelocityConfig}
* in order to be found by VelocityView without depending on the bean name of
* this configurer. Each DispatcherServlet may define its own VelocityConfigurer
* if desired, potentially with different template loader paths.
*
* <p>Note that you can also refer to a pre-configured VelocityEngine
* instance via the "velocityEngine" property, e.g. set up by
* {@link org.springframework.ui.velocity.VelocityEngineFactoryBean},
* This allows to share a VelocityEngine for web and email usage, for example.
*
* <p>This configurer registers the "spring.vm" Velocimacro library for web views
* (contained in this package and thus in <code>spring.jar</code>), which makes
* all of Spring's default Velocity macros available to the views.
* This allows for using the Spring-provided macros such as follows:
*
* <pre class="code">
* #springBind("person.age")
* age is ${status.value}</pre>
*
* @author Rod Johnson
* @author Juergen Hoeller
* @author Darren Davison
* @see #setConfigLocation
* @see #setVelocityProperties
* @see #setResourceLoaderPath
* @see #setVelocityEngine
* @see VelocityView
*/
public class VelocityConfigurer extends VelocityEngineFactory
implements VelocityConfig, InitializingBean, ResourceLoaderAware, ServletContextAware {
/** the name of the resource loader for Spring's bind macros */
private static final String SPRING_MACRO_RESOURCE_LOADER_NAME = "springMacro";
/** the key for the class of Spring's bind macro resource loader */
private static final String SPRING_MACRO_RESOURCE_LOADER_CLASS = "springMacro.resource.loader.class";
/** the name of Spring's default bind macro library */
private static final String SPRING_MACRO_LIBRARY = "org/springframework/web/servlet/view/velocity/spring.vm";
private VelocityEngine velocityEngine;
private ServletContext servletContext;
/**
* Set a pre-configured VelocityEngine to use for the Velocity web
* configuration: e.g. a shared one for web and email usage, set up via
* {@link org.springframework.ui.velocity.VelocityEngineFactoryBean}.
* <p>Note that the Spring macros will <i>not</i> be enabled automatically in
* case of an external VelocityEngine passed in here. Make sure to include
* <code>spring.vm</code> in your template loader path in such a scenario
* (if there is an actual need to use those macros).
* <p>If this is not set, VelocityEngineFactory's properties
* (inherited by this class) have to be specified.
*/
public void setVelocityEngine(VelocityEngine velocityEngine) {
this.velocityEngine = velocityEngine;
}
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
/**
* Initialize VelocityEngineFactory's VelocityEngine
* if not overridden by a pre-configured VelocityEngine.
* @see #createVelocityEngine
* @see #setVelocityEngine
*/
public void afterPropertiesSet() throws IOException, VelocityException {
if (this.velocityEngine == null) {
this.velocityEngine = createVelocityEngine();
}
}
/**
* Provides a ClasspathResourceLoader in addition to any default or user-defined
* loader in order to load the spring Velocity macros from the class path.
* @see org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
*/
@Override
protected void postProcessVelocityEngine(VelocityEngine velocityEngine) {
velocityEngine.setApplicationAttribute(ServletContext.class.getName(), this.servletContext);
velocityEngine.setProperty(
SPRING_MACRO_RESOURCE_LOADER_CLASS, ClasspathResourceLoader.class.getName());
velocityEngine.addProperty(
VelocityEngine.RESOURCE_LOADER, SPRING_MACRO_RESOURCE_LOADER_NAME);
velocityEngine.addProperty(
VelocityEngine.VM_LIBRARY, SPRING_MACRO_LIBRARY);
if (logger.isInfoEnabled()) {
logger.info("ClasspathResourceLoader with name '" + SPRING_MACRO_RESOURCE_LOADER_NAME +
"' added to configured VelocityEngine");
}
}
public VelocityEngine getVelocityEngine() {
return this.velocityEngine;
}
}
|