1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18
19 package org.apache.catalina.core;
20
21
22 import java.io.IOException;
23
24 import javax.servlet.ServletException;
25 import javax.servlet.ServletRequest;
26 import javax.servlet.ServletRequestEvent;
27 import javax.servlet.ServletRequestListener;
28 import javax.servlet.http.HttpServletResponse;
29
30 import org.apache.catalina.CometEvent;
31 import org.apache.catalina.Container;
32 import org.apache.catalina.Globals;
33 import org.apache.catalina.Wrapper;
34 import org.apache.catalina.connector.Request;
35 import org.apache.catalina.connector.Response;
36 import org.apache.catalina.util.StringManager;
37 import org.apache.catalina.valves.ValveBase;
38 import org.apache.tomcat.util.buf.MessageBytes;
39
40 /**
41 * Valve that implements the default basic behavior for the
42 * <code>StandardContext</code> container implementation.
43 * <p>
44 * <b>USAGE CONSTRAINT</b>: This implementation is likely to be useful only
45 * when processing HTTP requests.
46 *
47 * @author Craig R. McClanahan
48 * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
49 */
50
51 final class StandardContextValve
52 extends ValveBase {
53
54
55 // ----------------------------------------------------- Instance Variables
56
57
58 /**
59 * The descriptive information related to this implementation.
60 */
61 private static final String info =
62 "org.apache.catalina.core.StandardContextValve/1.0";
63
64
65 /**
66 * The string manager for this package.
67 */
68 private static final StringManager sm =
69 StringManager.getManager(Constants.Package);
70
71
72 private StandardContext context = null;
73
74
75 // ------------------------------------------------------------- Properties
76
77
78 /**
79 * Return descriptive information about this Valve implementation.
80 */
81 public String getInfo() {
82
83 return (info);
84
85 }
86
87
88 // --------------------------------------------------------- Public Methods
89
90
91 /**
92 * Cast to a StandardContext right away, as it will be needed later.
93 *
94 * @see org.apache.catalina.Contained#setContainer(org.apache.catalina.Container)
95 */
96 public void setContainer(Container container) {
97 super.setContainer(container);
98 context = (StandardContext) container;
99 }
100
101
102 /**
103 * Select the appropriate child Wrapper to process this request,
104 * based on the specified request URI. If no matching Wrapper can
105 * be found, return an appropriate HTTP error.
106 *
107 * @param request Request to be processed
108 * @param response Response to be produced
109 * @param valveContext Valve context used to forward to the next Valve
110 *
111 * @exception IOException if an input/output error occurred
112 * @exception ServletException if a servlet error occurred
113 */
114 public final void invoke(Request request, Response response)
115 throws IOException, ServletException {
116
117 // Disallow any direct access to resources under WEB-INF or META-INF
118 MessageBytes requestPathMB = request.getRequestPathMB();
119 if ((requestPathMB.startsWithIgnoreCase("/META-INF/", 0))
120 || (requestPathMB.equalsIgnoreCase("/META-INF"))
121 || (requestPathMB.startsWithIgnoreCase("/WEB-INF/", 0))
122 || (requestPathMB.equalsIgnoreCase("/WEB-INF"))) {
123 String requestURI = request.getDecodedRequestURI();
124 notFound(requestURI, response);
125 return;
126 }
127
128 // Wait if we are reloading
129 while (context.getPaused()) {
130 try {
131 Thread.sleep(1000);
132 } catch (InterruptedException e) {
133 ;
134 }
135 }
136
137 // Select the Wrapper to be used for this Request
138 Wrapper wrapper = request.getWrapper();
139 if (wrapper == null) {
140 String requestURI = request.getDecodedRequestURI();
141 notFound(requestURI, response);
142 return;
143 }
144
145 // Normal request processing
146 Object instances[] = context.getApplicationEventListeners();
147
148 ServletRequestEvent event = null;
149
150 if ((instances != null)
151 && (instances.length > 0)) {
152 event = new ServletRequestEvent
153 (((StandardContext) container).getServletContext(),
154 request.getRequest());
155 // create pre-service event
156 for (int i = 0; i < instances.length; i++) {
157 if (instances[i] == null)
158 continue;
159 if (!(instances[i] instanceof ServletRequestListener))
160 continue;
161 ServletRequestListener listener =
162 (ServletRequestListener) instances[i];
163 try {
164 listener.requestInitialized(event);
165 } catch (Throwable t) {
166 container.getLogger().error(sm.getString("standardContext.requestListener.requestInit",
167 instances[i].getClass().getName()), t);
168 ServletRequest sreq = request.getRequest();
169 sreq.setAttribute(Globals.EXCEPTION_ATTR,t);
170 return;
171 }
172 }
173 }
174
175 wrapper.getPipeline().getFirst().invoke(request, response);
176
177 if ((instances !=null ) &&
178 (instances.length > 0)) {
179 // create post-service event
180 for (int i = 0; i < instances.length; i++) {
181 if (instances[i] == null)
182 continue;
183 if (!(instances[i] instanceof ServletRequestListener))
184 continue;
185 ServletRequestListener listener =
186 (ServletRequestListener) instances[i];
187 try {
188 listener.requestDestroyed(event);
189 } catch (Throwable t) {
190 container.getLogger().error(sm.getString("standardContext.requestListener.requestDestroy",
191 instances[i].getClass().getName()), t);
192 ServletRequest sreq = request.getRequest();
193 sreq.setAttribute(Globals.EXCEPTION_ATTR,t);
194 }
195 }
196 }
197
198 }
199
200
201 /**
202 * Select the appropriate child Wrapper to process this request,
203 * based on the specified request URI. If no matching Wrapper can
204 * be found, return an appropriate HTTP error.
205 *
206 * @param request Request to be processed
207 * @param response Response to be produced
208 * @param valveContext Valve context used to forward to the next Valve
209 *
210 * @exception IOException if an input/output error occurred
211 * @exception ServletException if a servlet error occurred
212 */
213 public final void event(Request request, Response response, CometEvent event)
214 throws IOException, ServletException {
215
216 // Select the Wrapper to be used for this Request
217 Wrapper wrapper = request.getWrapper();
218
219 // Normal request processing
220 // FIXME: This could be an addition to the core API too
221 /*
222 Object instances[] = context.getApplicationEventListeners();
223
224 ServletRequestEvent event = null;
225
226 if ((instances != null)
227 && (instances.length > 0)) {
228 event = new ServletRequestEvent
229 (((StandardContext) container).getServletContext(),
230 request.getRequest());
231 // create pre-service event
232 for (int i = 0; i < instances.length; i++) {
233 if (instances[i] == null)
234 continue;
235 if (!(instances[i] instanceof ServletRequestListener))
236 continue;
237 ServletRequestListener listener =
238 (ServletRequestListener) instances[i];
239 try {
240 listener.requestInitialized(event);
241 } catch (Throwable t) {
242 container.getLogger().error(sm.getString("requestListenerValve.requestInit",
243 instances[i].getClass().getName()), t);
244 ServletRequest sreq = request.getRequest();
245 sreq.setAttribute(Globals.EXCEPTION_ATTR,t);
246 return;
247 }
248 }
249 }
250 */
251
252 wrapper.getPipeline().getFirst().event(request, response, event);
253
254 /*
255 if ((instances !=null ) &&
256 (instances.length > 0)) {
257 // create post-service event
258 for (int i = 0; i < instances.length; i++) {
259 if (instances[i] == null)
260 continue;
261 if (!(instances[i] instanceof ServletRequestListener))
262 continue;
263 ServletRequestListener listener =
264 (ServletRequestListener) instances[i];
265 try {
266 listener.requestDestroyed(event);
267 } catch (Throwable t) {
268 container.getLogger().error(sm.getString("requestListenerValve.requestDestroy",
269 instances[i].getClass().getName()), t);
270 ServletRequest sreq = request.getRequest();
271 sreq.setAttribute(Globals.EXCEPTION_ATTR,t);
272 }
273 }
274 }
275 */
276
277 }
278
279
280 // -------------------------------------------------------- Private Methods
281
282
283 /**
284 * Report a "not found" error for the specified resource. FIXME: We
285 * should really be using the error reporting settings for this web
286 * application, but currently that code runs at the wrapper level rather
287 * than the context level.
288 *
289 * @param requestURI The request URI for the requested resource
290 * @param response The response we are creating
291 */
292 private void notFound(String requestURI, HttpServletResponse response) {
293
294 try {
295 response.sendError(HttpServletResponse.SC_NOT_FOUND, requestURI);
296 } catch (IllegalStateException e) {
297 ;
298 } catch (IOException e) {
299 ;
300 }
301
302 }
303
304
305 }