KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > core > StandardWrapperValve


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 JavaDoc;
23
24 import javax.management.MalformedObjectNameException JavaDoc;
25 import javax.management.ObjectName JavaDoc;
26 import javax.servlet.Servlet JavaDoc;
27 import javax.servlet.ServletException JavaDoc;
28 import javax.servlet.UnavailableException JavaDoc;
29 import javax.servlet.http.HttpServletResponse JavaDoc;
30
31 import org.apache.catalina.CometEvent;
32 import org.apache.catalina.CometProcessor;
33 import org.apache.catalina.Context;
34 import org.apache.catalina.Globals;
35 import org.apache.catalina.connector.ClientAbortException;
36 import org.apache.catalina.connector.Request;
37 import org.apache.catalina.connector.Response;
38 import org.apache.catalina.util.StringManager;
39 import org.apache.catalina.valves.ValveBase;
40 import org.apache.commons.logging.Log;
41 import org.apache.commons.logging.LogFactory;
42 import org.apache.tomcat.util.buf.MessageBytes;
43 import org.apache.tomcat.util.log.SystemLogHandler;
44
45 /**
46  * Valve that implements the default basic behavior for the
47  * <code>StandardWrapper</code> container implementation.
48  *
49  * @author Craig R. McClanahan
50  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
51  */

52
53 final class StandardWrapperValve
54     extends ValveBase {
55
56     private static Log log = LogFactory.getLog(StandardWrapperValve.class);
57
58     // ----------------------------------------------------- Instance Variables
59

60
61     // Some JMX statistics. This vavle is associated with a StandardWrapper.
62
// We exponse the StandardWrapper as JMX ( j2eeType=Servlet ). The fields
63
// are here for performance.
64
private volatile long processingTime;
65     private volatile long maxTime;
66     private volatile long minTime = Long.MAX_VALUE;
67     private volatile int requestCount;
68     private volatile int errorCount;
69
70
71     /**
72      * The string manager for this package.
73      */

74     private static final StringManager sm =
75         StringManager.getManager(Constants.Package);
76
77
78     // --------------------------------------------------------- Public Methods
79

80
81     /**
82      * Invoke the servlet we are managing, respecting the rules regarding
83      * servlet lifecycle and SingleThreadModel support.
84      *
85      * @param request Request to be processed
86      * @param response Response to be produced
87      * @param valveContext Valve context used to forward to the next Valve
88      *
89      * @exception IOException if an input/output error occurred
90      * @exception ServletException if a servlet error occurred
91      */

92     public final void invoke(Request request, Response JavaDoc response)
93         throws IOException JavaDoc, ServletException JavaDoc {
94
95         // Initialize local variables we may need
96
boolean unavailable = false;
97         Throwable JavaDoc throwable = null;
98         // This should be a Request attribute...
99
long t1=System.currentTimeMillis();
100         requestCount++;
101         StandardWrapper wrapper = (StandardWrapper) getContainer();
102         Servlet JavaDoc servlet = null;
103         Context context = (Context) wrapper.getParent();
104         
105         // Check for the application being marked unavailable
106
if (!context.getAvailable()) {
107             response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
108                            sm.getString("standardContext.isUnavailable"));
109             unavailable = true;
110         }
111
112         // Check for the servlet being marked unavailable
113
if (!unavailable && wrapper.isUnavailable()) {
114             container.getLogger().info(sm.getString("standardWrapper.isUnavailable",
115                     wrapper.getName()));
116             long available = wrapper.getAvailable();
117             if ((available > 0L) && (available < Long.MAX_VALUE)) {
118                 response.setDateHeader("Retry-After", available);
119                 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
120                         sm.getString("standardWrapper.isUnavailable",
121                                 wrapper.getName()));
122             } else if (available == Long.MAX_VALUE) {
123                 response.sendError(HttpServletResponse.SC_NOT_FOUND,
124                         sm.getString("standardWrapper.notFound",
125                                 wrapper.getName()));
126             }
127             unavailable = true;
128         }
129
130         // Allocate a servlet instance to process this request
131
try {
132             if (!unavailable) {
133                 servlet = wrapper.allocate();
134             }
135         } catch (UnavailableException JavaDoc e) {
136             long available = wrapper.getAvailable();
137             if ((available > 0L) && (available < Long.MAX_VALUE)) {
138                 response.setDateHeader("Retry-After", available);
139                 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
140                            sm.getString("standardWrapper.isUnavailable",
141                                         wrapper.getName()));
142             } else if (available == Long.MAX_VALUE) {
143                 response.sendError(HttpServletResponse.SC_NOT_FOUND,
144                            sm.getString("standardWrapper.notFound",
145                                         wrapper.getName()));
146             }
147         } catch (ServletException JavaDoc e) {
148             container.getLogger().error(sm.getString("standardWrapper.allocateException",
149                              wrapper.getName()), StandardWrapper.getRootCause(e));
150             throwable = e;
151             exception(request, response, e);
152             servlet = null;
153         } catch (Throwable JavaDoc e) {
154             container.getLogger().error(sm.getString("standardWrapper.allocateException",
155                              wrapper.getName()), e);
156             throwable = e;
157             exception(request, response, e);
158             servlet = null;
159         }
160
161         // Identify if the request is Comet related now that the servlet has been allocated
162
if (servlet instanceof CometProcessor
163                 && request.getAttribute("org.apache.tomcat.comet.support") == Boolean.TRUE) {
164             request.setComet(true);
165         }
166         
167         // Acknowlege the request
168
try {
169             response.sendAcknowledgement();
170         } catch (IOException JavaDoc e) {
171             request.removeAttribute(Globals.JSP_FILE_ATTR);
172             container.getLogger().warn(sm.getString("standardWrapper.acknowledgeException",
173                              wrapper.getName()), e);
174             throwable = e;
175             exception(request, response, e);
176         } catch (Throwable JavaDoc e) {
177             container.getLogger().error(sm.getString("standardWrapper.acknowledgeException",
178                              wrapper.getName()), e);
179             throwable = e;
180             exception(request, response, e);
181             servlet = null;
182         }
183         MessageBytes requestPathMB = null;
184         if (request != null) {
185             requestPathMB = request.getRequestPathMB();
186         }
187         request.setAttribute
188             (ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
189              ApplicationFilterFactory.REQUEST_INTEGER);
190         request.setAttribute
191             (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
192              requestPathMB);
193         // Create the filter chain for this request
194
ApplicationFilterFactory factory =
195             ApplicationFilterFactory.getInstance();
196         ApplicationFilterChain filterChain =
197             factory.createFilterChain(request, wrapper, servlet);
198
199         // Call the filter chain for this request
200
// NOTE: This also calls the servlet's service() method
201
try {
202             String JavaDoc jspFile = wrapper.getJspFile();
203             if (jspFile != null)
204                 request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
205             else
206                 request.removeAttribute(Globals.JSP_FILE_ATTR);
207             if ((servlet != null) && (filterChain != null)) {
208                 // Swallow output if needed
209
if (context.getSwallowOutput()) {
210                     try {
211                         SystemLogHandler.startCapture();
212                         if (request.isComet()) {
213                             filterChain.doFilterEvent(request.getEvent());
214                         } else {
215                             filterChain.doFilter(request.getRequest(),
216                                     response.getResponse());
217                         }
218                     } finally {
219                         String JavaDoc log = SystemLogHandler.stopCapture();
220                         if (log != null && log.length() > 0) {
221                             context.getLogger().info(log);
222                         }
223                     }
224                 } else {
225                     if (request.isComet()) {
226                         filterChain.doFilterEvent(request.getEvent());
227                     } else {
228                         filterChain.doFilter
229                             (request.getRequest(), response.getResponse());
230                     }
231                 }
232
233             }
234             request.removeAttribute(Globals.JSP_FILE_ATTR);
235         } catch (ClientAbortException e) {
236             request.removeAttribute(Globals.JSP_FILE_ATTR);
237             throwable = e;
238             exception(request, response, e);
239         } catch (IOException JavaDoc e) {
240             request.removeAttribute(Globals.JSP_FILE_ATTR);
241             container.getLogger().warn(sm.getString("standardWrapper.serviceException",
242                              wrapper.getName()), e);
243             throwable = e;
244             exception(request, response, e);
245         } catch (UnavailableException JavaDoc e) {
246             request.removeAttribute(Globals.JSP_FILE_ATTR);
247             container.getLogger().warn(sm.getString("standardWrapper.serviceException",
248                              wrapper.getName()), e);
249             // throwable = e;
250
// exception(request, response, e);
251
wrapper.unavailable(e);
252             long available = wrapper.getAvailable();
253             if ((available > 0L) && (available < Long.MAX_VALUE)) {
254                 response.setDateHeader("Retry-After", available);
255                 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,
256                            sm.getString("standardWrapper.isUnavailable",
257                                         wrapper.getName()));
258             } else if (available == Long.MAX_VALUE) {
259                 response.sendError(HttpServletResponse.SC_NOT_FOUND,
260                             sm.getString("standardWrapper.notFound",
261                                         wrapper.getName()));
262             }
263             // Do not save exception in 'throwable', because we
264
// do not want to do exception(request, response, e) processing
265
} catch (ServletException JavaDoc e) {
266             request.removeAttribute(Globals.JSP_FILE_ATTR);
267             Throwable JavaDoc rootCause = StandardWrapper.getRootCause(e);
268             if (!(rootCause instanceof ClientAbortException)) {
269                 container.getLogger().error(sm.getString("standardWrapper.serviceException",
270                                  wrapper.getName()), rootCause);
271             }
272             throwable = e;
273             exception(request, response, e);
274         } catch (Throwable JavaDoc e) {
275             request.removeAttribute(Globals.JSP_FILE_ATTR);
276             container.getLogger().error(sm.getString("standardWrapper.serviceException",
277                              wrapper.getName()), e);
278             throwable = e;
279             exception(request, response, e);
280         }
281
282         // Release the filter chain (if any) for this request
283
if (filterChain != null) {
284             if (request.isComet()) {
285                 // If this is a Comet request, then the same chain will be used for the
286
// processing of all subsequent events.
287
filterChain.reuse();
288             } else {
289                 filterChain.release();
290             }
291         }
292
293         // Deallocate the allocated servlet instance
294
try {
295             if (servlet != null) {
296                 wrapper.deallocate(servlet);
297             }
298         } catch (Throwable JavaDoc e) {
299             container.getLogger().error(sm.getString("standardWrapper.deallocateException",
300                              wrapper.getName()), e);
301             if (throwable == null) {
302                 throwable = e;
303                 exception(request, response, e);
304             }
305         }
306
307         // If this servlet has been marked permanently unavailable,
308
// unload it and release this instance
309
try {
310             if ((servlet != null) &&
311                 (wrapper.getAvailable() == Long.MAX_VALUE)) {
312                 wrapper.unload();
313             }
314         } catch (Throwable JavaDoc e) {
315             container.getLogger().error(sm.getString("standardWrapper.unloadException",
316                              wrapper.getName()), e);
317             if (throwable == null) {
318                 throwable = e;
319                 exception(request, response, e);
320             }
321         }
322         long t2=System.currentTimeMillis();
323
324         long time=t2-t1;
325         processingTime += time;
326         if( time > maxTime) maxTime=time;
327         if( time < minTime) minTime=time;
328
329     }
330
331
332     /**
333      * Process a Comet event. The main differences here are to not use sendError
334      * (the response is committed), to avoid creating a new filter chain
335      * (which would work but be pointless), and a few very minor tweaks.
336      *
337      * @param request The servlet request to be processed
338      * @param response The servlet response to be created
339      *
340      * @exception IOException if an input/output error occurs, or is thrown
341      * by a subsequently invoked Valve, Filter, or Servlet
342      * @exception ServletException if a servlet error occurs, or is thrown
343      * by a subsequently invoked Valve, Filter, or Servlet
344      */

345     public void event(Request request, Response JavaDoc response, CometEvent event)
346         throws IOException JavaDoc, ServletException JavaDoc {
347         
348         // Initialize local variables we may need
349
Throwable JavaDoc throwable = null;
350         // This should be a Request attribute...
351
long t1=System.currentTimeMillis();
352         // FIXME: Add a flag to count the total amount of events processed ? requestCount++;
353
StandardWrapper wrapper = (StandardWrapper) getContainer();
354         Servlet JavaDoc servlet = null;
355         Context context = (Context) wrapper.getParent();
356
357         // Check for the application being marked unavailable
358
boolean unavailable = !context.getAvailable() || wrapper.isUnavailable();
359         
360         // Allocate a servlet instance to process this request
361
try {
362             if (!unavailable) {
363                 servlet = wrapper.allocate();
364             }
365         } catch (UnavailableException JavaDoc e) {
366             // The response is already committed, so it's not possible to do anything
367
} catch (ServletException JavaDoc e) {
368             container.getLogger().error(sm.getString("standardWrapper.allocateException",
369                              wrapper.getName()), StandardWrapper.getRootCause(e));
370             throwable = e;
371             exception(request, response, e);
372             servlet = null;
373         } catch (Throwable JavaDoc e) {
374             container.getLogger().error(sm.getString("standardWrapper.allocateException",
375                              wrapper.getName()), e);
376             throwable = e;
377             exception(request, response, e);
378             servlet = null;
379         }
380
381         MessageBytes requestPathMB = null;
382         if (request != null) {
383             requestPathMB = request.getRequestPathMB();
384         }
385         request.setAttribute
386             (ApplicationFilterFactory.DISPATCHER_TYPE_ATTR,
387              ApplicationFilterFactory.REQUEST_INTEGER);
388         request.setAttribute
389             (ApplicationFilterFactory.DISPATCHER_REQUEST_PATH_ATTR,
390              requestPathMB);
391         // Get the current (unchanged) filter chain for this request
392
ApplicationFilterChain filterChain =
393             (ApplicationFilterChain) request.getFilterChain();
394
395         // Call the filter chain for this request
396
// NOTE: This also calls the servlet's event() method
397
try {
398             String JavaDoc jspFile = wrapper.getJspFile();
399             if (jspFile != null)
400                 request.setAttribute(Globals.JSP_FILE_ATTR, jspFile);
401             else
402                 request.removeAttribute(Globals.JSP_FILE_ATTR);
403             if ((servlet != null) && (filterChain != null)) {
404
405                 // Swallow output if needed
406
if (context.getSwallowOutput()) {
407                     try {
408                         SystemLogHandler.startCapture();
409                         filterChain.doFilterEvent(request.getEvent());
410                     } finally {
411                         String JavaDoc log = SystemLogHandler.stopCapture();
412                         if (log != null && log.length() > 0) {
413                             context.getLogger().info(log);
414                         }
415                     }
416                 } else {
417                     filterChain.doFilterEvent(request.getEvent());
418                 }
419
420             }
421             request.removeAttribute(Globals.JSP_FILE_ATTR);
422         } catch (ClientAbortException e) {
423             request.removeAttribute(Globals.JSP_FILE_ATTR);
424             throwable = e;
425             exception(request, response, e);
426         } catch (IOException JavaDoc e) {
427             request.removeAttribute(Globals.JSP_FILE_ATTR);
428             container.getLogger().warn(sm.getString("standardWrapper.serviceException",
429                              wrapper.getName()), e);
430             throwable = e;
431             exception(request, response, e);
432         } catch (UnavailableException JavaDoc e) {
433             request.removeAttribute(Globals.JSP_FILE_ATTR);
434             container.getLogger().warn(sm.getString("standardWrapper.serviceException",
435                              wrapper.getName()), e);
436             // Do not save exception in 'throwable', because we
437
// do not want to do exception(request, response, e) processing
438
} catch (ServletException JavaDoc e) {
439             request.removeAttribute(Globals.JSP_FILE_ATTR);
440             Throwable JavaDoc rootCause = StandardWrapper.getRootCause(e);
441             if (!(rootCause instanceof ClientAbortException)) {
442                 container.getLogger().error(sm.getString("standardWrapper.serviceException",
443                                  wrapper.getName()), rootCause);
444             }
445             throwable = e;
446             exception(request, response, e);
447         } catch (Throwable JavaDoc e) {
448             request.removeAttribute(Globals.JSP_FILE_ATTR);
449             container.getLogger().error(sm.getString("standardWrapper.serviceException",
450                              wrapper.getName()), e);
451             throwable = e;
452             exception(request, response, e);
453         }
454
455         // Release the filter chain (if any) for this request
456
if (filterChain != null) {
457             filterChain.reuse();
458         }
459
460         // Deallocate the allocated servlet instance
461
try {
462             if (servlet != null) {
463                 wrapper.deallocate(servlet);
464             }
465         } catch (Throwable JavaDoc e) {
466             container.getLogger().error(sm.getString("standardWrapper.deallocateException",
467                              wrapper.getName()), e);
468             if (throwable == null) {
469                 throwable = e;
470                 exception(request, response, e);
471             }
472         }
473
474         // If this servlet has been marked permanently unavailable,
475
// unload it and release this instance
476
try {
477             if ((servlet != null) &&
478                 (wrapper.getAvailable() == Long.MAX_VALUE)) {
479                 wrapper.unload();
480             }
481         } catch (Throwable JavaDoc e) {
482             container.getLogger().error(sm.getString("standardWrapper.unloadException",
483                              wrapper.getName()), e);
484             if (throwable == null) {
485                 throwable = e;
486                 exception(request, response, e);
487             }
488         }
489
490         long t2=System.currentTimeMillis();
491
492         long time=t2-t1;
493         processingTime += time;
494         if( time > maxTime) maxTime=time;
495         if( time < minTime) minTime=time;
496
497     }
498
499
500     // -------------------------------------------------------- Private Methods
501

502
503     /**
504      * Handle the specified ServletException encountered while processing
505      * the specified Request to produce the specified Response. Any
506      * exceptions that occur during generation of the exception report are
507      * logged and swallowed.
508      *
509      * @param request The request being processed
510      * @param response The response being generated
511      * @param exception The exception that occurred (which possibly wraps
512      * a root cause exception
513      */

514     private void exception(Request request, Response JavaDoc response,
515                            Throwable JavaDoc exception) {
516         request.setAttribute(Globals.EXCEPTION_ATTR, exception);
517         response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
518
519     }
520
521     public long getProcessingTime() {
522         return processingTime;
523     }
524
525     public void setProcessingTime(long processingTime) {
526         this.processingTime = processingTime;
527     }
528
529     public long getMaxTime() {
530         return maxTime;
531     }
532
533     public void setMaxTime(long maxTime) {
534         this.maxTime = maxTime;
535     }
536
537     public long getMinTime() {
538         return minTime;
539     }
540
541     public void setMinTime(long minTime) {
542         this.minTime = minTime;
543     }
544
545     public int getRequestCount() {
546         return requestCount;
547     }
548
549     public void setRequestCount(int requestCount) {
550         this.requestCount = requestCount;
551     }
552
553     public int getErrorCount() {
554         return errorCount;
555     }
556
557     public void setErrorCount(int errorCount) {
558         this.errorCount = errorCount;
559     }
560
561     // Don't register in JMX
562

563     public ObjectName JavaDoc createObjectName(String JavaDoc domain, ObjectName JavaDoc parent)
564             throws MalformedObjectNameException JavaDoc
565     {
566         return null;
567     }
568 }
569
Popular Tags