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