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:
018: package org.apache.catalina.core;
019:
020: import java.io.IOException;
021:
022: import javax.servlet.ServletException;
023: import javax.servlet.ServletRequest;
024: import javax.servlet.ServletRequestEvent;
025: import javax.servlet.ServletRequestListener;
026: import javax.servlet.http.HttpServletResponse;
027:
028: import org.apache.catalina.CometEvent;
029: import org.apache.catalina.Container;
030: import org.apache.catalina.Globals;
031: import org.apache.catalina.Wrapper;
032: import org.apache.catalina.connector.Request;
033: import org.apache.catalina.connector.Response;
034: import org.apache.catalina.util.StringManager;
035: import org.apache.catalina.valves.ValveBase;
036: import org.apache.tomcat.util.buf.MessageBytes;
037:
038: /**
039: * Valve that implements the default basic behavior for the
040: * <code>StandardContext</code> container implementation.
041: * <p>
042: * <b>USAGE CONSTRAINT</b>: This implementation is likely to be useful only
043: * when processing HTTP requests.
044: *
045: * @author Craig R. McClanahan
046: * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
047: */
048:
049: final class StandardContextValve extends ValveBase {
050:
051: // ----------------------------------------------------- Instance Variables
052:
053: /**
054: * The descriptive information related to this implementation.
055: */
056: private static final String info = "org.apache.catalina.core.StandardContextValve/1.0";
057:
058: /**
059: * The string manager for this package.
060: */
061: private static final StringManager sm = StringManager
062: .getManager(Constants.Package);
063:
064: private StandardContext context = null;
065:
066: // ------------------------------------------------------------- Properties
067:
068: /**
069: * Return descriptive information about this Valve implementation.
070: */
071: public String getInfo() {
072:
073: return (info);
074:
075: }
076:
077: // --------------------------------------------------------- Public Methods
078:
079: /**
080: * Cast to a StandardContext right away, as it will be needed later.
081: *
082: * @see org.apache.catalina.Contained#setContainer(org.apache.catalina.Container)
083: */
084: public void setContainer(Container container) {
085: super .setContainer(container);
086: context = (StandardContext) container;
087: }
088:
089: /**
090: * Select the appropriate child Wrapper to process this request,
091: * based on the specified request URI. If no matching Wrapper can
092: * be found, return an appropriate HTTP error.
093: *
094: * @param request Request to be processed
095: * @param response Response to be produced
096: * @param valveContext Valve context used to forward to the next Valve
097: *
098: * @exception IOException if an input/output error occurred
099: * @exception ServletException if a servlet error occurred
100: */
101: public final void invoke(Request request, Response response)
102: throws IOException, ServletException {
103:
104: // Disallow any direct access to resources under WEB-INF or META-INF
105: MessageBytes requestPathMB = request.getRequestPathMB();
106: if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
107: || (requestPathMB.equalsIgnoreCase("/META-INF"))
108: || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
109: || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
110: String requestURI = request.getDecodedRequestURI();
111: notFound(requestURI, response);
112: return;
113: }
114:
115: // Wait if we are reloading
116: while (context.getPaused()) {
117: try {
118: Thread.sleep(1000);
119: } catch (InterruptedException e) {
120: ;
121: }
122: }
123:
124: // Select the Wrapper to be used for this Request
125: Wrapper wrapper = request.getWrapper();
126: if (wrapper == null) {
127: String requestURI = request.getDecodedRequestURI();
128: notFound(requestURI, response);
129: return;
130: }
131:
132: // Normal request processing
133: Object instances[] = context.getApplicationEventListeners();
134:
135: ServletRequestEvent event = null;
136:
137: if ((instances != null) && (instances.length > 0)) {
138: event = new ServletRequestEvent(
139: ((StandardContext) container).getServletContext(),
140: request.getRequest());
141: // create pre-service event
142: for (int i = 0; i < instances.length; i++) {
143: if (instances[i] == null)
144: continue;
145: if (!(instances[i] instanceof ServletRequestListener))
146: continue;
147: ServletRequestListener listener = (ServletRequestListener) instances[i];
148: try {
149: listener.requestInitialized(event);
150: } catch (Throwable t) {
151: container
152: .getLogger()
153: .error(
154: sm
155: .getString(
156: "standardContext.requestListener.requestInit",
157: instances[i]
158: .getClass()
159: .getName()),
160: t);
161: ServletRequest sreq = request.getRequest();
162: sreq.setAttribute(Globals.EXCEPTION_ATTR, t);
163: return;
164: }
165: }
166: }
167:
168: wrapper.getPipeline().getFirst().invoke(request, response);
169:
170: if ((instances != null) && (instances.length > 0)) {
171: // create post-service event
172: for (int i = 0; i < instances.length; i++) {
173: if (instances[i] == null)
174: continue;
175: if (!(instances[i] instanceof ServletRequestListener))
176: continue;
177: ServletRequestListener listener = (ServletRequestListener) instances[i];
178: try {
179: listener.requestDestroyed(event);
180: } catch (Throwable t) {
181: container
182: .getLogger()
183: .error(
184: sm
185: .getString(
186: "standardContext.requestListener.requestDestroy",
187: instances[i]
188: .getClass()
189: .getName()),
190: t);
191: ServletRequest sreq = request.getRequest();
192: sreq.setAttribute(Globals.EXCEPTION_ATTR, t);
193: }
194: }
195: }
196:
197: }
198:
199: /**
200: * Select the appropriate child Wrapper to process this request,
201: * based on the specified request URI. If no matching Wrapper can
202: * be found, return an appropriate HTTP error.
203: *
204: * @param request Request to be processed
205: * @param response Response to be produced
206: * @param valveContext Valve context used to forward to the next Valve
207: *
208: * @exception IOException if an input/output error occurred
209: * @exception ServletException if a servlet error occurred
210: */
211: public final void event(Request request, Response response,
212: CometEvent event) throws IOException, ServletException {
213:
214: // Select the Wrapper to be used for this Request
215: Wrapper wrapper = request.getWrapper();
216:
217: // Normal request processing
218: // FIXME: This could be an addition to the core API too
219: /*
220: Object instances[] = context.getApplicationEventListeners();
221:
222: ServletRequestEvent event = null;
223:
224: if ((instances != null)
225: && (instances.length > 0)) {
226: event = new ServletRequestEvent
227: (((StandardContext) container).getServletContext(),
228: request.getRequest());
229: // create pre-service event
230: for (int i = 0; i < instances.length; i++) {
231: if (instances[i] == null)
232: continue;
233: if (!(instances[i] instanceof ServletRequestListener))
234: continue;
235: ServletRequestListener listener =
236: (ServletRequestListener) instances[i];
237: try {
238: listener.requestInitialized(event);
239: } catch (Throwable t) {
240: container.getLogger().error(sm.getString("requestListenerValve.requestInit",
241: instances[i].getClass().getName()), t);
242: ServletRequest sreq = request.getRequest();
243: sreq.setAttribute(Globals.EXCEPTION_ATTR,t);
244: return;
245: }
246: }
247: }
248: */
249:
250: wrapper.getPipeline().getFirst()
251: .event(request, response, event);
252:
253: /*
254: if ((instances !=null ) &&
255: (instances.length > 0)) {
256: // create post-service event
257: for (int i = 0; i < instances.length; i++) {
258: if (instances[i] == null)
259: continue;
260: if (!(instances[i] instanceof ServletRequestListener))
261: continue;
262: ServletRequestListener listener =
263: (ServletRequestListener) instances[i];
264: try {
265: listener.requestDestroyed(event);
266: } catch (Throwable t) {
267: container.getLogger().error(sm.getString("requestListenerValve.requestDestroy",
268: instances[i].getClass().getName()), t);
269: ServletRequest sreq = request.getRequest();
270: sreq.setAttribute(Globals.EXCEPTION_ATTR,t);
271: }
272: }
273: }
274: */
275:
276: }
277:
278: // -------------------------------------------------------- Private Methods
279:
280: /**
281: * Report a "not found" error for the specified resource. FIXME: We
282: * should really be using the error reporting settings for this web
283: * application, but currently that code runs at the wrapper level rather
284: * than the context level.
285: *
286: * @param requestURI The request URI for the requested resource
287: * @param response The response we are creating
288: */
289: private void notFound(String requestURI,
290: HttpServletResponse response) {
291:
292: try {
293: response.sendError(HttpServletResponse.SC_NOT_FOUND,
294: requestURI);
295: } catch (IllegalStateException e) {
296: ;
297: } catch (IOException e) {
298: ;
299: }
300:
301: }
302:
303: }
|