001/*
002 * Copyright 2002-2012 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      https://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.web.servlet.view.velocity;
018
019import java.io.IOException;
020import javax.servlet.ServletContext;
021
022import org.apache.velocity.app.VelocityEngine;
023import org.apache.velocity.exception.VelocityException;
024import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
025
026import org.springframework.beans.factory.InitializingBean;
027import org.springframework.context.ResourceLoaderAware;
028import org.springframework.web.context.ServletContextAware;
029
030/**
031 * JavaBean to configure Velocity for web usage, via the "configLocation"
032 * and/or "velocityProperties" and/or "resourceLoaderPath" bean properties.
033 * The simplest way to use this class is to specify just a "resourceLoaderPath";
034 * you do not need any further configuration then.
035 *
036 * <pre class="code">
037 * &lt;bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer"&gt;
038 *   &lt;property name="resourceLoaderPath">&lt;value&gt;/WEB-INF/velocity/&lt;/value>&lt;/property&gt;
039 * &lt;/bean&gt;</pre>
040 *
041 * This bean must be included in the application context of any application
042 * using Spring's {@link VelocityView} for web MVC. It exists purely to configure
043 * Velocity; it is not meant to be referenced by application components (just
044 * internally by VelocityView). This class implements {@link VelocityConfig}
045 * in order to be found by VelocityView without depending on the bean name of
046 * this configurer. Each DispatcherServlet may define its own VelocityConfigurer
047 * if desired, potentially with different template loader paths.
048 *
049 * <p>Note that you can also refer to a pre-configured VelocityEngine
050 * instance via the "velocityEngine" property, e.g. set up by
051 * {@link org.springframework.ui.velocity.VelocityEngineFactoryBean},
052 * This allows to share a VelocityEngine for web and email usage, for example.
053 *
054 * <p>This configurer registers the "spring.vm" Velocimacro library for web views
055 * (contained in this package and thus in {@code spring.jar}), which makes
056 * all of Spring's default Velocity macros available to the views.
057 * This allows for using the Spring-provided macros such as follows:
058 *
059 * <pre class="code">
060 * #springBind("person.age")
061 * age is ${status.value}</pre>
062 *
063 * @author Rod Johnson
064 * @author Juergen Hoeller
065 * @author Darren Davison
066 * @see #setConfigLocation
067 * @see #setVelocityProperties
068 * @see #setResourceLoaderPath
069 * @see #setVelocityEngine
070 * @see VelocityView
071 * @deprecated as of Spring 4.3, in favor of FreeMarker
072 */
073@Deprecated
074public class VelocityConfigurer extends org.springframework.ui.velocity.VelocityEngineFactory
075                implements VelocityConfig, InitializingBean, ResourceLoaderAware, ServletContextAware {
076
077        /** the name of the resource loader for Spring's bind macros */
078        private static final String SPRING_MACRO_RESOURCE_LOADER_NAME = "springMacro";
079
080        /** the key for the class of Spring's bind macro resource loader */
081        private static final String SPRING_MACRO_RESOURCE_LOADER_CLASS = "springMacro.resource.loader.class";
082
083        /** the name of Spring's default bind macro library */
084        private static final String SPRING_MACRO_LIBRARY = "org/springframework/web/servlet/view/velocity/spring.vm";
085
086
087        private VelocityEngine velocityEngine;
088
089        private ServletContext servletContext;
090
091
092        /**
093         * Set a pre-configured VelocityEngine to use for the Velocity web
094         * configuration: e.g. a shared one for web and email usage, set up via
095         * {@link org.springframework.ui.velocity.VelocityEngineFactoryBean}.
096         * <p>Note that the Spring macros will <i>not</i> be enabled automatically in
097         * case of an external VelocityEngine passed in here. Make sure to include
098         * {@code spring.vm} in your template loader path in such a scenario
099         * (if there is an actual need to use those macros).
100         * <p>If this is not set, VelocityEngineFactory's properties
101         * (inherited by this class) have to be specified.
102         */
103        public void setVelocityEngine(VelocityEngine velocityEngine) {
104                this.velocityEngine = velocityEngine;
105        }
106
107        @Override
108        public void setServletContext(ServletContext servletContext) {
109                this.servletContext = servletContext;
110        }
111
112        /**
113         * Initialize VelocityEngineFactory's VelocityEngine
114         * if not overridden by a pre-configured VelocityEngine.
115         * @see #createVelocityEngine
116         * @see #setVelocityEngine
117         */
118        @Override
119        public void afterPropertiesSet() throws IOException, VelocityException {
120                if (this.velocityEngine == null) {
121                        this.velocityEngine = createVelocityEngine();
122                }
123        }
124
125        /**
126         * Provides a ClasspathResourceLoader in addition to any default or user-defined
127         * loader in order to load the spring Velocity macros from the class path.
128         * @see org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
129         */
130        @Override
131        protected void postProcessVelocityEngine(VelocityEngine velocityEngine) {
132                velocityEngine.setApplicationAttribute(ServletContext.class.getName(), this.servletContext);
133                velocityEngine.setProperty(
134                                SPRING_MACRO_RESOURCE_LOADER_CLASS, ClasspathResourceLoader.class.getName());
135                velocityEngine.addProperty(
136                                VelocityEngine.RESOURCE_LOADER, SPRING_MACRO_RESOURCE_LOADER_NAME);
137                velocityEngine.addProperty(
138                                VelocityEngine.VM_LIBRARY, SPRING_MACRO_LIBRARY);
139
140                if (logger.isInfoEnabled()) {
141                        logger.info("ClasspathResourceLoader with name '" + SPRING_MACRO_RESOURCE_LOADER_NAME +
142                                        "' added to configured VelocityEngine");
143                }
144        }
145
146        @Override
147        public VelocityEngine getVelocityEngine() {
148                return this.velocityEngine;
149        }
150
151}