001 /*******************************************************************************
002 * Copyright (C) PicoContainer Organization. All rights reserved.
003 * ---------------------------------------------------------------------------
004 * The software in this package is published under the terms of the BSD style
005 * license a copy of which has been included with this distribution in the
006 * LICENSE.txt file.
007 ******************************************************************************/
008 package org.picocontainer.web.webwork.velocity;
009
010 import org.apache.velocity.Template;
011 import org.apache.velocity.VelocityContext;
012 import org.apache.velocity.context.Context;
013 import org.apache.velocity.tools.view.servlet.VelocityViewServlet;
014 import org.picocontainer.PicoContainer;
015 import org.picocontainer.MutablePicoContainer;
016 import org.picocontainer.containers.EmptyPicoContainer;
017 import org.picocontainer.web.PicoServletContainerFilter;
018
019 import webwork.action.ServletActionContext;
020 import webwork.util.ServletValueStack;
021 import webwork.view.velocity.WebWorkUtil;
022
023 /**
024 * velocity integration servlet. integrates container hieararchy into velocity
025 * context as well webwork specific objects. This servlet is not derived from
026 * standart webwork velocity servlet because it inherits from obsolete velocity
027 * servlet ( which does not allow resource loading from webapp ). acc
028 * configuration is done like original velocity servlet does
029 *
030 * @author Konstantin Pribluda
031 */
032 @SuppressWarnings("serial")
033 public final class WebWorkVelocityServlet extends VelocityViewServlet {
034
035 public static class ServletFilter extends PicoServletContainerFilter {
036 private static ThreadLocal<MutablePicoContainer> currentRequestContainer = new ThreadLocal<MutablePicoContainer>();
037 private static ThreadLocal<MutablePicoContainer> currentSessionContainer = new ThreadLocal<MutablePicoContainer>();
038 private static ThreadLocal<MutablePicoContainer> currentAppContainer = new ThreadLocal<MutablePicoContainer>();
039
040 protected void setAppContainer(MutablePicoContainer container) {
041 currentAppContainer.set(container);
042 }
043 protected void setRequestContainer(MutablePicoContainer container) {
044 currentRequestContainer.set(container);
045 }
046 protected void setSessionContainer(MutablePicoContainer container) {
047 currentSessionContainer.set(container);
048 }
049
050 protected static MutablePicoContainer getRequestContainerForThread() {
051 return currentRequestContainer.get();
052 }
053 protected static MutablePicoContainer getSessionContainerForThread() {
054 return currentSessionContainer.get();
055 }
056 protected static MutablePicoContainer getApplicationContainerForThread() {
057 return currentAppContainer.get();
058 }
059 }
060
061 static final String WEBWORK_UTIL = "webwork";
062 // those have to be removed once dependency problem is solved.
063 // will bomb anyway.
064 static final String REQUEST = "req";
065 static final String RESPONSE = "res";
066
067 static final EmptyPicoContainer emptyContainer = new EmptyPicoContainer();
068
069 protected Context createContext(javax.servlet.http.HttpServletRequest request,
070 javax.servlet.http.HttpServletResponse response) {
071 Context ctx = new NanocontainerVelocityContext(ServletFilter.getRequestContainerForThread(),
072 ServletValueStack.getStack(request));
073 ctx.put(REQUEST, request);
074 ctx.put(RESPONSE, response);
075 return ctx;
076 }
077
078 /**
079 * Get the template to show.
080 */
081 protected Template handleRequest(javax.servlet.http.HttpServletRequest aRequest,
082 javax.servlet.http.HttpServletResponse aResponse, Context ctx) throws java.lang.Exception {
083 // Bind standard WebWork utility into context
084
085 ServletActionContext.setContext(aRequest, aResponse, getServletContext(), null);
086 ctx.put(WEBWORK_UTIL, new WebWorkUtil(ctx));
087
088 String servletPath = (String) aRequest.getAttribute("javax.servlet.include.servlet_path");
089 if (servletPath == null)
090 servletPath = aRequest.getServletPath();
091 return getTemplate(servletPath);
092 }
093
094 static final class NanocontainerVelocityContext extends VelocityContext {
095 final PicoContainer container;
096 final ServletValueStack stack;
097
098 NanocontainerVelocityContext(PicoContainer container, ServletValueStack stack) {
099 this.container = container != null ? container : emptyContainer;
100 this.stack = stack;
101 }
102
103 public boolean internalContainsKey(java.lang.Object key) {
104 boolean contains = super.internalContainsKey(key);
105 if (contains)
106 return contains;
107
108 contains = stack.test(key.toString());
109 if (contains)
110 return contains;
111
112 return container.getComponentAdapter(key) != null;
113 }
114
115 public Object internalGet(String key) {
116 if (super.internalContainsKey(key))
117 return super.internalGet(key);
118
119 if (stack.test(key))
120 return stack.findValue(key);
121
122 return container.getComponent(key);
123 }
124 }
125 }