001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: *
017: * $Header:$
018: */
019: package org.apache.beehive.controls.runtime.servlet;
020:
021: import java.util.Stack;
022: import java.io.InputStream;
023: import java.beans.beancontext.BeanContextChild;
024: import java.beans.beancontext.BeanContextServiceProvider;
025: import java.net.URL;
026: import java.net.MalformedURLException;
027: import javax.servlet.ServletContext;
028: import javax.servlet.ServletRequest;
029: import javax.servlet.ServletResponse;
030: import javax.servlet.http.HttpServletRequest;
031: import javax.servlet.http.HttpServletResponse;
032:
033: import org.apache.beehive.controls.runtime.bean.ControlContainerContext;
034: import org.apache.beehive.controls.runtime.bean.WebContextFactoryProvider;
035: import org.apache.beehive.controls.spi.context.ControlBeanContextFactory;
036:
037: /**
038: * The ServletBeanContext provides a ControlBeanContext implementation that offers services
039: * and a resource management context that is appropriate to web tier usage of controls.
040: */
041: public class ServletBeanContext extends ControlContainerContext {
042: public ServletBeanContext() {
043: //
044: // This sets the BeanContextServicesFactory instance on the ControlBeanContext and allows this
045: // CCC object to be created with a BeanContextServicesDelegate of the type returned by this factory
046: //
047: super (WebContextFactoryProvider.WEB_CONTEXT_BCS_FACTORY);
048: }
049:
050: /**
051: * Called by BeanContextSupport superclass during construction and deserialization to
052: * initialize subclass transient state
053: */
054: public void initialize() {
055: super .initialize();
056:
057: //
058: // Register the ServletService classes associated with the ServletServiceProvider
059: //
060: ServletServiceProvider ssp = ServletServiceProvider
061: .getProvider();
062: addService(ServletContext.class, ssp);
063: addService(ServletRequest.class, ssp);
064: addService(ServletResponse.class, ssp);
065: addService(HttpServletRequest.class, ssp);
066: addService(HttpServletResponse.class, ssp);
067:
068: //
069: // Register an *internal* service that is used to create ControlBeanContext objects for
070: // children of this control container
071: //
072: _bcsp = WebContextFactoryProvider.getProvider();
073: addService(ControlBeanContextFactory.class, _bcsp);
074: }
075:
076: /**
077: * Begins a new execution context, associated with a specific ServletRequest
078: */
079: public void beginContext(ServletContext context,
080: ServletRequest req, ServletResponse resp) {
081: pushRequestContext(context, req, resp);
082: super .beginContext();
083: }
084:
085: /**
086: * Ends the current execution context, and resetes the current active ServletRequest.
087: */
088: public void endContext() {
089: super .endContext();
090: popRequestContext();
091: }
092:
093: private Stack<RequestContext> getRequestStack() {
094: if (_reqStack == null)
095: _reqStack = new Stack<RequestContext>();
096:
097: return _reqStack;
098: }
099:
100: /**
101: * Pushes the current request context onto the stack
102: */
103: private synchronized void pushRequestContext(
104: ServletContext context, ServletRequest req,
105: ServletResponse resp) {
106: getRequestStack().push(new RequestContext(context, req, resp));
107: }
108:
109: /**
110: * Pops the current request context from the stack
111: */
112: private synchronized void popRequestContext() {
113: getRequestStack().pop();
114: }
115:
116: /**
117: * Returns the current request context, or null is none is available
118: */
119: private synchronized RequestContext peekRequestContext() {
120: Stack<RequestContext> reqStack = getRequestStack();
121: if (reqStack.empty())
122: return null;
123:
124: return reqStack.peek();
125: }
126:
127: /**
128: * Returns the ServletContext associated with this context (or null if not currently
129: * processing a request)
130: */
131: public ServletContext getServletContext() {
132: RequestContext reqContext = peekRequestContext();
133: if (reqContext == null)
134: return null;
135:
136: return reqContext._context;
137: }
138:
139: /**
140: * Returns the ServletRequest associated with this context (or null if not currently
141: * processing a request)
142: */
143: public ServletRequest getServletRequest() {
144: RequestContext reqContext = peekRequestContext();
145: if (reqContext == null)
146: return null;
147:
148: return reqContext._request;
149: }
150:
151: /**
152: * Returns the ServletResponse associated with this context (or null if not currently
153: * processing a request)
154: */
155: public ServletResponse getServletResponse() {
156: RequestContext reqContext = peekRequestContext();
157: if (reqContext == null)
158: return null;
159:
160: return reqContext._response;
161: }
162:
163: /**
164: * Enables/disable the use of request/response wrappers for this context. By default,
165: * wrappers are enabled if this API is not invoked.
166: */
167: public void setWrappers(boolean useWrappers) {
168: _useWrappers = useWrappers;
169: }
170:
171: /**
172: * Override BeanContext.getResourceAsStream() so it delegates to the current ServletContext.
173: *
174: * @param name the resource name
175: * @param bcc the specified child
176: * @return an <code>InputStream</code> for reading the resource, or
177: * <code>null</code> if the resource could not be found.
178: * @throws IllegalArgumentException <code>IllegalArgumentException</code> if the resource is not valid
179: */
180: public InputStream getResourceAsStream(String name,
181: BeanContextChild bcc) throws IllegalArgumentException {
182: ServletContext sc = getServletContext();
183: if (sc != null)
184: return sc.getResourceAsStream(name);
185:
186: return null;
187: }
188:
189: /**
190: * Override BeanContext.getResource() so it delegates to the current ServletContext.
191: *
192: * @param name the resource name
193: * @param bcc the specified child
194: * @return a <code>URL</code> for the named
195: * resource for the specified child
196: * @throws IllegalArgumentException <code>IllegalArgumentException</code> if the resource is not valid
197: */
198: public URL getResource(String name, BeanContextChild bcc)
199: throws IllegalArgumentException {
200: ServletContext sc = getServletContext();
201: if (sc != null) {
202: try {
203: return sc.getResource(name);
204: } catch (MalformedURLException mue) {
205: throw new IllegalArgumentException(mue.getMessage());
206: }
207: }
208:
209: return null;
210: }
211:
212: /**
213: * Override ControlBeanContext.getService(). A control bean creates its bean context using the
214: * ControlBeanContextFactory service provided by this context. A control bean will attempt to create
215: * its context before adding its self to this context as a child. This creates a chicken/egg problem since
216: * only a child of a context may request a service from it.
217: *
218: * This method provides a way to crack the chicken/egg problem by first trying to get the service using the
219: * control bean context's getService() method, and if that call returns null and the requested service is
220: * the ControlBeanContextFactory then returning an instance of the service provider.
221: *
222: * @param serviceClass
223: * @param selector
224: */
225: public <T> T getService(Class<T> serviceClass, Object selector) {
226: T service = super .getService(serviceClass, selector);
227: if (service == null
228: && serviceClass.equals(ControlBeanContextFactory.class)) {
229: return (T) _bcsp.getService(this , this , serviceClass,
230: selector);
231: }
232: return service;
233: }
234:
235: protected boolean useWrappers() {
236: return _useWrappers;
237: }
238:
239: private static class RequestContext {
240: RequestContext(ServletContext context, ServletRequest req,
241: ServletResponse resp) {
242: _context = context;
243: _request = req;
244: _response = resp;
245: }
246:
247: ServletContext _context;
248: ServletResponse _response;
249: ServletRequest _request;
250: }
251:
252: private boolean _useWrappers = true;
253: private transient Stack<RequestContext> _reqStack;
254: private transient BeanContextServiceProvider _bcsp;
255: }
|