KickJava   Java API By Example, From Geeks To Geeks.

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


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 import java.lang.reflect.Method JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.PrintStream JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Properties JavaDoc;
30 import java.util.Stack JavaDoc;
31 import java.security.AccessController JavaDoc;
32 import java.security.PrivilegedActionException JavaDoc;
33 import java.security.PrivilegedExceptionAction JavaDoc;
34 import javax.servlet.Servlet JavaDoc;
35 import javax.servlet.ServletConfig JavaDoc;
36 import javax.servlet.ServletContext JavaDoc;
37 import javax.servlet.ServletException JavaDoc;
38 import javax.servlet.ServletRequest JavaDoc;
39 import javax.servlet.ServletResponse JavaDoc;
40 import javax.servlet.SingleThreadModel JavaDoc;
41 import javax.servlet.UnavailableException JavaDoc;
42 import javax.management.ListenerNotFoundException JavaDoc;
43 import javax.management.MBeanNotificationInfo JavaDoc;
44 import javax.management.Notification JavaDoc;
45 import javax.management.NotificationBroadcasterSupport JavaDoc;
46 import javax.management.NotificationEmitter JavaDoc;
47 import javax.management.NotificationFilter JavaDoc;
48 import javax.management.NotificationListener JavaDoc;
49 import javax.management.ObjectName JavaDoc;
50
51 import org.apache.PeriodicEventListener;
52 import org.apache.catalina.Container;
53 import org.apache.catalina.ContainerServlet;
54 import org.apache.catalina.Context;
55 import org.apache.catalina.InstanceEvent;
56 import org.apache.catalina.InstanceListener;
57 import org.apache.catalina.LifecycleException;
58 import org.apache.catalina.Loader;
59 import org.apache.catalina.Wrapper;
60 import org.apache.catalina.security.SecurityUtil;
61 import org.apache.catalina.util.Enumerator;
62 import org.apache.catalina.util.InstanceSupport;
63 import org.apache.tomcat.util.IntrospectionUtils;
64 import org.apache.tomcat.util.log.SystemLogHandler;
65 import org.apache.tomcat.util.modeler.Registry;
66
67 /**
68  * Standard implementation of the <b>Wrapper</b> interface that represents
69  * an individual servlet definition. No child Containers are allowed, and
70  * the parent Container must be a Context.
71  *
72  * @author Craig R. McClanahan
73  * @author Remy Maucherat
74  * @version $Revision: 467989 $ $Date: 2006-10-26 15:08:58 +0200 (jeu., 26 oct. 2006) $
75  */

76 public class StandardWrapper
77     extends ContainerBase
78     implements ServletConfig JavaDoc, Wrapper, NotificationEmitter JavaDoc {
79
80     protected static org.apache.commons.logging.Log log=
81         org.apache.commons.logging.LogFactory.getLog( StandardWrapper.class );
82
83     protected static final String JavaDoc[] DEFAULT_SERVLET_METHODS = new String JavaDoc[] {
84                                                     "GET", "HEAD", "POST" };
85
86     // ----------------------------------------------------------- Constructors
87

88
89     /**
90      * Create a new StandardWrapper component with the default basic Valve.
91      */

92     public StandardWrapper() {
93
94         super();
95         swValve=new StandardWrapperValve();
96         pipeline.setBasic(swValve);
97         broadcaster = new NotificationBroadcasterSupport JavaDoc();
98
99         if (restrictedServlets == null) {
100             restrictedServlets = new Properties JavaDoc();
101             try {
102                 InputStream JavaDoc is =
103                     this.getClass().getClassLoader().getResourceAsStream
104                         ("org/apache/catalina/core/RestrictedServlets.properties");
105                 if (is != null) {
106                     restrictedServlets.load(is);
107                 } else {
108                     log.error(sm.getString("standardWrapper.restrictedServletsResource"));
109                 }
110             } catch (IOException JavaDoc e) {
111                 log.error(sm.getString("standardWrapper.restrictedServletsResource"), e);
112             }
113         }
114         
115     }
116
117
118     // ----------------------------------------------------- Instance Variables
119

120
121     /**
122      * The date and time at which this servlet will become available (in
123      * milliseconds since the epoch), or zero if the servlet is available.
124      * If this value equals Long.MAX_VALUE, the unavailability of this
125      * servlet is considered permanent.
126      */

127     protected long available = 0L;
128     
129     /**
130      * The broadcaster that sends j2ee notifications.
131      */

132     protected NotificationBroadcasterSupport JavaDoc broadcaster = null;
133     
134     /**
135      * The count of allocations that are currently active (even if they
136      * are for the same instance, as will be true on a non-STM servlet).
137      */

138     protected int countAllocated = 0;
139
140
141     /**
142      * The facade associated with this wrapper.
143      */

144     protected StandardWrapperFacade facade =
145         new StandardWrapperFacade(this);
146
147
148     /**
149      * The descriptive information string for this implementation.
150      */

151     protected static final String JavaDoc info =
152         "org.apache.catalina.core.StandardWrapper/1.0";
153
154
155     /**
156      * The (single) initialized instance of this servlet.
157      */

158     protected Servlet JavaDoc instance = null;
159
160
161     /**
162      * The support object for our instance listeners.
163      */

164     protected InstanceSupport instanceSupport = new InstanceSupport(this);
165
166
167     /**
168      * The context-relative URI of the JSP file for this servlet.
169      */

170     protected String JavaDoc jspFile = null;
171
172
173     /**
174      * The load-on-startup order value (negative value means load on
175      * first call) for this servlet.
176      */

177     protected int loadOnStartup = -1;
178
179
180     /**
181      * Mappings associated with the wrapper.
182      */

183     protected ArrayList JavaDoc mappings = new ArrayList JavaDoc();
184
185
186     /**
187      * The initialization parameters for this servlet, keyed by
188      * parameter name.
189      */

190     protected HashMap JavaDoc parameters = new HashMap JavaDoc();
191
192
193     /**
194      * The security role references for this servlet, keyed by role name
195      * used in the servlet. The corresponding value is the role name of
196      * the web application itself.
197      */

198     protected HashMap JavaDoc references = new HashMap JavaDoc();
199
200
201     /**
202      * The run-as identity for this servlet.
203      */

204     protected String JavaDoc runAs = null;
205
206     /**
207      * The notification sequence number.
208      */

209     protected long sequenceNumber = 0;
210
211     /**
212      * The fully qualified servlet class name for this servlet.
213      */

214     protected String JavaDoc servletClass = null;
215
216
217     /**
218      * Does this servlet implement the SingleThreadModel interface?
219      */

220     protected boolean singleThreadModel = false;
221
222
223     /**
224      * Are we unloading our servlet instance at the moment?
225      */

226     protected boolean unloading = false;
227
228
229     /**
230      * Maximum number of STM instances.
231      */

232     protected int maxInstances = 20;
233
234
235     /**
236      * Number of instances currently loaded for a STM servlet.
237      */

238     protected int nInstances = 0;
239
240
241     /**
242      * Stack containing the STM instances.
243      */

244     protected Stack JavaDoc instancePool = null;
245
246     
247     /**
248      * Wait time for servlet unload in ms.
249      */

250     protected long unloadDelay = 2000;
251     
252
253     /**
254      * True if this StandardWrapper is for the JspServlet
255      */

256     protected boolean isJspServlet;
257
258
259     /**
260      * The ObjectName of the JSP monitoring mbean
261      */

262     protected ObjectName JavaDoc jspMonitorON;
263
264
265     /**
266      * Should we swallow System.out
267      */

268     protected boolean swallowOutput = false;
269
270     // To support jmx attributes
271
protected StandardWrapperValve swValve;
272     protected long loadTime=0;
273     protected int classLoadTime=0;
274     
275     /**
276      * Static class array used when the SecurityManager is turned on and
277      * <code>Servlet.init</code> is invoked.
278      */

279     protected static Class JavaDoc[] classType = new Class JavaDoc[]{ServletConfig JavaDoc.class};
280     
281     
282     /**
283      * Static class array used when the SecurityManager is turned on and
284      * <code>Servlet.service</code> is invoked.
285      */

286     protected static Class JavaDoc[] classTypeUsedInService = new Class JavaDoc[]{
287                                                          ServletRequest JavaDoc.class,
288                                                          ServletResponse JavaDoc.class};
289     
290     /**
291      * Restricted servlets (which can only be loaded by a privileged webapp).
292      */

293     protected static Properties JavaDoc restrictedServlets = null;
294     
295     
296     // ------------------------------------------------------------- Properties
297

298
299     /**
300      * Return the available date/time for this servlet, in milliseconds since
301      * the epoch. If this date/time is Long.MAX_VALUE, it is considered to mean
302      * that unavailability is permanent and any request for this servlet will return
303      * an SC_NOT_FOUND error. If this date/time is in the future, any request for
304      * this servlet will return an SC_SERVICE_UNAVAILABLE error. If it is zero,
305      * the servlet is currently available.
306      */

307     public long getAvailable() {
308
309         return (this.available);
310
311     }
312
313
314     /**
315      * Set the available date/time for this servlet, in milliseconds since the
316      * epoch. If this date/time is Long.MAX_VALUE, it is considered to mean
317      * that unavailability is permanent and any request for this servlet will return
318      * an SC_NOT_FOUND error. If this date/time is in the future, any request for
319      * this servlet will return an SC_SERVICE_UNAVAILABLE error.
320      *
321      * @param available The new available date/time
322      */

323     public void setAvailable(long available) {
324
325         long oldAvailable = this.available;
326         if (available > System.currentTimeMillis())
327             this.available = available;
328         else
329             this.available = 0L;
330         support.firePropertyChange("available", new Long JavaDoc(oldAvailable),
331                                    new Long JavaDoc(this.available));
332
333     }
334
335
336     /**
337      * Return the number of active allocations of this servlet, even if they
338      * are all for the same instance (as will be true for servlets that do
339      * not implement <code>SingleThreadModel</code>.
340      */

341     public int getCountAllocated() {
342
343         return (this.countAllocated);
344
345     }
346
347
348     public String JavaDoc getEngineName() {
349         return ((StandardContext)getParent()).getEngineName();
350     }
351
352
353     /**
354      * Return descriptive information about this Container implementation and
355      * the corresponding version number, in the format
356      * <code>&lt;description&gt;/&lt;version&gt;</code>.
357      */

358     public String JavaDoc getInfo() {
359
360         return (info);
361
362     }
363
364
365     /**
366      * Return the InstanceSupport object for this Wrapper instance.
367      */

368     public InstanceSupport getInstanceSupport() {
369
370         return (this.instanceSupport);
371
372     }
373
374
375     /**
376      * Return the context-relative URI of the JSP file for this servlet.
377      */

378     public String JavaDoc getJspFile() {
379
380         return (this.jspFile);
381
382     }
383
384
385     /**
386      * Set the context-relative URI of the JSP file for this servlet.
387      *
388      * @param jspFile JSP file URI
389      */

390     public void setJspFile(String JavaDoc jspFile) {
391
392         String JavaDoc oldJspFile = this.jspFile;
393         this.jspFile = jspFile;
394         support.firePropertyChange("jspFile", oldJspFile, this.jspFile);
395
396         // Each jsp-file needs to be represented by its own JspServlet and
397
// corresponding JspMonitoring mbean, because it may be initialized
398
// with its own init params
399
isJspServlet = true;
400
401     }
402
403
404     /**
405      * Return the load-on-startup order value (negative value means
406      * load on first call).
407      */

408     public int getLoadOnStartup() {
409
410         if (isJspServlet && loadOnStartup < 0) {
411             /*
412              * JspServlet must always be preloaded, because its instance is
413              * used during registerJMX (when registering the JSP
414              * monitoring mbean)
415              */

416              return Integer.MAX_VALUE;
417         } else {
418             return (this.loadOnStartup);
419         }
420     }
421
422
423     /**
424      * Set the load-on-startup order value (negative value means
425      * load on first call).
426      *
427      * @param value New load-on-startup value
428      */

429     public void setLoadOnStartup(int value) {
430
431         int oldLoadOnStartup = this.loadOnStartup;
432         this.loadOnStartup = value;
433         support.firePropertyChange("loadOnStartup",
434                                    new Integer JavaDoc(oldLoadOnStartup),
435                                    new Integer JavaDoc(this.loadOnStartup));
436
437     }
438
439
440
441     /**
442      * Set the load-on-startup order value from a (possibly null) string.
443      * Per the specification, any missing or non-numeric value is converted
444      * to a zero, so that this servlet will still be loaded at startup
445      * time, but in an arbitrary order.
446      *
447      * @param value New load-on-startup value
448      */

449     public void setLoadOnStartupString(String JavaDoc value) {
450
451         try {
452             setLoadOnStartup(Integer.parseInt(value));
453         } catch (NumberFormatException JavaDoc e) {
454             setLoadOnStartup(0);
455         }
456     }
457
458     public String JavaDoc getLoadOnStartupString() {
459         return Integer.toString( getLoadOnStartup());
460     }
461
462
463     /**
464      * Return maximum number of instances that will be allocated when a single
465      * thread model servlet is used.
466      */

467     public int getMaxInstances() {
468
469         return (this.maxInstances);
470
471     }
472
473
474     /**
475      * Set the maximum number of instances that will be allocated when a single
476      * thread model servlet is used.
477      *
478      * @param maxInstances New value of maxInstances
479      */

480     public void setMaxInstances(int maxInstances) {
481
482         int oldMaxInstances = this.maxInstances;
483         this.maxInstances = maxInstances;
484         support.firePropertyChange("maxInstances", oldMaxInstances,
485                                    this.maxInstances);
486
487     }
488
489
490     /**
491      * Set the parent Container of this Wrapper, but only if it is a Context.
492      *
493      * @param container Proposed parent Container
494      */

495     public void setParent(Container container) {
496
497         if ((container != null) &&
498             !(container instanceof Context JavaDoc))
499             throw new IllegalArgumentException JavaDoc
500                 (sm.getString("standardWrapper.notContext"));
501         if (container instanceof StandardContext) {
502             swallowOutput = ((StandardContext)container).getSwallowOutput();
503             unloadDelay = ((StandardContext)container).getUnloadDelay();
504         }
505         super.setParent(container);
506
507     }
508
509
510     /**
511      * Return the run-as identity for this servlet.
512      */

513     public String JavaDoc getRunAs() {
514
515         return (this.runAs);
516
517     }
518
519
520     /**
521      * Set the run-as identity for this servlet.
522      *
523      * @param runAs New run-as identity value
524      */

525     public void setRunAs(String JavaDoc runAs) {
526
527         String JavaDoc oldRunAs = this.runAs;
528         this.runAs = runAs;
529         support.firePropertyChange("runAs", oldRunAs, this.runAs);
530
531     }
532
533
534     /**
535      * Return the fully qualified servlet class name for this servlet.
536      */

537     public String JavaDoc getServletClass() {
538
539         return (this.servletClass);
540
541     }
542
543
544     /**
545      * Set the fully qualified servlet class name for this servlet.
546      *
547      * @param servletClass Servlet class name
548      */

549     public void setServletClass(String JavaDoc servletClass) {
550
551         String JavaDoc oldServletClass = this.servletClass;
552         this.servletClass = servletClass;
553         support.firePropertyChange("servletClass", oldServletClass,
554                                    this.servletClass);
555         if (Constants.JSP_SERVLET_CLASS.equals(servletClass)) {
556             isJspServlet = true;
557         }
558     }
559
560
561
562     /**
563      * Set the name of this servlet. This is an alias for the normal
564      * <code>Container.setName()</code> method, and complements the
565      * <code>getServletName()</code> method required by the
566      * <code>ServletConfig</code> interface.
567      *
568      * @param name The new name of this servlet
569      */

570     public void setServletName(String JavaDoc name) {
571
572         setName(name);
573
574     }
575
576
577     /**
578      * Return <code>true</code> if the servlet class represented by this
579      * component implements the <code>SingleThreadModel</code> interface.
580      */

581     public boolean isSingleThreadModel() {
582
583         try {
584             loadServlet();
585         } catch (Throwable JavaDoc t) {
586             ;
587         }
588         return (singleThreadModel);
589
590     }
591
592
593     /**
594      * Is this servlet currently unavailable?
595      */

596     public boolean isUnavailable() {
597
598         if (available == 0L)
599             return (false);
600         else if (available <= System.currentTimeMillis()) {
601             available = 0L;
602             return (false);
603         } else
604             return (true);
605
606     }
607
608
609     /**
610      * Gets the names of the methods supported by the underlying servlet.
611      *
612      * This is the same set of methods included in the Allow response header
613      * in response to an OPTIONS request method processed by the underlying
614      * servlet.
615      *
616      * @return Array of names of the methods supported by the underlying
617      * servlet
618      */

619     public String JavaDoc[] getServletMethods() throws ServletException JavaDoc {
620
621         Class JavaDoc servletClazz = loadServlet().getClass();
622         if (!javax.servlet.http.HttpServlet JavaDoc.class.isAssignableFrom(
623                                                         servletClazz)) {
624             return DEFAULT_SERVLET_METHODS;
625         }
626
627         HashSet JavaDoc allow = new HashSet JavaDoc();
628         allow.add("TRACE");
629         allow.add("OPTIONS");
630     
631         Method JavaDoc[] methods = getAllDeclaredMethods(servletClazz);
632         for (int i=0; methods != null && i<methods.length; i++) {
633             Method JavaDoc m = methods[i];
634         
635             if (m.getName().equals("doGet")) {
636                 allow.add("GET");
637                 allow.add("HEAD");
638             } else if (m.getName().equals("doPost")) {
639                 allow.add("POST");
640             } else if (m.getName().equals("doPut")) {
641                 allow.add("PUT");
642             } else if (m.getName().equals("doDelete")) {
643                 allow.add("DELETE");
644             }
645         }
646
647         String JavaDoc[] methodNames = new String JavaDoc[allow.size()];
648         return (String JavaDoc[]) allow.toArray(methodNames);
649
650     }
651
652
653     // --------------------------------------------------------- Public Methods
654

655
656     /**
657      * Execute a periodic task, such as reloading, etc. This method will be
658      * invoked inside the classloading context of this container. Unexpected
659      * throwables will be caught and logged.
660      */

661     public void backgroundProcess() {
662         super.backgroundProcess();
663         
664         if (!started)
665             return;
666         
667         if (getServlet() != null && (getServlet() instanceof PeriodicEventListener)) {
668             ((PeriodicEventListener) getServlet()).periodicEvent();
669         }
670     }
671     
672     
673     /**
674      * Extract the root cause from a servlet exception.
675      *
676      * @param e The servlet exception
677      */

678     public static Throwable JavaDoc getRootCause(ServletException JavaDoc e) {
679         Throwable JavaDoc rootCause = e;
680         Throwable JavaDoc rootCauseCheck = null;
681         // Extra aggressive rootCause finding
682
int loops = 0;
683         do {
684             loops++;
685             rootCauseCheck = rootCause.getCause();
686             if (rootCauseCheck != null)
687                 rootCause = rootCauseCheck;
688         } while (rootCauseCheck != null && (loops < 20));
689         return rootCause;
690     }
691
692
693     /**
694      * Refuse to add a child Container, because Wrappers are the lowest level
695      * of the Container hierarchy.
696      *
697      * @param child Child container to be added
698      */

699     public void addChild(Container child) {
700
701         throw new IllegalStateException JavaDoc
702             (sm.getString("standardWrapper.notChild"));
703
704     }
705
706
707     /**
708      * Add a new servlet initialization parameter for this servlet.
709      *
710      * @param name Name of this initialization parameter to add
711      * @param value Value of this initialization parameter to add
712      */

713     public void addInitParameter(String JavaDoc name, String JavaDoc value) {
714
715         synchronized (parameters) {
716             parameters.put(name, value);
717         }
718         fireContainerEvent("addInitParameter", name);
719
720     }
721
722
723     /**
724      * Add a new listener interested in InstanceEvents.
725      *
726      * @param listener The new listener
727      */

728     public void addInstanceListener(InstanceListener listener) {
729
730         instanceSupport.addInstanceListener(listener);
731
732     }
733
734
735     /**
736      * Add a mapping associated with the Wrapper.
737      *
738      * @param mapping The new wrapper mapping
739      */

740     public void addMapping(String JavaDoc mapping) {
741
742         synchronized (mappings) {
743             mappings.add(mapping);
744         }
745         fireContainerEvent("addMapping", mapping);
746
747     }
748
749
750     /**
751      * Add a new security role reference record to the set of records for
752      * this servlet.
753      *
754      * @param name Role name used within this servlet
755      * @param link Role name used within the web application
756      */

757     public void addSecurityReference(String JavaDoc name, String JavaDoc link) {
758
759         synchronized (references) {
760             references.put(name, link);
761         }
762         fireContainerEvent("addSecurityReference", name);
763
764     }
765
766
767     /**
768      * Return the associated servlet instance.
769      */

770     public Servlet JavaDoc getServlet() {
771         return instance;
772     }
773     
774     
775     /**
776      * Allocate an initialized instance of this Servlet that is ready to have
777      * its <code>service()</code> method called. If the servlet class does
778      * not implement <code>SingleThreadModel</code>, the (only) initialized
779      * instance may be returned immediately. If the servlet class implements
780      * <code>SingleThreadModel</code>, the Wrapper implementation must ensure
781      * that this instance is not allocated again until it is deallocated by a
782      * call to <code>deallocate()</code>.
783      *
784      * @exception ServletException if the servlet init() method threw
785      * an exception
786      * @exception ServletException if a loading error occurs
787      */

788     public Servlet JavaDoc allocate() throws ServletException JavaDoc {
789
790         // If we are currently unloading this servlet, throw an exception
791
if (unloading)
792             throw new ServletException JavaDoc
793               (sm.getString("standardWrapper.unloading", getName()));
794
795         // If not SingleThreadedModel, return the same instance every time
796
if (!singleThreadModel) {
797
798             // Load and initialize our instance if necessary
799
if (instance == null) {
800                 synchronized (this) {
801                     if (instance == null) {
802                         try {
803                             if (log.isDebugEnabled())
804                                 log.debug("Allocating non-STM instance");
805
806                             instance = loadServlet();
807                         } catch (ServletException JavaDoc e) {
808                             throw e;
809                         } catch (Throwable JavaDoc e) {
810                             throw new ServletException JavaDoc
811                                 (sm.getString("standardWrapper.allocate"), e);
812                         }
813                     }
814                 }
815             }
816
817             if (!singleThreadModel) {
818                 if (log.isTraceEnabled())
819                     log.trace(" Returning non-STM instance");
820                 countAllocated++;
821                 return (instance);
822             }
823
824         }
825
826         synchronized (instancePool) {
827
828             while (countAllocated >= nInstances) {
829                 // Allocate a new instance if possible, or else wait
830
if (nInstances < maxInstances) {
831                     try {
832                         instancePool.push(loadServlet());
833                         nInstances++;
834                     } catch (ServletException JavaDoc e) {
835                         throw e;
836                     } catch (Throwable JavaDoc e) {
837                         throw new ServletException JavaDoc
838                             (sm.getString("standardWrapper.allocate"), e);
839                     }
840                 } else {
841                     try {
842                         instancePool.wait();
843                     } catch (InterruptedException JavaDoc e) {
844                         ;
845                     }
846                 }
847             }
848             if (log.isTraceEnabled())
849                 log.trace(" Returning allocated STM instance");
850             countAllocated++;
851             return (Servlet JavaDoc) instancePool.pop();
852
853         }
854
855     }
856
857
858     /**
859      * Return this previously allocated servlet to the pool of available
860      * instances. If this servlet class does not implement SingleThreadModel,
861      * no action is actually required.
862      *
863      * @param servlet The servlet to be returned
864      *
865      * @exception ServletException if a deallocation error occurs
866      */

867     public void deallocate(Servlet JavaDoc servlet) throws ServletException JavaDoc {
868
869         // If not SingleThreadModel, no action is required
870
if (!singleThreadModel) {
871             countAllocated--;
872             return;
873         }
874
875         // Unlock and free this instance
876
synchronized (instancePool) {
877             countAllocated--;
878             instancePool.push(servlet);
879             instancePool.notify();
880         }
881
882     }
883
884
885     /**
886      * Return the value for the specified initialization parameter name,
887      * if any; otherwise return <code>null</code>.
888      *
889      * @param name Name of the requested initialization parameter
890      */

891     public String JavaDoc findInitParameter(String JavaDoc name) {
892
893         synchronized (parameters) {
894             return ((String JavaDoc) parameters.get(name));
895         }
896
897     }
898
899
900     /**
901      * Return the names of all defined initialization parameters for this
902      * servlet.
903      */

904     public String JavaDoc[] findInitParameters() {
905
906         synchronized (parameters) {
907             String JavaDoc results[] = new String JavaDoc[parameters.size()];
908             return ((String JavaDoc[]) parameters.keySet().toArray(results));
909         }
910
911     }
912
913
914     /**
915      * Return the mappings associated with this wrapper.
916      */

917     public String JavaDoc[] findMappings() {
918
919         synchronized (mappings) {
920             return (String JavaDoc[]) mappings.toArray(new String JavaDoc[mappings.size()]);
921         }
922
923     }
924
925
926     /**
927      * Return the security role link for the specified security role
928      * reference name, if any; otherwise return <code>null</code>.
929      *
930      * @param name Security role reference used within this servlet
931      */

932     public String JavaDoc findSecurityReference(String JavaDoc name) {
933
934         synchronized (references) {
935             return ((String JavaDoc) references.get(name));
936         }
937
938     }
939
940
941     /**
942      * Return the set of security role reference names associated with
943      * this servlet, if any; otherwise return a zero-length array.
944      */

945     public String JavaDoc[] findSecurityReferences() {
946
947         synchronized (references) {
948             String JavaDoc results[] = new String JavaDoc[references.size()];
949             return ((String JavaDoc[]) references.keySet().toArray(results));
950         }
951
952     }
953
954
955     /**
956      * FIXME: Fooling introspection ...
957      */

958     public Wrapper findMappingObject() {
959         return (Wrapper) getMappingObject();
960     }
961
962
963     /**
964      * Load and initialize an instance of this servlet, if there is not already
965      * at least one initialized instance. This can be used, for example, to
966      * load servlets that are marked in the deployment descriptor to be loaded
967      * at server startup time.
968      * <p>
969      * <b>IMPLEMENTATION NOTE</b>: Servlets whose classnames begin with
970      * <code>org.apache.catalina.</code> (so-called "container" servlets)
971      * are loaded by the same classloader that loaded this class, rather than
972      * the classloader for the current web application.
973      * This gives such classes access to Catalina internals, which are
974      * prevented for classes loaded for web applications.
975      *
976      * @exception ServletException if the servlet init() method threw
977      * an exception
978      * @exception ServletException if some other loading problem occurs
979      */

980     public synchronized void load() throws ServletException JavaDoc {
981         instance = loadServlet();
982     }
983
984
985     /**
986      * Load and initialize an instance of this servlet, if there is not already
987      * at least one initialized instance. This can be used, for example, to
988      * load servlets that are marked in the deployment descriptor to be loaded
989      * at server startup time.
990      */

991     public synchronized Servlet JavaDoc loadServlet() throws ServletException JavaDoc {
992
993         // Nothing to do if we already have an instance or an instance pool
994
if (!singleThreadModel && (instance != null))
995             return instance;
996
997         PrintStream JavaDoc out = System.out;
998         if (swallowOutput) {
999             SystemLogHandler.startCapture();
1000        }
1001
1002        Servlet JavaDoc servlet;
1003        try {
1004            long t1=System.currentTimeMillis();
1005            // If this "servlet" is really a JSP file, get the right class.
1006
// HOLD YOUR NOSE - this is a kludge that avoids having to do special
1007
// case Catalina-specific code in Jasper - it also requires that the
1008
// servlet path be replaced by the <jsp-file> element content in
1009
// order to be completely effective
1010
String JavaDoc actualClass = servletClass;
1011            if ((actualClass == null) && (jspFile != null)) {
1012                Wrapper jspWrapper = (Wrapper)
1013                    ((Context JavaDoc) getParent()).findChild(Constants.JSP_SERVLET_NAME);
1014                if (jspWrapper != null) {
1015                    actualClass = jspWrapper.getServletClass();
1016                    // Merge init parameters
1017
String JavaDoc paramNames[] = jspWrapper.findInitParameters();
1018                    for (int i = 0; i < paramNames.length; i++) {
1019                        if (parameters.get(paramNames[i]) == null) {
1020                            parameters.put
1021                                (paramNames[i],
1022                                 jspWrapper.findInitParameter(paramNames[i]));
1023                        }
1024                    }
1025                }
1026            }
1027
1028            // Complain if no servlet class has been specified
1029
if (actualClass == null) {
1030                unavailable(null);
1031                throw new ServletException JavaDoc
1032                    (sm.getString("standardWrapper.notClass", getName()));
1033            }
1034
1035            // Acquire an instance of the class loader to be used
1036
Loader loader = getLoader();
1037            if (loader == null) {
1038                unavailable(null);
1039                throw new ServletException JavaDoc
1040                    (sm.getString("standardWrapper.missingLoader", getName()));
1041            }
1042
1043            ClassLoader JavaDoc classLoader = loader.getClassLoader();
1044
1045            // Special case class loader for a container provided servlet
1046
//
1047
if (isContainerProvidedServlet(actualClass) &&
1048                    ! ((Context JavaDoc)getParent()).getPrivileged() ) {
1049                // If it is a priviledged context - using its own
1050
// class loader will work, since it's a child of the container
1051
// loader
1052
classLoader = this.getClass().getClassLoader();
1053            }
1054
1055            // Load the specified servlet class from the appropriate class loader
1056
Class JavaDoc classClass = null;
1057            try {
1058                if (SecurityUtil.isPackageProtectionEnabled()){
1059                    final ClassLoader JavaDoc fclassLoader = classLoader;
1060                    final String JavaDoc factualClass = actualClass;
1061                    try{
1062                        classClass = (Class JavaDoc)AccessController.doPrivileged(
1063                                new PrivilegedExceptionAction JavaDoc(){
1064                                    public Object JavaDoc run() throws Exception JavaDoc{
1065                                        if (fclassLoader != null) {
1066                                            return fclassLoader.loadClass(factualClass);
1067                                        } else {
1068                                            return Class.forName(factualClass);
1069                                        }
1070                                    }
1071                        });
1072                    } catch(PrivilegedActionException JavaDoc pax){
1073                        Exception JavaDoc ex = pax.getException();
1074                        if (ex instanceof ClassNotFoundException JavaDoc){
1075                            throw (ClassNotFoundException JavaDoc)ex;
1076                        } else {
1077                            getServletContext().log( "Error loading "
1078                                + fclassLoader + " " + factualClass, ex );
1079                        }
1080                    }
1081                } else {
1082                    if (classLoader != null) {
1083                        classClass = classLoader.loadClass(actualClass);
1084                    } else {
1085                        classClass = Class.forName(actualClass);
1086                    }
1087                }
1088            } catch (ClassNotFoundException JavaDoc e) {
1089                unavailable(null);
1090                getServletContext().log( "Error loading " + classLoader + " " + actualClass, e );
1091                throw new ServletException JavaDoc
1092                    (sm.getString("standardWrapper.missingClass", actualClass),
1093                     e);
1094            }
1095
1096            if (classClass == null) {
1097                unavailable(null);
1098                throw new ServletException JavaDoc
1099                    (sm.getString("standardWrapper.missingClass", actualClass));
1100            }
1101
1102            // Instantiate and initialize an instance of the servlet class itself
1103
try {
1104                servlet = (Servlet JavaDoc) classClass.newInstance();
1105                // Annotation processing
1106
if (!((Context JavaDoc) getParent()).getIgnoreAnnotations()) {
1107                    if (getParent() instanceof StandardContext) {
1108                       ((StandardContext)getParent()).getAnnotationProcessor().processAnnotations(servlet);
1109                       ((StandardContext)getParent()).getAnnotationProcessor().postConstruct(servlet);
1110                    }
1111                }
1112            } catch (ClassCastException JavaDoc e) {
1113                unavailable(null);
1114                // Restore the context ClassLoader
1115
throw new ServletException JavaDoc
1116                    (sm.getString("standardWrapper.notServlet", actualClass), e);
1117            } catch (Throwable JavaDoc e) {
1118                unavailable(null);
1119              
1120                // Added extra log statement for Bugzilla 36630:
1121
// http://issues.apache.org/bugzilla/show_bug.cgi?id=36630
1122
if(log.isDebugEnabled()) {
1123                    log.debug(sm.getString("standardWrapper.instantiate", actualClass), e);
1124                }
1125
1126                // Restore the context ClassLoader
1127
throw new ServletException JavaDoc
1128                    (sm.getString("standardWrapper.instantiate", actualClass), e);
1129            }
1130
1131            // Check if loading the servlet in this web application should be
1132
// allowed
1133
if (!isServletAllowed(servlet)) {
1134                throw new SecurityException JavaDoc
1135                    (sm.getString("standardWrapper.privilegedServlet",
1136                                  actualClass));
1137            }
1138
1139            // Special handling for ContainerServlet instances
1140
if ((servlet instanceof ContainerServlet) &&
1141                  (isContainerProvidedServlet(actualClass) ||
1142                    ((Context JavaDoc)getParent()).getPrivileged() )) {
1143                ((ContainerServlet) servlet).setWrapper(this);
1144            }
1145
1146            classLoadTime=(int) (System.currentTimeMillis() -t1);
1147            // Call the initialization method of this servlet
1148
try {
1149                instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
1150                                                  servlet);
1151
1152                if( System.getSecurityManager() != null) {
1153
1154                    Object JavaDoc[] args = new Object JavaDoc[]{((ServletConfig JavaDoc)facade)};
1155                    SecurityUtil.doAsPrivilege("init",
1156                                               servlet,
1157                                               classType,
1158                                               args);
1159                    args = null;
1160                } else {
1161                    servlet.init(facade);
1162                }
1163
1164                // Invoke jspInit on JSP pages
1165
if ((loadOnStartup >= 0) && (jspFile != null)) {
1166                    // Invoking jspInit
1167
DummyRequest req = new DummyRequest();
1168                    req.setServletPath(jspFile);
1169                    req.setQueryString("jsp_precompile=true");
1170                    DummyResponse res = new DummyResponse();
1171
1172                    if( System.getSecurityManager() != null) {
1173                        Object JavaDoc[] args = new Object JavaDoc[]{req, res};
1174                        SecurityUtil.doAsPrivilege("service",
1175                                                   servlet,
1176                                                   classTypeUsedInService,
1177                                                   args);
1178                        args = null;
1179                    } else {
1180                        servlet.service(req, res);
1181                    }
1182                }
1183                instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
1184                                                  servlet);
1185            } catch (UnavailableException JavaDoc f) {
1186                instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
1187                                                  servlet, f);
1188                unavailable(f);
1189                throw f;
1190            } catch (ServletException JavaDoc f) {
1191                instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
1192                                                  servlet, f);
1193                // If the servlet wanted to be unavailable it would have
1194
// said so, so do not call unavailable(null).
1195
throw f;
1196            } catch (Throwable JavaDoc f) {
1197                getServletContext().log("StandardWrapper.Throwable", f );
1198                instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
1199                                                  servlet, f);
1200                // If the servlet wanted to be unavailable it would have
1201
// said so, so do not call unavailable(null).
1202
throw new ServletException JavaDoc
1203                    (sm.getString("standardWrapper.initException", getName()), f);
1204            }
1205
1206            // Register our newly initialized instance
1207
singleThreadModel = servlet instanceof SingleThreadModel JavaDoc;
1208            if (singleThreadModel) {
1209                if (instancePool == null)
1210                    instancePool = new Stack JavaDoc();
1211            }
1212            fireContainerEvent("load", this);
1213
1214            loadTime=System.currentTimeMillis() -t1;
1215        } finally {
1216            if (swallowOutput) {
1217                String JavaDoc log = SystemLogHandler.stopCapture();
1218                if (log != null && log.length() > 0) {
1219                    if (getServletContext() != null) {
1220                        getServletContext().log(log);
1221                    } else {
1222                        out.println(log);
1223                    }
1224                }
1225            }
1226        }
1227        return servlet;
1228
1229    }
1230
1231
1232    /**
1233     * Remove the specified initialization parameter from this servlet.
1234     *
1235     * @param name Name of the initialization parameter to remove
1236     */

1237    public void removeInitParameter(String JavaDoc name) {
1238
1239        synchronized (parameters) {
1240            parameters.remove(name);
1241        }
1242        fireContainerEvent("removeInitParameter", name);
1243
1244    }
1245
1246
1247    /**
1248     * Remove a listener no longer interested in InstanceEvents.
1249     *
1250     * @param listener The listener to remove
1251     */

1252    public void removeInstanceListener(InstanceListener listener) {
1253
1254        instanceSupport.removeInstanceListener(listener);
1255
1256    }
1257
1258
1259    /**
1260     * Remove a mapping associated with the wrapper.
1261     *
1262     * @param mapping The pattern to remove
1263     */

1264    public void removeMapping(String JavaDoc mapping) {
1265
1266        synchronized (mappings) {
1267            mappings.remove(mapping);
1268        }
1269        fireContainerEvent("removeMapping", mapping);
1270
1271    }
1272
1273
1274    /**
1275     * Remove any security role reference for the specified role name.
1276     *
1277     * @param name Security role used within this servlet to be removed
1278     */

1279    public void removeSecurityReference(String JavaDoc name) {
1280
1281        synchronized (references) {
1282            references.remove(name);
1283        }
1284        fireContainerEvent("removeSecurityReference", name);
1285
1286    }
1287
1288
1289    /**
1290     * Return a String representation of this component.
1291     */

1292    public String JavaDoc toString() {
1293
1294        StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1295        if (getParent() != null) {
1296            sb.append(getParent().toString());
1297            sb.append(".");
1298        }
1299        sb.append("StandardWrapper[");
1300        sb.append(getName());
1301        sb.append("]");
1302        return (sb.toString());
1303
1304    }
1305
1306
1307    /**
1308     * Process an UnavailableException, marking this servlet as unavailable
1309     * for the specified amount of time.
1310     *
1311     * @param unavailable The exception that occurred, or <code>null</code>
1312     * to mark this servlet as permanently unavailable
1313     */

1314    public void unavailable(UnavailableException JavaDoc unavailable) {
1315        getServletContext().log(sm.getString("standardWrapper.unavailable", getName()));
1316        if (unavailable == null)
1317            setAvailable(Long.MAX_VALUE);
1318        else if (unavailable.isPermanent())
1319            setAvailable(Long.MAX_VALUE);
1320        else {
1321            int unavailableSeconds = unavailable.getUnavailableSeconds();
1322            if (unavailableSeconds <= 0)
1323                unavailableSeconds = 60; // Arbitrary default
1324
setAvailable(System.currentTimeMillis() +
1325                         (unavailableSeconds * 1000L));
1326        }
1327
1328    }
1329
1330
1331    /**
1332     * Unload all initialized instances of this servlet, after calling the
1333     * <code>destroy()</code> method for each instance. This can be used,
1334     * for example, prior to shutting down the entire servlet engine, or
1335     * prior to reloading all of the classes from the Loader associated with
1336     * our Loader's repository.
1337     *
1338     * @exception ServletException if an exception is thrown by the
1339     * destroy() method
1340     */

1341    public synchronized void unload() throws ServletException JavaDoc {
1342
1343        // Nothing to do if we have never loaded the instance
1344
if (!singleThreadModel && (instance == null))
1345            return;
1346        unloading = true;
1347
1348        // Loaf a while if the current instance is allocated
1349
// (possibly more than once if non-STM)
1350
if (countAllocated > 0) {
1351            int nRetries = 0;
1352            long delay = unloadDelay / 20;
1353            while ((nRetries < 21) && (countAllocated > 0)) {
1354                if ((nRetries % 10) == 0) {
1355                    log.info(sm.getString("standardWrapper.waiting",
1356                                          new Integer JavaDoc(countAllocated)));
1357                }
1358                try {
1359                    Thread.sleep(delay);
1360                } catch (InterruptedException JavaDoc e) {
1361                    ;
1362                }
1363                nRetries++;
1364            }
1365        }
1366
1367        PrintStream JavaDoc out = System.out;
1368        if (swallowOutput) {
1369            SystemLogHandler.startCapture();
1370        }
1371
1372        // Call the servlet destroy() method
1373
try {
1374            instanceSupport.fireInstanceEvent
1375              (InstanceEvent.BEFORE_DESTROY_EVENT, instance);
1376
1377            if( System.getSecurityManager() != null) {
1378                SecurityUtil.doAsPrivilege("destroy",
1379                                           instance);
1380                SecurityUtil.remove(instance);
1381            } else {
1382                instance.destroy();
1383            }
1384            
1385            instanceSupport.fireInstanceEvent
1386              (InstanceEvent.AFTER_DESTROY_EVENT, instance);
1387
1388            // Annotation processing
1389
if (!((Context JavaDoc) getParent()).getIgnoreAnnotations()) {
1390               ((StandardContext)getParent()).getAnnotationProcessor().preDestroy(instance);
1391            }
1392
1393        } catch (Throwable JavaDoc t) {
1394            instanceSupport.fireInstanceEvent
1395              (InstanceEvent.AFTER_DESTROY_EVENT, instance, t);
1396            instance = null;
1397            instancePool = null;
1398            nInstances = 0;
1399            fireContainerEvent("unload", this);
1400            unloading = false;
1401            throw new ServletException JavaDoc
1402                (sm.getString("standardWrapper.destroyException", getName()),
1403                 t);
1404        } finally {
1405            // Write captured output
1406
if (swallowOutput) {
1407                String JavaDoc log = SystemLogHandler.stopCapture();
1408                if (log != null && log.length() > 0) {
1409                    if (getServletContext() != null) {
1410                        getServletContext().log(log);
1411                    } else {
1412                        out.println(log);
1413                    }
1414                }
1415            }
1416        }
1417
1418        // Deregister the destroyed instance
1419
instance = null;
1420
1421        if (singleThreadModel && (instancePool != null)) {
1422            try {
1423                while (!instancePool.isEmpty()) {
1424                    Servlet JavaDoc s = (Servlet JavaDoc) instancePool.pop();
1425                    if (System.getSecurityManager() != null) {
1426                        SecurityUtil.doAsPrivilege("destroy", s);
1427                        SecurityUtil.remove(instance);
1428                    } else {
1429                        s.destroy();
1430                    }
1431                    // Annotation processing
1432
if (!((Context JavaDoc) getParent()).getIgnoreAnnotations()) {
1433                       ((StandardContext)getParent()).getAnnotationProcessor().preDestroy(s);
1434                    }
1435                }
1436            } catch (Throwable JavaDoc t) {
1437                instancePool = null;
1438                nInstances = 0;
1439                unloading = false;
1440                fireContainerEvent("unload", this);
1441                throw new ServletException JavaDoc
1442                    (sm.getString("standardWrapper.destroyException",
1443                                  getName()), t);
1444            }
1445            instancePool = null;
1446            nInstances = 0;
1447        }
1448
1449        singleThreadModel = false;
1450
1451        unloading = false;
1452        fireContainerEvent("unload", this);
1453
1454    }
1455
1456
1457    // -------------------------------------------------- ServletConfig Methods
1458

1459
1460    /**
1461     * Return the initialization parameter value for the specified name,
1462     * if any; otherwise return <code>null</code>.
1463     *
1464     * @param name Name of the initialization parameter to retrieve
1465     */

1466    public String JavaDoc getInitParameter(String JavaDoc name) {
1467
1468        return (findInitParameter(name));
1469
1470    }
1471
1472
1473    /**
1474     * Return the set of initialization parameter names defined for this
1475     * servlet. If none are defined, an empty Enumeration is returned.
1476     */

1477    public Enumeration JavaDoc getInitParameterNames() {
1478
1479        synchronized (parameters) {
1480            return (new Enumerator(parameters.keySet()));
1481        }
1482
1483    }
1484
1485
1486    /**
1487     * Return the servlet context with which this servlet is associated.
1488     */

1489    public ServletContext JavaDoc getServletContext() {
1490
1491        if (parent == null)
1492            return (null);
1493        else if (!(parent instanceof Context JavaDoc))
1494            return (null);
1495        else
1496            return (((Context JavaDoc) parent).getServletContext());
1497
1498    }
1499
1500
1501    /**
1502     * Return the name of this servlet.
1503     */

1504    public String JavaDoc getServletName() {
1505
1506        return (getName());
1507
1508    }
1509
1510    public long getProcessingTime() {
1511        return swValve.getProcessingTime();
1512    }
1513
1514    public void setProcessingTime(long processingTime) {
1515        swValve.setProcessingTime(processingTime);
1516    }
1517
1518    public long getMaxTime() {
1519        return swValve.getMaxTime();
1520    }
1521
1522    public void setMaxTime(long maxTime) {
1523        swValve.setMaxTime(maxTime);
1524    }
1525
1526    public long getMinTime() {
1527        return swValve.getMinTime();
1528    }
1529
1530    public void setMinTime(long minTime) {
1531        swValve.setMinTime(minTime);
1532    }
1533
1534    public int getRequestCount() {
1535        return swValve.getRequestCount();
1536    }
1537
1538    public void setRequestCount(int requestCount) {
1539        swValve.setRequestCount(requestCount);
1540    }
1541
1542    public int getErrorCount() {
1543        return swValve.getErrorCount();
1544    }
1545
1546    public void setErrorCount(int errorCount) {
1547           swValve.setErrorCount(errorCount);
1548    }
1549
1550    /**
1551     * Increment the error count used for monitoring.
1552     */

1553    public void incrementErrorCount(){
1554        swValve.setErrorCount(swValve.getErrorCount() + 1);
1555    }
1556
1557    public long getLoadTime() {
1558        return loadTime;
1559    }
1560
1561    public void setLoadTime(long loadTime) {
1562        this.loadTime = loadTime;
1563    }
1564
1565    public int getClassLoadTime() {
1566        return classLoadTime;
1567    }
1568
1569    // -------------------------------------------------------- Package Methods
1570

1571
1572    // -------------------------------------------------------- protected Methods
1573

1574
1575    /**
1576     * Add a default Mapper implementation if none have been configured
1577     * explicitly.
1578     *
1579     * @param mapperClass Java class name of the default Mapper
1580     */

1581    protected void addDefaultMapper(String JavaDoc mapperClass) {
1582
1583        ; // No need for a default Mapper on a Wrapper
1584

1585    }
1586
1587
1588    /**
1589     * Return <code>true</code> if the specified class name represents a
1590     * container provided servlet class that should be loaded by the
1591     * server class loader.
1592     *
1593     * @param classname Name of the class to be checked
1594     */

1595    protected boolean isContainerProvidedServlet(String JavaDoc classname) {
1596
1597        if (classname.startsWith("org.apache.catalina.")) {
1598            return (true);
1599        }
1600        try {
1601            Class JavaDoc clazz =
1602                this.getClass().getClassLoader().loadClass(classname);
1603            return (ContainerServlet.class.isAssignableFrom(clazz));
1604        } catch (Throwable JavaDoc t) {
1605            return (false);
1606        }
1607
1608    }
1609
1610
1611    /**
1612     * Return <code>true</code> if loading this servlet is allowed.
1613     */

1614    protected boolean isServletAllowed(Object JavaDoc servlet) {
1615
1616        // Privileged webapps may load all servlets without restriction
1617
if (((Context JavaDoc) getParent()).getPrivileged()) {
1618            return true;
1619        }
1620        
1621        if (servlet instanceof ContainerServlet) {
1622            return (false);
1623        }
1624
1625        Class JavaDoc clazz = servlet.getClass();
1626        while (clazz != null && !clazz.getName().equals("javax.servlet.http.HttpServlet")) {
1627            if ("restricted".equals(restrictedServlets.getProperty(clazz.getName()))) {
1628                return (false);
1629            }
1630            clazz = clazz.getSuperclass();
1631        }
1632        
1633        return (true);
1634
1635    }
1636
1637
1638    protected Method JavaDoc[] getAllDeclaredMethods(Class JavaDoc c) {
1639
1640        if (c.equals(javax.servlet.http.HttpServlet JavaDoc.class)) {
1641            return null;
1642        }
1643
1644        Method JavaDoc[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
1645
1646        Method JavaDoc[] thisMethods = c.getDeclaredMethods();
1647        if (thisMethods == null) {
1648            return parentMethods;
1649        }
1650
1651        if ((parentMethods != null) && (parentMethods.length > 0)) {
1652            Method JavaDoc[] allMethods =
1653                new Method JavaDoc[parentMethods.length + thisMethods.length];
1654        System.arraycopy(parentMethods, 0, allMethods, 0,
1655                             parentMethods.length);
1656        System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
1657                             thisMethods.length);
1658
1659        thisMethods = allMethods;
1660    }
1661
1662    return thisMethods;
1663    }
1664
1665
1666    // ------------------------------------------------------ Lifecycle Methods
1667

1668
1669    /**
1670     * Start this component, pre-loading the servlet if the load-on-startup
1671     * value is set appropriately.
1672     *
1673     * @exception LifecycleException if a fatal error occurs during startup
1674     */

1675    public void start() throws LifecycleException {
1676    
1677        // Send j2ee.state.starting notification
1678
if (this.getObjectName() != null) {
1679            Notification JavaDoc notification = new Notification JavaDoc("j2ee.state.starting",
1680                                                        this.getObjectName(),
1681                                                        sequenceNumber++);
1682            broadcaster.sendNotification(notification);
1683        }
1684        
1685        // Start up this component
1686
super.start();
1687
1688        if( oname != null )
1689            registerJMX((StandardContext)getParent());
1690        
1691        // Load and initialize an instance of this servlet if requested
1692
// MOVED TO StandardContext START() METHOD
1693

1694        setAvailable(0L);
1695        
1696        // Send j2ee.state.running notification
1697
if (this.getObjectName() != null) {
1698            Notification JavaDoc notification =
1699                new Notification JavaDoc("j2ee.state.running", this.getObjectName(),
1700                                sequenceNumber++);
1701            broadcaster.sendNotification(notification);
1702        }
1703
1704    }
1705
1706
1707    /**
1708     * Stop this component, gracefully shutting down the servlet if it has
1709     * been initialized.
1710     *
1711     * @exception LifecycleException if a fatal error occurs during shutdown
1712     */

1713    public void stop() throws LifecycleException {
1714
1715        setAvailable(Long.MAX_VALUE);
1716        
1717        // Send j2ee.state.stopping notification
1718
if (this.getObjectName() != null) {
1719            Notification JavaDoc notification =
1720                new Notification JavaDoc("j2ee.state.stopping", this.getObjectName(),
1721                                sequenceNumber++);
1722            broadcaster.sendNotification(notification);
1723        }
1724        
1725        // Shut down our servlet instance (if it has been initialized)
1726
try {
1727            unload();
1728        } catch (ServletException JavaDoc e) {
1729            getServletContext().log(sm.getString
1730                      ("standardWrapper.unloadException", getName()), e);
1731        }
1732
1733        // Shut down this component
1734
super.stop();
1735
1736        // Send j2ee.state.stoppped notification
1737
if (this.getObjectName() != null) {
1738            Notification JavaDoc notification =
1739                new Notification JavaDoc("j2ee.state.stopped", this.getObjectName(),
1740                                sequenceNumber++);
1741            broadcaster.sendNotification(notification);
1742        }
1743        
1744        if( oname != null ) {
1745            Registry.getRegistry(null, null).unregisterComponent(oname);
1746            
1747            // Send j2ee.object.deleted notification
1748
Notification JavaDoc notification =
1749                new Notification JavaDoc("j2ee.object.deleted", this.getObjectName(),
1750                                sequenceNumber++);
1751            broadcaster.sendNotification(notification);
1752        }
1753
1754        if (isJspServlet && jspMonitorON != null ) {
1755            Registry.getRegistry(null, null).unregisterComponent(jspMonitorON);
1756        }
1757
1758    }
1759
1760    protected void registerJMX(StandardContext ctx) {
1761
1762        String JavaDoc parentName = ctx.getName();
1763        parentName = ("".equals(parentName)) ? "/" : parentName;
1764
1765        String JavaDoc hostName = ctx.getParent().getName();
1766        hostName = (hostName==null) ? "DEFAULT" : hostName;
1767
1768        String JavaDoc domain = ctx.getDomain();
1769
1770        String JavaDoc webMod= "//" + hostName + parentName;
1771        String JavaDoc onameStr = domain + ":j2eeType=Servlet,name=" + getName() +
1772                          ",WebModule=" + webMod + ",J2EEApplication=" +
1773                          ctx.getJ2EEApplication() + ",J2EEServer=" +
1774                          ctx.getJ2EEServer();
1775        try {
1776            oname=new ObjectName JavaDoc(onameStr);
1777            controller=oname;
1778            Registry.getRegistry(null, null)
1779                .registerComponent(this, oname, null );
1780            
1781            // Send j2ee.object.created notification
1782
if (this.getObjectName() != null) {
1783                Notification JavaDoc notification = new Notification JavaDoc(
1784                                                "j2ee.object.created",
1785                                                this.getObjectName(),
1786                                                sequenceNumber++);
1787                broadcaster.sendNotification(notification);
1788            }
1789        } catch( Exception JavaDoc ex ) {
1790            log.info("Error registering servlet with jmx " + this);
1791        }
1792
1793        if (isJspServlet) {
1794            // Register JSP monitoring mbean
1795
onameStr = domain + ":type=JspMonitor,name=" + getName()
1796                       + ",WebModule=" + webMod
1797                       + ",J2EEApplication=" + ctx.getJ2EEApplication()
1798                       + ",J2EEServer=" + ctx.getJ2EEServer();
1799            try {
1800                jspMonitorON = new ObjectName JavaDoc(onameStr);
1801                Registry.getRegistry(null, null)
1802                    .registerComponent(instance, jspMonitorON, null);
1803            } catch( Exception JavaDoc ex ) {
1804                log.info("Error registering JSP monitoring with jmx " +
1805                         instance);
1806            }
1807        }
1808    }
1809    
1810
1811    /* Remove a JMX notficationListener
1812     * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
1813     */

1814    public void removeNotificationListener(NotificationListener JavaDoc listener,
1815            NotificationFilter JavaDoc filter, Object JavaDoc object) throws ListenerNotFoundException JavaDoc {
1816        broadcaster.removeNotificationListener(listener,filter,object);
1817        
1818    }
1819    
1820    protected MBeanNotificationInfo JavaDoc[] notificationInfo;
1821    
1822    /* Get JMX Broadcaster Info
1823     * @TODO use StringManager for international support!
1824     * @TODO This two events we not send j2ee.state.failed and j2ee.attribute.changed!
1825     * @see javax.management.NotificationBroadcaster#getNotificationInfo()
1826     */

1827    public MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
1828        
1829        if(notificationInfo == null) {
1830            notificationInfo = new MBeanNotificationInfo JavaDoc[]{
1831                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
1832                    "j2ee.object.created"},
1833                    Notification JavaDoc.class.getName(),
1834                    "servlet is created"
1835                    ),
1836                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
1837                    "j2ee.state.starting"},
1838                    Notification JavaDoc.class.getName(),
1839                    "servlet is starting"
1840                    ),
1841                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
1842                    "j2ee.state.running"},
1843                    Notification JavaDoc.class.getName(),
1844                    "servlet is running"
1845                    ),
1846                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
1847                    "j2ee.state.stopped"},
1848                    Notification JavaDoc.class.getName(),
1849                    "servlet start to stopped"
1850                    ),
1851                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
1852                    "j2ee.object.stopped"},
1853                    Notification JavaDoc.class.getName(),
1854                    "servlet is stopped"
1855                    ),
1856                    new MBeanNotificationInfo JavaDoc(new String JavaDoc[] {
1857                    "j2ee.object.deleted"},
1858                    Notification JavaDoc.class.getName(),
1859                    "servlet is deleted"
1860                    )
1861            };
1862            
1863        }
1864        
1865        return notificationInfo;
1866    }
1867    
1868    
1869    /* Add a JMX-NotificationListener
1870     * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
1871     */

1872    public void addNotificationListener(NotificationListener JavaDoc listener,
1873            NotificationFilter JavaDoc filter, Object JavaDoc object) throws IllegalArgumentException JavaDoc {
1874        broadcaster.addNotificationListener(listener,filter,object);
1875    }
1876    
1877    
1878    /**
1879     * Remove a JMX-NotificationListener
1880     * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
1881     */

1882    public void removeNotificationListener(NotificationListener JavaDoc listener)
1883        throws ListenerNotFoundException JavaDoc {
1884        broadcaster.removeNotificationListener(listener);
1885    }
1886    
1887    
1888     // ------------------------------------------------------------- Attributes
1889

1890        
1891    public boolean isEventProvider() {
1892        return false;
1893    }
1894    
1895    public boolean isStateManageable() {
1896        return false;
1897    }
1898    
1899    public boolean isStatisticsProvider() {
1900        return false;
1901    }
1902        
1903        
1904}
1905
Popular Tags