Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » core » [javadoc | source]
    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;
   22   import java.io.IOException;
   23   import java.io.InputStream;
   24   import java.io.PrintStream;
   25   import java.util.ArrayList;
   26   import java.util.Enumeration;
   27   import java.util.HashMap;
   28   import java.util.HashSet;
   29   import java.util.Properties;
   30   import java.util.Stack;
   31   import java.security.AccessController;
   32   import java.security.PrivilegedActionException;
   33   import java.security.PrivilegedExceptionAction;
   34   import javax.servlet.Servlet;
   35   import javax.servlet.ServletConfig;
   36   import javax.servlet.ServletContext;
   37   import javax.servlet.ServletException;
   38   import javax.servlet.ServletRequest;
   39   import javax.servlet.ServletResponse;
   40   import javax.servlet.SingleThreadModel;
   41   import javax.servlet.UnavailableException;
   42   import javax.management.ListenerNotFoundException;
   43   import javax.management.MBeanNotificationInfo;
   44   import javax.management.Notification;
   45   import javax.management.NotificationBroadcasterSupport;
   46   import javax.management.NotificationEmitter;
   47   import javax.management.NotificationFilter;
   48   import javax.management.NotificationListener;
   49   import javax.management.ObjectName;
   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.Globals;
   56   import org.apache.catalina.InstanceEvent;
   57   import org.apache.catalina.InstanceListener;
   58   import org.apache.catalina.LifecycleException;
   59   import org.apache.catalina.Loader;
   60   import org.apache.catalina.Wrapper;
   61   import org.apache.catalina.security.SecurityUtil;
   62   import org.apache.catalina.util.Enumerator;
   63   import org.apache.catalina.util.InstanceSupport;
   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: 598795 $ $Date: 2007-11-27 23:43:49 +0100 (mar., 27 nov. 2007) $
   75    */
   76   public class StandardWrapper
   77       extends ContainerBase
   78       implements ServletConfig, Wrapper, NotificationEmitter {
   79   
   80       protected static org.apache.juli.logging.Log log=
   81           org.apache.juli.logging.LogFactory.getLog( StandardWrapper.class );
   82   
   83       protected static final String[] DEFAULT_SERVLET_METHODS = new String[] {
   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();
   98   
   99           if (restrictedServlets == null) {
  100               restrictedServlets = new Properties();
  101               try {
  102                   InputStream 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 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 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 info =
  152           "org.apache.catalina.core.StandardWrapper/1.0";
  153   
  154   
  155       /**
  156        * The (single) initialized instance of this servlet.
  157        */
  158       protected Servlet 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 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 mappings = new ArrayList();
  184   
  185   
  186       /**
  187        * The initialization parameters for this servlet, keyed by
  188        * parameter name.
  189        */
  190       protected HashMap parameters = new HashMap();
  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 references = new HashMap();
  199   
  200   
  201       /**
  202        * The run-as identity for this servlet.
  203        */
  204       protected String 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 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 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 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[] classType = new Class[]{ServletConfig.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[] classTypeUsedInService = new Class[]{
  287                                                            ServletRequest.class,
  288                                                            ServletResponse.class};
  289       
  290       /**
  291        * Restricted servlets (which can only be loaded by a privileged webapp).
  292        */
  293       protected static Properties 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(oldAvailable),
  331                                      new Long(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 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 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 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 jspFile) {
  391   
  392           String 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(oldLoadOnStartup),
  435                                      new Integer(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 value) {
  450   
  451           try {
  452               setLoadOnStartup(Integer.parseInt(value));
  453           } catch (NumberFormatException e) {
  454               setLoadOnStartup(0);
  455           }
  456       }
  457   
  458       public String 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))
  499               throw new IllegalArgumentException
  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 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 runAs) {
  526   
  527           String 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 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 servletClass) {
  550   
  551           String 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 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 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[] getServletMethods() throws ServletException {
  620   
  621           Class servletClazz = loadServlet().getClass();
  622           if (!javax.servlet.http.HttpServlet.class.isAssignableFrom(
  623                                                           servletClazz)) {
  624               return DEFAULT_SERVLET_METHODS;
  625           }
  626   
  627           HashSet allow = new HashSet();
  628           allow.add("TRACE");
  629           allow.add("OPTIONS");
  630   	
  631           Method[] methods = getAllDeclaredMethods(servletClazz);
  632           for (int i=0; methods != null && i<methods.length; i++) {
  633               Method 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[] methodNames = new String[allow.size()];
  648           return (String[]) 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 getRootCause(ServletException e) {
  679           Throwable rootCause = e;
  680           Throwable 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
  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 name, String 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 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 name, String 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 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 allocate() throws ServletException {
  789   
  790           // If we are currently unloading this servlet, throw an exception
  791           if (unloading)
  792               throw new ServletException
  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 e) {
  808                               throw e;
  809                           } catch (Throwable e) {
  810                               throw new ServletException
  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 e) {
  835                           throw e;
  836                       } catch (Throwable e) {
  837                           throw new ServletException
  838                               (sm.getString("standardWrapper.allocate"), e);
  839                       }
  840                   } else {
  841                       try {
  842                           instancePool.wait();
  843                       } catch (InterruptedException e) {
  844                           ;
  845                       }
  846                   }
  847               }
  848               if (log.isTraceEnabled())
  849                   log.trace("  Returning allocated STM instance");
  850               countAllocated++;
  851               return (Servlet) 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 servlet) throws ServletException {
  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 findInitParameter(String name) {
  892   
  893           synchronized (parameters) {
  894               return ((String) 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[] findInitParameters() {
  905   
  906           synchronized (parameters) {
  907               String results[] = new String[parameters.size()];
  908               return ((String[]) parameters.keySet().toArray(results));
  909           }
  910   
  911       }
  912   
  913   
  914       /**
  915        * Return the mappings associated with this wrapper.
  916        */
  917       public String[] findMappings() {
  918   
  919           synchronized (mappings) {
  920               return (String[]) mappings.toArray(new String[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 findSecurityReference(String name) {
  933   
  934           synchronized (references) {
  935               return ((String) 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[] findSecurityReferences() {
  946   
  947           synchronized (references) {
  948               String results[] = new String[references.size()];
  949               return ((String[]) 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 {
  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 loadServlet() throws ServletException {
  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 out = System.out;
  998           if (swallowOutput) {
  999               SystemLogHandler.startCapture();
 1000           }
 1001   
 1002           Servlet 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 actualClass = servletClass;
 1011               if ((actualClass == null) && (jspFile != null)) {
 1012                   Wrapper jspWrapper = (Wrapper)
 1013                       ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
 1014                   if (jspWrapper != null) {
 1015                       actualClass = jspWrapper.getServletClass();
 1016                       // Merge init parameters
 1017                       String 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
 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
 1040                       (sm.getString("standardWrapper.missingLoader", getName()));
 1041               }
 1042   
 1043               ClassLoader classLoader = loader.getClassLoader();
 1044   
 1045               // Special case class loader for a container provided servlet
 1046               //  
 1047               if (isContainerProvidedServlet(actualClass) && 
 1048                       ! ((Context)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 classClass = null;
 1057               try {
 1058                   if (SecurityUtil.isPackageProtectionEnabled()){
 1059                       final ClassLoader fclassLoader = classLoader;
 1060                       final String factualClass = actualClass;
 1061                       try{
 1062                           classClass = (Class)AccessController.doPrivileged(
 1063                                   new PrivilegedExceptionAction(){
 1064                                       public Object run() throws Exception{
 1065                                           if (fclassLoader != null) {
 1066                                               return fclassLoader.loadClass(factualClass);
 1067                                           } else {
 1068                                               return Class.forName(factualClass);
 1069                                           }
 1070                                       }
 1071                           });
 1072                       } catch(PrivilegedActionException pax){
 1073                           Exception ex = pax.getException();
 1074                           if (ex instanceof ClassNotFoundException){
 1075                               throw (ClassNotFoundException)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 e) {
 1089                   unavailable(null);
 1090                   getServletContext().log( "Error loading " + classLoader + " " + actualClass, e );
 1091                   throw new ServletException
 1092                       (sm.getString("standardWrapper.missingClass", actualClass),
 1093                        e);
 1094               }
 1095   
 1096               if (classClass == null) {
 1097                   unavailable(null);
 1098                   throw new ServletException
 1099                       (sm.getString("standardWrapper.missingClass", actualClass));
 1100               }
 1101   
 1102               // Instantiate and initialize an instance of the servlet class itself
 1103               try {
 1104                   servlet = (Servlet) classClass.newInstance();
 1105                   // Annotation processing
 1106                   if (!((Context) getParent()).getIgnoreAnnotations()) {
 1107                       if (getParent() instanceof StandardContext) {
 1108                          ((StandardContext)getParent()).getAnnotationProcessor().processAnnotations(servlet);
 1109                          ((StandardContext)getParent()).getAnnotationProcessor().postConstruct(servlet);
 1110                       }
 1111                   }
 1112               } catch (ClassCastException e) {
 1113                   unavailable(null);
 1114                   // Restore the context ClassLoader
 1115                   throw new ServletException
 1116                       (sm.getString("standardWrapper.notServlet", actualClass), e);
 1117               } catch (Throwable 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
 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
 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)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( Globals.IS_SECURITY_ENABLED) {
 1153   
 1154                       Object[] args = new Object[]{((ServletConfig)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( Globals.IS_SECURITY_ENABLED) {
 1173                           Object[] args = new Object[]{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 f) {
 1186                   instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
 1187                                                     servlet, f);
 1188                   unavailable(f);
 1189                   throw f;
 1190               } catch (ServletException 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 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
 1203                       (sm.getString("standardWrapper.initException", getName()), f);
 1204               }
 1205   
 1206               // Register our newly initialized instance
 1207               singleThreadModel = servlet instanceof SingleThreadModel;
 1208               if (singleThreadModel) {
 1209                   if (instancePool == null)
 1210                       instancePool = new Stack();
 1211               }
 1212               fireContainerEvent("load", this);
 1213   
 1214               loadTime=System.currentTimeMillis() -t1;
 1215           } finally {
 1216               if (swallowOutput) {
 1217                   String 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 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 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 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 toString() {
 1293   
 1294           StringBuffer sb = new StringBuffer();
 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 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 {
 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(countAllocated)));
 1357                   }
 1358                   try {
 1359                       Thread.sleep(delay);
 1360                   } catch (InterruptedException e) {
 1361                       ;
 1362                   }
 1363                   nRetries++;
 1364               }
 1365           }
 1366   
 1367           PrintStream 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( Globals.IS_SECURITY_ENABLED) {
 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) getParent()).getIgnoreAnnotations()) {
 1390                  ((StandardContext)getParent()).getAnnotationProcessor().preDestroy(instance);
 1391               }
 1392   
 1393           } catch (Throwable 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
 1402                   (sm.getString("standardWrapper.destroyException", getName()),
 1403                    t);
 1404           } finally {
 1405               // Write captured output
 1406               if (swallowOutput) {
 1407                   String 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 s = (Servlet) instancePool.pop();
 1425                       if (Globals.IS_SECURITY_ENABLED) {
 1426                           SecurityUtil.doAsPrivilege("destroy", s);
 1427                           SecurityUtil.remove(instance);                           
 1428                       } else {
 1429                           s.destroy();
 1430                       }
 1431                       // Annotation processing
 1432                       if (!((Context) getParent()).getIgnoreAnnotations()) {
 1433                          ((StandardContext)getParent()).getAnnotationProcessor().preDestroy(s);
 1434                       }
 1435                   }
 1436               } catch (Throwable t) {
 1437                   instancePool = null;
 1438                   nInstances = 0;
 1439                   unloading = false;
 1440                   fireContainerEvent("unload", this);
 1441                   throw new ServletException
 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 getInitParameter(String 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 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 getServletContext() {
 1490   
 1491           if (parent == null)
 1492               return (null);
 1493           else if (!(parent instanceof Context))
 1494               return (null);
 1495           else
 1496               return (((Context) parent).getServletContext());
 1497   
 1498       }
 1499   
 1500   
 1501       /**
 1502        * Return the name of this servlet.
 1503        */
 1504       public String 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 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 classname) {
 1596   
 1597           if (classname.startsWith("org.apache.catalina.")) {
 1598               return (true);
 1599           }
 1600           try {
 1601               Class clazz =
 1602                   this.getClass().getClassLoader().loadClass(classname);
 1603               return (ContainerServlet.class.isAssignableFrom(clazz));
 1604           } catch (Throwable 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 servlet) {
 1615   
 1616           // Privileged webapps may load all servlets without restriction
 1617           if (((Context) getParent()).getPrivileged()) {
 1618               return true;
 1619           }
 1620           
 1621           if (servlet instanceof ContainerServlet) {
 1622               return (false);
 1623           }
 1624   
 1625           Class 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[] getAllDeclaredMethods(Class c) {
 1639   
 1640           if (c.equals(javax.servlet.http.HttpServlet.class)) {
 1641               return null;
 1642           }
 1643   
 1644           Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());
 1645   
 1646           Method[] thisMethods = c.getDeclaredMethods();
 1647           if (thisMethods == null) {
 1648               return parentMethods;
 1649           }
 1650   
 1651           if ((parentMethods != null) && (parentMethods.length > 0)) {
 1652               Method[] allMethods =
 1653                   new Method[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 notification = new Notification("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 notification = 
 1699                   new Notification("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 notification = 
 1720                   new Notification("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 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 notification = 
 1739                   new Notification("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 notification = 
 1749                   new Notification("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 parentName = ctx.getName();
 1763           parentName = ("".equals(parentName)) ? "/" : parentName;
 1764   
 1765           String hostName = ctx.getParent().getName();
 1766           hostName = (hostName==null) ? "DEFAULT" : hostName;
 1767   
 1768           String domain = ctx.getDomain();
 1769   
 1770           String webMod= "//" + hostName + parentName;
 1771           String onameStr = domain + ":j2eeType=Servlet,name=" + getName() +
 1772                             ",WebModule=" + webMod + ",J2EEApplication=" +
 1773                             ctx.getJ2EEApplication() + ",J2EEServer=" +
 1774                             ctx.getJ2EEServer();
 1775           try {
 1776               oname=new ObjectName(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 notification = new Notification(
 1784                                                   "j2ee.object.created", 
 1785                                                   this.getObjectName(), 
 1786                                                   sequenceNumber++);
 1787                   broadcaster.sendNotification(notification);
 1788               }
 1789           } catch( Exception ex ) {
 1790               log.info("Error registering servlet with jmx " + this, ex);
 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(onameStr);
 1801                   Registry.getRegistry(null, null)
 1802                       .registerComponent(instance, jspMonitorON, null);
 1803               } catch( Exception ex ) {
 1804                   log.info("Error registering JSP monitoring with jmx " +
 1805                            instance, ex);
 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 listener, 
 1815       		NotificationFilter filter, Object object) throws ListenerNotFoundException {
 1816       	broadcaster.removeNotificationListener(listener,filter,object);
 1817       	
 1818       }
 1819       
 1820       protected MBeanNotificationInfo[] 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[] getNotificationInfo() {
 1828       	
 1829       	if(notificationInfo == null) {
 1830       		notificationInfo = new MBeanNotificationInfo[]{
 1831       				new MBeanNotificationInfo(new String[] {
 1832       				"j2ee.object.created"},
 1833   					Notification.class.getName(),
 1834   					"servlet is created"
 1835       				), 
 1836   					new MBeanNotificationInfo(new String[] {
 1837   					"j2ee.state.starting"},
 1838   					Notification.class.getName(),
 1839   					"servlet is starting"
 1840   					),
 1841   					new MBeanNotificationInfo(new String[] {
 1842   					"j2ee.state.running"},
 1843   					Notification.class.getName(),
 1844   					"servlet is running"
 1845   					),
 1846   					new MBeanNotificationInfo(new String[] {
 1847   					"j2ee.state.stopped"},
 1848   					Notification.class.getName(),
 1849   					"servlet start to stopped"
 1850   					),
 1851   					new MBeanNotificationInfo(new String[] {
 1852   					"j2ee.object.stopped"},
 1853   					Notification.class.getName(),
 1854   					"servlet is stopped"
 1855   					),
 1856   					new MBeanNotificationInfo(new String[] {
 1857   					"j2ee.object.deleted"},
 1858   					Notification.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 listener, 
 1873               NotificationFilter filter, Object object) throws IllegalArgumentException {
 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 listener) 
 1883           throws ListenerNotFoundException {
 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   }

Save This Page
Home » apache-tomcat-6.0.16-src » org.apache » catalina » core » [javadoc | source]