001/*
002 * Copyright 2002-2010 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.lang.reflect.Method;
020import java.util.Map;
021import javax.servlet.http.HttpServletRequest;
022import javax.servlet.http.HttpServletResponse;
023
024import org.apache.velocity.VelocityContext;
025import org.apache.velocity.context.Context;
026
027import org.springframework.util.ClassUtils;
028import org.springframework.util.ReflectionUtils;
029
030/**
031 * {@link VelocityView} subclass which adds support for Velocity Tools toolboxes
032 * and Velocity Tools ViewTool callbacks / Velocity Tools 1.3 init methods.
033 *
034 * <p>Specify a "toolboxConfigLocation", for example "/WEB-INF/toolbox.xml",
035 * to automatically load a Velocity Tools toolbox definition file and expose
036 * all defined tools in the specified scopes. If no config location is
037 * specified, no toolbox will be loaded and exposed.
038 *
039 * <p>This view will always create a special Velocity context, namely an
040 * instance of the ChainedContext class which is part of the view package
041 * of Velocity tools. This allows to use tools from the view package of
042 * Velocity Tools, like LinkTool, which need to be initialized with a special
043 * context that implements the ViewContext interface (i.e. a ChainedContext).
044 *
045 * <p>This view also checks tools that are specified as "toolAttributes":
046 * If they implement the ViewTool interface, they will get initialized with
047 * the Velocity context. This allows tools from the view package of Velocity
048 * Tools, such as LinkTool, to be defined as
049 * {@link #setToolAttributes "toolAttributes"} on a VelocityToolboxView,
050 * instead of in a separate toolbox XML file.
051 *
052 * <p>This is a separate class mainly to avoid a required dependency on
053 * the view package of Velocity Tools in {@link VelocityView} itself.
054 * As of Spring 3.0, this class requires Velocity Tools 1.3 or higher.
055 *
056 * @author Juergen Hoeller
057 * @since 1.1.3
058 * @see #setToolboxConfigLocation
059 * @see #initTool
060 * @see org.apache.velocity.tools.view.context.ViewContext
061 * @see org.apache.velocity.tools.view.context.ChainedContext
062 * @deprecated as of Spring 4.3, in favor of FreeMarker
063 */
064@Deprecated
065public class VelocityToolboxView extends VelocityView {
066
067        private String toolboxConfigLocation;
068
069
070        /**
071         * Set a Velocity Toolbox config location, for example "/WEB-INF/toolbox.xml",
072         * to automatically load a Velocity Tools toolbox definition file and expose
073         * all defined tools in the specified scopes. If no config location is
074         * specified, no toolbox will be loaded and exposed.
075         * <p>The specified location string needs to refer to a ServletContext
076         * resource, as expected by ServletToolboxManager which is part of
077         * the view package of Velocity Tools.
078         * @see org.apache.velocity.tools.view.servlet.ServletToolboxManager#getInstance
079         */
080        public void setToolboxConfigLocation(String toolboxConfigLocation) {
081                this.toolboxConfigLocation = toolboxConfigLocation;
082        }
083
084        /**
085         * Return the Velocity Toolbox config location, if any.
086         */
087        protected String getToolboxConfigLocation() {
088                return this.toolboxConfigLocation;
089        }
090
091
092        /**
093         * Overridden to create a ChainedContext, which is part of the view package
094         * of Velocity Tools, as special context. ChainedContext is needed for
095         * initialization of ViewTool instances.
096         * @see #initTool
097         */
098        @Override
099        @SuppressWarnings({ "rawtypes", "unchecked" })
100        protected Context createVelocityContext(
101                        Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
102
103                // Create a ChainedContext instance.
104                org.apache.velocity.tools.view.context.ChainedContext velocityContext =
105                                new org.apache.velocity.tools.view.context.ChainedContext(
106                                                new VelocityContext(model), getVelocityEngine(), request, response, getServletContext());
107
108                // Load a Velocity Tools toolbox, if necessary.
109                if (getToolboxConfigLocation() != null) {
110                        org.apache.velocity.tools.view.ToolboxManager toolboxManager =
111                                        org.apache.velocity.tools.view.servlet.ServletToolboxManager.getInstance(
112                                                        getServletContext(), getToolboxConfigLocation());
113                        Map toolboxContext = toolboxManager.getToolbox(velocityContext);
114                        velocityContext.setToolbox(toolboxContext);
115                }
116
117                return velocityContext;
118        }
119
120        /**
121         * Overridden to check for the ViewContext interface which is part of the
122         * view package of Velocity Tools. This requires a special Velocity context,
123         * like ChainedContext as set up by {@link #createVelocityContext} in this class.
124         */
125        @Override
126        protected void initTool(Object tool, Context velocityContext) throws Exception {
127                // Velocity Tools 1.3: a class-level "init(Object)" method.
128                Method initMethod = ClassUtils.getMethodIfAvailable(tool.getClass(), "init", Object.class);
129                if (initMethod != null) {
130                        ReflectionUtils.invokeMethod(initMethod, tool, velocityContext);
131                }
132        }
133
134}