FileDocCategorySizeDatePackage
StandardWrapper.javaAPI DocApache Tomcat 6.0.1462222Fri Jul 20 04:20:32 BST 2007org.apache.catalina.core

StandardWrapper

public class StandardWrapper extends ContainerBase implements org.apache.catalina.Wrapper, NotificationEmitter, ServletConfig
Standard implementation of the Wrapper interface that represents an individual servlet definition. No child Containers are allowed, and the parent Container must be a Context.
author
Craig R. McClanahan
author
Remy Maucherat
version
$Revision: 505593 $ $Date: 2007-02-10 01:54:56 +0100 (sam., 10 févr. 2007) $

Fields Summary
protected static org.apache.juli.logging.Log
log
protected static final String[]
DEFAULT_SERVLET_METHODS
protected long
available
The date and time at which this servlet will become available (in milliseconds since the epoch), or zero if the servlet is available. If this value equals Long.MAX_VALUE, the unavailability of this servlet is considered permanent.
protected NotificationBroadcasterSupport
broadcaster
The broadcaster that sends j2ee notifications.
protected int
countAllocated
The count of allocations that are currently active (even if they are for the same instance, as will be true on a non-STM servlet).
protected StandardWrapperFacade
facade
The facade associated with this wrapper.
protected static final String
info
The descriptive information string for this implementation.
protected Servlet
instance
The (single) initialized instance of this servlet.
protected org.apache.catalina.util.InstanceSupport
instanceSupport
The support object for our instance listeners.
protected String
jspFile
The context-relative URI of the JSP file for this servlet.
protected int
loadOnStartup
The load-on-startup order value (negative value means load on first call) for this servlet.
protected ArrayList
mappings
Mappings associated with the wrapper.
protected HashMap
parameters
The initialization parameters for this servlet, keyed by parameter name.
protected HashMap
references
The security role references for this servlet, keyed by role name used in the servlet. The corresponding value is the role name of the web application itself.
protected String
runAs
The run-as identity for this servlet.
protected long
sequenceNumber
The notification sequence number.
protected String
servletClass
The fully qualified servlet class name for this servlet.
protected boolean
singleThreadModel
Does this servlet implement the SingleThreadModel interface?
protected boolean
unloading
Are we unloading our servlet instance at the moment?
protected int
maxInstances
Maximum number of STM instances.
protected int
nInstances
Number of instances currently loaded for a STM servlet.
protected Stack
instancePool
Stack containing the STM instances.
protected long
unloadDelay
Wait time for servlet unload in ms.
protected boolean
isJspServlet
True if this StandardWrapper is for the JspServlet
protected ObjectName
jspMonitorON
The ObjectName of the JSP monitoring mbean
protected boolean
swallowOutput
Should we swallow System.out
protected StandardWrapperValve
swValve
protected long
loadTime
protected int
classLoadTime
protected static Class[]
classType
Static class array used when the SecurityManager is turned on and Servlet.init is invoked.
protected static Class[]
classTypeUsedInService
Static class array used when the SecurityManager is turned on and Servlet.service is invoked.
protected static Properties
restrictedServlets
Restricted servlets (which can only be loaded by a privileged webapp).
protected MBeanNotificationInfo[]
notificationInfo
Constructors Summary
public StandardWrapper()
Create a new StandardWrapper component with the default basic Valve.


    // ----------------------------------------------------------- Constructors


                   
      

        super();
        swValve=new StandardWrapperValve();
        pipeline.setBasic(swValve);
        broadcaster = new NotificationBroadcasterSupport();

        if (restrictedServlets == null) {
            restrictedServlets = new Properties();
            try {
                InputStream is = 
                    this.getClass().getClassLoader().getResourceAsStream
                        ("org/apache/catalina/core/RestrictedServlets.properties");
                if (is != null) {
                    restrictedServlets.load(is);
                } else {
                    log.error(sm.getString("standardWrapper.restrictedServletsResource"));
                }
            } catch (IOException e) {
                log.error(sm.getString("standardWrapper.restrictedServletsResource"), e);
            }
        }
        
    
Methods Summary
public voidaddChild(org.apache.catalina.Container child)
Refuse to add a child Container, because Wrappers are the lowest level of the Container hierarchy.

param
child Child container to be added


        throw new IllegalStateException
            (sm.getString("standardWrapper.notChild"));

    
protected voidaddDefaultMapper(java.lang.String mapperClass)
Add a default Mapper implementation if none have been configured explicitly.

param
mapperClass Java class name of the default Mapper


        ;       // No need for a default Mapper on a Wrapper

    
public voidaddInitParameter(java.lang.String name, java.lang.String value)
Add a new servlet initialization parameter for this servlet.

param
name Name of this initialization parameter to add
param
value Value of this initialization parameter to add


        synchronized (parameters) {
            parameters.put(name, value);
        }
        fireContainerEvent("addInitParameter", name);

    
public voidaddInstanceListener(org.apache.catalina.InstanceListener listener)
Add a new listener interested in InstanceEvents.

param
listener The new listener


        instanceSupport.addInstanceListener(listener);

    
public voidaddMapping(java.lang.String mapping)
Add a mapping associated with the Wrapper.

param
mapping The new wrapper mapping


        synchronized (mappings) {
            mappings.add(mapping);
        }
        fireContainerEvent("addMapping", mapping);

    
public voidaddNotificationListener(javax.management.NotificationListener listener, javax.management.NotificationFilter filter, java.lang.Object object)

    	broadcaster.addNotificationListener(listener,filter,object);
    
public voidaddSecurityReference(java.lang.String name, java.lang.String link)
Add a new security role reference record to the set of records for this servlet.

param
name Role name used within this servlet
param
link Role name used within the web application


        synchronized (references) {
            references.put(name, link);
        }
        fireContainerEvent("addSecurityReference", name);

    
public javax.servlet.Servletallocate()
Allocate an initialized instance of this Servlet that is ready to have its service() method called. If the servlet class does not implement SingleThreadModel, the (only) initialized instance may be returned immediately. If the servlet class implements SingleThreadModel, the Wrapper implementation must ensure that this instance is not allocated again until it is deallocated by a call to deallocate().

exception
ServletException if the servlet init() method threw an exception
exception
ServletException if a loading error occurs


        // If we are currently unloading this servlet, throw an exception
        if (unloading)
            throw new ServletException
              (sm.getString("standardWrapper.unloading", getName()));

        // If not SingleThreadedModel, return the same instance every time
        if (!singleThreadModel) {

            // Load and initialize our instance if necessary
            if (instance == null) {
                synchronized (this) {
                    if (instance == null) {
                        try {
                            if (log.isDebugEnabled())
                                log.debug("Allocating non-STM instance");

                            instance = loadServlet();
                        } catch (ServletException e) {
                            throw e;
                        } catch (Throwable e) {
                            throw new ServletException
                                (sm.getString("standardWrapper.allocate"), e);
                        }
                    }
                }
            }

            if (!singleThreadModel) {
                if (log.isTraceEnabled())
                    log.trace("  Returning non-STM instance");
                countAllocated++;
                return (instance);
            }

        }

        synchronized (instancePool) {

            while (countAllocated >= nInstances) {
                // Allocate a new instance if possible, or else wait
                if (nInstances < maxInstances) {
                    try {
                        instancePool.push(loadServlet());
                        nInstances++;
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        throw new ServletException
                            (sm.getString("standardWrapper.allocate"), e);
                    }
                } else {
                    try {
                        instancePool.wait();
                    } catch (InterruptedException e) {
                        ;
                    }
                }
            }
            if (log.isTraceEnabled())
                log.trace("  Returning allocated STM instance");
            countAllocated++;
            return (Servlet) instancePool.pop();

        }

    
public voidbackgroundProcess()
Execute a periodic task, such as reloading, etc. This method will be invoked inside the classloading context of this container. Unexpected throwables will be caught and logged.

        super.backgroundProcess();
        
        if (!started)
            return;
        
        if (getServlet() != null && (getServlet() instanceof PeriodicEventListener)) {
            ((PeriodicEventListener) getServlet()).periodicEvent();
        }
    
public voiddeallocate(javax.servlet.Servlet servlet)
Return this previously allocated servlet to the pool of available instances. If this servlet class does not implement SingleThreadModel, no action is actually required.

param
servlet The servlet to be returned
exception
ServletException if a deallocation error occurs


        // If not SingleThreadModel, no action is required
        if (!singleThreadModel) {
            countAllocated--;
            return;
        }

        // Unlock and free this instance
        synchronized (instancePool) {
            countAllocated--;
            instancePool.push(servlet);
            instancePool.notify();
        }

    
public java.lang.StringfindInitParameter(java.lang.String name)
Return the value for the specified initialization parameter name, if any; otherwise return null.

param
name Name of the requested initialization parameter


        synchronized (parameters) {
            return ((String) parameters.get(name));
        }

    
public java.lang.String[]findInitParameters()
Return the names of all defined initialization parameters for this servlet.


        synchronized (parameters) {
            String results[] = new String[parameters.size()];
            return ((String[]) parameters.keySet().toArray(results));
        }

    
public org.apache.catalina.WrapperfindMappingObject()
FIXME: Fooling introspection ...

        return (Wrapper) getMappingObject();
    
public java.lang.String[]findMappings()
Return the mappings associated with this wrapper.


        synchronized (mappings) {
            return (String[]) mappings.toArray(new String[mappings.size()]);
        }

    
public java.lang.StringfindSecurityReference(java.lang.String name)
Return the security role link for the specified security role reference name, if any; otherwise return null.

param
name Security role reference used within this servlet


        synchronized (references) {
            return ((String) references.get(name));
        }

    
public java.lang.String[]findSecurityReferences()
Return the set of security role reference names associated with this servlet, if any; otherwise return a zero-length array.


        synchronized (references) {
            String results[] = new String[references.size()];
            return ((String[]) references.keySet().toArray(results));
        }

    
protected java.lang.reflect.Method[]getAllDeclaredMethods(java.lang.Class c)


        if (c.equals(javax.servlet.http.HttpServlet.class)) {
            return null;
        }

        Method[] parentMethods = getAllDeclaredMethods(c.getSuperclass());

        Method[] thisMethods = c.getDeclaredMethods();
        if (thisMethods == null) {
            return parentMethods;
        }

        if ((parentMethods != null) && (parentMethods.length > 0)) {
            Method[] allMethods =
                new Method[parentMethods.length + thisMethods.length];
	    System.arraycopy(parentMethods, 0, allMethods, 0,
                             parentMethods.length);
	    System.arraycopy(thisMethods, 0, allMethods, parentMethods.length,
                             thisMethods.length);

	    thisMethods = allMethods;
	}

	return thisMethods;
    
public longgetAvailable()
Return the available date/time for this servlet, in milliseconds since the epoch. If this date/time is Long.MAX_VALUE, it is considered to mean that unavailability is permanent and any request for this servlet will return an SC_NOT_FOUND error. If this date/time is in the future, any request for this servlet will return an SC_SERVICE_UNAVAILABLE error. If it is zero, the servlet is currently available.

    
    
    // ------------------------------------------------------------- Properties


                                                                           
       

        return (this.available);

    
public intgetClassLoadTime()

        return classLoadTime;
    
public intgetCountAllocated()
Return the number of active allocations of this servlet, even if they are all for the same instance (as will be true for servlets that do not implement SingleThreadModel.


        return (this.countAllocated);

    
public java.lang.StringgetEngineName()

        return ((StandardContext)getParent()).getEngineName();
    
public intgetErrorCount()

        return swValve.getErrorCount();
    
public java.lang.StringgetInfo()
Return descriptive information about this Container implementation and the corresponding version number, in the format <description>/<version>.


        return (info);

    
public java.lang.StringgetInitParameter(java.lang.String name)
Return the initialization parameter value for the specified name, if any; otherwise return null.

param
name Name of the initialization parameter to retrieve


        return (findInitParameter(name));

    
public java.util.EnumerationgetInitParameterNames()
Return the set of initialization parameter names defined for this servlet. If none are defined, an empty Enumeration is returned.


        synchronized (parameters) {
            return (new Enumerator(parameters.keySet()));
        }

    
public org.apache.catalina.util.InstanceSupportgetInstanceSupport()
Return the InstanceSupport object for this Wrapper instance.


        return (this.instanceSupport);

    
public java.lang.StringgetJspFile()
Return the context-relative URI of the JSP file for this servlet.


        return (this.jspFile);

    
public intgetLoadOnStartup()
Return the load-on-startup order value (negative value means load on first call).


        if (isJspServlet && loadOnStartup < 0) {
            /*
             * JspServlet must always be preloaded, because its instance is
             * used during registerJMX (when registering the JSP
             * monitoring mbean)
             */
             return Integer.MAX_VALUE;
        } else {
            return (this.loadOnStartup);
        }
    
public java.lang.StringgetLoadOnStartupString()

        return Integer.toString( getLoadOnStartup());
    
public longgetLoadTime()

        return loadTime;
    
public intgetMaxInstances()
Return maximum number of instances that will be allocated when a single thread model servlet is used.


        return (this.maxInstances);

    
public longgetMaxTime()

        return swValve.getMaxTime();
    
public longgetMinTime()

        return swValve.getMinTime();
    
public javax.management.MBeanNotificationInfo[]getNotificationInfo()

    	
    	if(notificationInfo == null) {
    		notificationInfo = new MBeanNotificationInfo[]{
    				new MBeanNotificationInfo(new String[] {
    				"j2ee.object.created"},
					Notification.class.getName(),
					"servlet is created"
    				), 
					new MBeanNotificationInfo(new String[] {
					"j2ee.state.starting"},
					Notification.class.getName(),
					"servlet is starting"
					),
					new MBeanNotificationInfo(new String[] {
					"j2ee.state.running"},
					Notification.class.getName(),
					"servlet is running"
					),
					new MBeanNotificationInfo(new String[] {
					"j2ee.state.stopped"},
					Notification.class.getName(),
					"servlet start to stopped"
					),
					new MBeanNotificationInfo(new String[] {
					"j2ee.object.stopped"},
					Notification.class.getName(),
					"servlet is stopped"
					),
					new MBeanNotificationInfo(new String[] {
					"j2ee.object.deleted"},
					Notification.class.getName(),
					"servlet is deleted"
					)
    		};
    		
    	}
    	
    	return notificationInfo;
    
public longgetProcessingTime()

        return swValve.getProcessingTime();
    
public intgetRequestCount()

        return swValve.getRequestCount();
    
public static java.lang.ThrowablegetRootCause(javax.servlet.ServletException e)
Extract the root cause from a servlet exception.

param
e The servlet exception

        Throwable rootCause = e;
        Throwable rootCauseCheck = null;
        // Extra aggressive rootCause finding
        int loops = 0;
        do {
            loops++;
            rootCauseCheck = rootCause.getCause();
            if (rootCauseCheck != null)
                rootCause = rootCauseCheck;
        } while (rootCauseCheck != null && (loops < 20));
        return rootCause;
    
public java.lang.StringgetRunAs()
Return the run-as identity for this servlet.


        return (this.runAs);

    
public javax.servlet.ServletgetServlet()
Return the associated servlet instance.

        return instance;
    
public java.lang.StringgetServletClass()
Return the fully qualified servlet class name for this servlet.


        return (this.servletClass);

    
public javax.servlet.ServletContextgetServletContext()
Return the servlet context with which this servlet is associated.


        if (parent == null)
            return (null);
        else if (!(parent instanceof Context))
            return (null);
        else
            return (((Context) parent).getServletContext());

    
public java.lang.String[]getServletMethods()
Gets the names of the methods supported by the underlying servlet. This is the same set of methods included in the Allow response header in response to an OPTIONS request method processed by the underlying servlet.

return
Array of names of the methods supported by the underlying servlet


        Class servletClazz = loadServlet().getClass();
        if (!javax.servlet.http.HttpServlet.class.isAssignableFrom(
                                                        servletClazz)) {
            return DEFAULT_SERVLET_METHODS;
        }

        HashSet allow = new HashSet();
        allow.add("TRACE");
        allow.add("OPTIONS");
	
        Method[] methods = getAllDeclaredMethods(servletClazz);
        for (int i=0; methods != null && i<methods.length; i++) {
            Method m = methods[i];
	    
            if (m.getName().equals("doGet")) {
                allow.add("GET");
                allow.add("HEAD");
            } else if (m.getName().equals("doPost")) {
                allow.add("POST");
            } else if (m.getName().equals("doPut")) {
                allow.add("PUT");
            } else if (m.getName().equals("doDelete")) {
                allow.add("DELETE");
            }
        }

        String[] methodNames = new String[allow.size()];
        return (String[]) allow.toArray(methodNames);

    
public java.lang.StringgetServletName()
Return the name of this servlet.


        return (getName());

    
public voidincrementErrorCount()
Increment the error count used for monitoring.

        swValve.setErrorCount(swValve.getErrorCount() + 1);
    
protected booleanisContainerProvidedServlet(java.lang.String classname)
Return true if the specified class name represents a container provided servlet class that should be loaded by the server class loader.

param
classname Name of the class to be checked


        if (classname.startsWith("org.apache.catalina.")) {
            return (true);
        }
        try {
            Class clazz =
                this.getClass().getClassLoader().loadClass(classname);
            return (ContainerServlet.class.isAssignableFrom(clazz));
        } catch (Throwable t) {
            return (false);
        }

    
public booleanisEventProvider()

        return false;
    
protected booleanisServletAllowed(java.lang.Object servlet)
Return true if loading this servlet is allowed.


        // Privileged webapps may load all servlets without restriction
        if (((Context) getParent()).getPrivileged()) {
            return true;
        }
        
        if (servlet instanceof ContainerServlet) {
            return (false);
        }

        Class clazz = servlet.getClass();
        while (clazz != null && !clazz.getName().equals("javax.servlet.http.HttpServlet")) {
            if ("restricted".equals(restrictedServlets.getProperty(clazz.getName()))) {
                return (false);
            }
            clazz = clazz.getSuperclass();
        }
        
        return (true);

    
public booleanisSingleThreadModel()
Return true if the servlet class represented by this component implements the SingleThreadModel interface.


        try {
            loadServlet();
        } catch (Throwable t) {
            ;
        }
        return (singleThreadModel);

    
public booleanisStateManageable()

        return false;
    
public booleanisStatisticsProvider()

        return false;
    
public booleanisUnavailable()
Is this servlet currently unavailable?


        if (available == 0L)
            return (false);
        else if (available <= System.currentTimeMillis()) {
            available = 0L;
            return (false);
        } else
            return (true);

    
public synchronized voidload()
Load and initialize an instance of this servlet, if there is not already at least one initialized instance. This can be used, for example, to load servlets that are marked in the deployment descriptor to be loaded at server startup time.

IMPLEMENTATION NOTE: Servlets whose classnames begin with org.apache.catalina. (so-called "container" servlets) are loaded by the same classloader that loaded this class, rather than the classloader for the current web application. This gives such classes access to Catalina internals, which are prevented for classes loaded for web applications.

exception
ServletException if the servlet init() method threw an exception
exception
ServletException if some other loading problem occurs

        instance = loadServlet();
    
public synchronized javax.servlet.ServletloadServlet()
Load and initialize an instance of this servlet, if there is not already at least one initialized instance. This can be used, for example, to load servlets that are marked in the deployment descriptor to be loaded at server startup time.


        // Nothing to do if we already have an instance or an instance pool
        if (!singleThreadModel && (instance != null))
            return instance;

        PrintStream out = System.out;
        if (swallowOutput) {
            SystemLogHandler.startCapture();
        }

        Servlet servlet;
        try {
            long t1=System.currentTimeMillis();
            // If this "servlet" is really a JSP file, get the right class.
            // HOLD YOUR NOSE - this is a kludge that avoids having to do special
            // case Catalina-specific code in Jasper - it also requires that the
            // servlet path be replaced by the <jsp-file> element content in
            // order to be completely effective
            String actualClass = servletClass;
            if ((actualClass == null) && (jspFile != null)) {
                Wrapper jspWrapper = (Wrapper)
                    ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
                if (jspWrapper != null) {
                    actualClass = jspWrapper.getServletClass();
                    // Merge init parameters
                    String paramNames[] = jspWrapper.findInitParameters();
                    for (int i = 0; i < paramNames.length; i++) {
                        if (parameters.get(paramNames[i]) == null) {
                            parameters.put
                                (paramNames[i], 
                                 jspWrapper.findInitParameter(paramNames[i]));
                        }
                    }
                }
            }

            // Complain if no servlet class has been specified
            if (actualClass == null) {
                unavailable(null);
                throw new ServletException
                    (sm.getString("standardWrapper.notClass", getName()));
            }

            // Acquire an instance of the class loader to be used
            Loader loader = getLoader();
            if (loader == null) {
                unavailable(null);
                throw new ServletException
                    (sm.getString("standardWrapper.missingLoader", getName()));
            }

            ClassLoader classLoader = loader.getClassLoader();

            // Special case class loader for a container provided servlet
            //  
            if (isContainerProvidedServlet(actualClass) && 
                    ! ((Context)getParent()).getPrivileged() ) {
                // If it is a priviledged context - using its own
                // class loader will work, since it's a child of the container
                // loader
                classLoader = this.getClass().getClassLoader();
            }

            // Load the specified servlet class from the appropriate class loader
            Class classClass = null;
            try {
                if (SecurityUtil.isPackageProtectionEnabled()){
                    final ClassLoader fclassLoader = classLoader;
                    final String factualClass = actualClass;
                    try{
                        classClass = (Class)AccessController.doPrivileged(
                                new PrivilegedExceptionAction(){
                                    public Object run() throws Exception{
                                        if (fclassLoader != null) {
                                            return fclassLoader.loadClass(factualClass);
                                        } else {
                                            return Class.forName(factualClass);
                                        }
                                    }
                        });
                    } catch(PrivilegedActionException pax){
                        Exception ex = pax.getException();
                        if (ex instanceof ClassNotFoundException){
                            throw (ClassNotFoundException)ex;
                        } else {
                            getServletContext().log( "Error loading "
                                + fclassLoader + " " + factualClass, ex );
                        }
                    }
                } else {
                    if (classLoader != null) {
                        classClass = classLoader.loadClass(actualClass);
                    } else {
                        classClass = Class.forName(actualClass);
                    }
                }
            } catch (ClassNotFoundException e) {
                unavailable(null);
                getServletContext().log( "Error loading " + classLoader + " " + actualClass, e );
                throw new ServletException
                    (sm.getString("standardWrapper.missingClass", actualClass),
                     e);
            }

            if (classClass == null) {
                unavailable(null);
                throw new ServletException
                    (sm.getString("standardWrapper.missingClass", actualClass));
            }

            // Instantiate and initialize an instance of the servlet class itself
            try {
                servlet = (Servlet) classClass.newInstance();
                // Annotation processing
                if (!((Context) getParent()).getIgnoreAnnotations()) {
                    if (getParent() instanceof StandardContext) {
                       ((StandardContext)getParent()).getAnnotationProcessor().processAnnotations(servlet);
                       ((StandardContext)getParent()).getAnnotationProcessor().postConstruct(servlet);
                    }
                }
            } catch (ClassCastException e) {
                unavailable(null);
                // Restore the context ClassLoader
                throw new ServletException
                    (sm.getString("standardWrapper.notServlet", actualClass), e);
            } catch (Throwable e) {
                unavailable(null);
              
                // Added extra log statement for Bugzilla 36630:
                // http://issues.apache.org/bugzilla/show_bug.cgi?id=36630
                if(log.isDebugEnabled()) {
                    log.debug(sm.getString("standardWrapper.instantiate", actualClass), e);
                }

                // Restore the context ClassLoader
                throw new ServletException
                    (sm.getString("standardWrapper.instantiate", actualClass), e);
            }

            // Check if loading the servlet in this web application should be
            // allowed
            if (!isServletAllowed(servlet)) {
                throw new SecurityException
                    (sm.getString("standardWrapper.privilegedServlet",
                                  actualClass));
            }

            // Special handling for ContainerServlet instances
            if ((servlet instanceof ContainerServlet) &&
                  (isContainerProvidedServlet(actualClass) ||
                    ((Context)getParent()).getPrivileged() )) {
                ((ContainerServlet) servlet).setWrapper(this);
            }

            classLoadTime=(int) (System.currentTimeMillis() -t1);
            // Call the initialization method of this servlet
            try {
                instanceSupport.fireInstanceEvent(InstanceEvent.BEFORE_INIT_EVENT,
                                                  servlet);

                if( Globals.IS_SECURITY_ENABLED) {

                    Object[] args = new Object[]{((ServletConfig)facade)};
                    SecurityUtil.doAsPrivilege("init",
                                               servlet,
                                               classType,
                                               args);
                    args = null;
                } else {
                    servlet.init(facade);
                }

                // Invoke jspInit on JSP pages
                if ((loadOnStartup >= 0) && (jspFile != null)) {
                    // Invoking jspInit
                    DummyRequest req = new DummyRequest();
                    req.setServletPath(jspFile);
                    req.setQueryString("jsp_precompile=true");
                    DummyResponse res = new DummyResponse();

                    if( Globals.IS_SECURITY_ENABLED) {
                        Object[] args = new Object[]{req, res};
                        SecurityUtil.doAsPrivilege("service",
                                                   servlet,
                                                   classTypeUsedInService,
                                                   args);
                        args = null;
                    } else {
                        servlet.service(req, res);
                    }
                }
                instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                                  servlet);
            } catch (UnavailableException f) {
                instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                                  servlet, f);
                unavailable(f);
                throw f;
            } catch (ServletException f) {
                instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                                  servlet, f);
                // If the servlet wanted to be unavailable it would have
                // said so, so do not call unavailable(null).
                throw f;
            } catch (Throwable f) {
                getServletContext().log("StandardWrapper.Throwable", f );
                instanceSupport.fireInstanceEvent(InstanceEvent.AFTER_INIT_EVENT,
                                                  servlet, f);
                // If the servlet wanted to be unavailable it would have
                // said so, so do not call unavailable(null).
                throw new ServletException
                    (sm.getString("standardWrapper.initException", getName()), f);
            }

            // Register our newly initialized instance
            singleThreadModel = servlet instanceof SingleThreadModel;
            if (singleThreadModel) {
                if (instancePool == null)
                    instancePool = new Stack();
            }
            fireContainerEvent("load", this);

            loadTime=System.currentTimeMillis() -t1;
        } finally {
            if (swallowOutput) {
                String log = SystemLogHandler.stopCapture();
                if (log != null && log.length() > 0) {
                    if (getServletContext() != null) {
                        getServletContext().log(log);
                    } else {
                        out.println(log);
                    }
                }
            }
        }
        return servlet;

    
protected voidregisterJMX(StandardContext ctx)


        String parentName = ctx.getName();
        parentName = ("".equals(parentName)) ? "/" : parentName;

        String hostName = ctx.getParent().getName();
        hostName = (hostName==null) ? "DEFAULT" : hostName;

        String domain = ctx.getDomain();

        String webMod= "//" + hostName + parentName;
        String onameStr = domain + ":j2eeType=Servlet,name=" + getName() +
                          ",WebModule=" + webMod + ",J2EEApplication=" +
                          ctx.getJ2EEApplication() + ",J2EEServer=" +
                          ctx.getJ2EEServer();
        try {
            oname=new ObjectName(onameStr);
            controller=oname;
            Registry.getRegistry(null, null)
                .registerComponent(this, oname, null );
            
            // Send j2ee.object.created notification 
            if (this.getObjectName() != null) {
                Notification notification = new Notification(
                                                "j2ee.object.created", 
                                                this.getObjectName(), 
                                                sequenceNumber++);
                broadcaster.sendNotification(notification);
            }
        } catch( Exception ex ) {
            log.info("Error registering servlet with jmx " + this);
        }

        if (isJspServlet) {
            // Register JSP monitoring mbean
            onameStr = domain + ":type=JspMonitor,name=" + getName()
                       + ",WebModule=" + webMod
                       + ",J2EEApplication=" + ctx.getJ2EEApplication()
                       + ",J2EEServer=" + ctx.getJ2EEServer();
            try {
                jspMonitorON = new ObjectName(onameStr);
                Registry.getRegistry(null, null)
                    .registerComponent(instance, jspMonitorON, null);
            } catch( Exception ex ) {
                log.info("Error registering JSP monitoring with jmx " +
                         instance);
            }
        }
    
public voidremoveInitParameter(java.lang.String name)
Remove the specified initialization parameter from this servlet.

param
name Name of the initialization parameter to remove


        synchronized (parameters) {
            parameters.remove(name);
        }
        fireContainerEvent("removeInitParameter", name);

    
public voidremoveInstanceListener(org.apache.catalina.InstanceListener listener)
Remove a listener no longer interested in InstanceEvents.

param
listener The listener to remove


        instanceSupport.removeInstanceListener(listener);

    
public voidremoveMapping(java.lang.String mapping)
Remove a mapping associated with the wrapper.

param
mapping The pattern to remove


        synchronized (mappings) {
            mappings.remove(mapping);
        }
        fireContainerEvent("removeMapping", mapping);

    
public voidremoveNotificationListener(javax.management.NotificationListener listener, javax.management.NotificationFilter filter, java.lang.Object object)

    	broadcaster.removeNotificationListener(listener,filter,object);
    	
    
public voidremoveNotificationListener(javax.management.NotificationListener listener)
Remove a JMX-NotificationListener

see
javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)

    	broadcaster.removeNotificationListener(listener);
    
public voidremoveSecurityReference(java.lang.String name)
Remove any security role reference for the specified role name.

param
name Security role used within this servlet to be removed


        synchronized (references) {
            references.remove(name);
        }
        fireContainerEvent("removeSecurityReference", name);

    
public voidsetAvailable(long available)
Set the available date/time for this servlet, in milliseconds since the epoch. If this date/time is Long.MAX_VALUE, it is considered to mean that unavailability is permanent and any request for this servlet will return an SC_NOT_FOUND error. If this date/time is in the future, any request for this servlet will return an SC_SERVICE_UNAVAILABLE error.

param
available The new available date/time


        long oldAvailable = this.available;
        if (available > System.currentTimeMillis())
            this.available = available;
        else
            this.available = 0L;
        support.firePropertyChange("available", new Long(oldAvailable),
                                   new Long(this.available));

    
public voidsetErrorCount(int errorCount)

           swValve.setErrorCount(errorCount);
    
public voidsetJspFile(java.lang.String jspFile)
Set the context-relative URI of the JSP file for this servlet.

param
jspFile JSP file URI


        String oldJspFile = this.jspFile;
        this.jspFile = jspFile;
        support.firePropertyChange("jspFile", oldJspFile, this.jspFile);

        // Each jsp-file needs to be represented by its own JspServlet and
        // corresponding JspMonitoring mbean, because it may be initialized
        // with its own init params
        isJspServlet = true;

    
public voidsetLoadOnStartup(int value)
Set the load-on-startup order value (negative value means load on first call).

param
value New load-on-startup value


        int oldLoadOnStartup = this.loadOnStartup;
        this.loadOnStartup = value;
        support.firePropertyChange("loadOnStartup",
                                   new Integer(oldLoadOnStartup),
                                   new Integer(this.loadOnStartup));

    
public voidsetLoadOnStartupString(java.lang.String value)
Set the load-on-startup order value from a (possibly null) string. Per the specification, any missing or non-numeric value is converted to a zero, so that this servlet will still be loaded at startup time, but in an arbitrary order.

param
value New load-on-startup value


        try {
            setLoadOnStartup(Integer.parseInt(value));
        } catch (NumberFormatException e) {
            setLoadOnStartup(0);
        }
    
public voidsetLoadTime(long loadTime)

        this.loadTime = loadTime;
    
public voidsetMaxInstances(int maxInstances)
Set the maximum number of instances that will be allocated when a single thread model servlet is used.

param
maxInstances New value of maxInstances


        int oldMaxInstances = this.maxInstances;
        this.maxInstances = maxInstances;
        support.firePropertyChange("maxInstances", oldMaxInstances,
                                   this.maxInstances);

    
public voidsetMaxTime(long maxTime)

        swValve.setMaxTime(maxTime);
    
public voidsetMinTime(long minTime)

        swValve.setMinTime(minTime);
    
public voidsetParent(org.apache.catalina.Container container)
Set the parent Container of this Wrapper, but only if it is a Context.

param
container Proposed parent Container


        if ((container != null) &&
            !(container instanceof Context))
            throw new IllegalArgumentException
                (sm.getString("standardWrapper.notContext"));
        if (container instanceof StandardContext) {
            swallowOutput = ((StandardContext)container).getSwallowOutput();
            unloadDelay = ((StandardContext)container).getUnloadDelay();
        }
        super.setParent(container);

    
public voidsetProcessingTime(long processingTime)

        swValve.setProcessingTime(processingTime);
    
public voidsetRequestCount(int requestCount)

        swValve.setRequestCount(requestCount);
    
public voidsetRunAs(java.lang.String runAs)
Set the run-as identity for this servlet.

param
runAs New run-as identity value


        String oldRunAs = this.runAs;
        this.runAs = runAs;
        support.firePropertyChange("runAs", oldRunAs, this.runAs);

    
public voidsetServletClass(java.lang.String servletClass)
Set the fully qualified servlet class name for this servlet.

param
servletClass Servlet class name


        String oldServletClass = this.servletClass;
        this.servletClass = servletClass;
        support.firePropertyChange("servletClass", oldServletClass,
                                   this.servletClass);
        if (Constants.JSP_SERVLET_CLASS.equals(servletClass)) {
            isJspServlet = true;
        }
    
public voidsetServletName(java.lang.String name)
Set the name of this servlet. This is an alias for the normal Container.setName() method, and complements the getServletName() method required by the ServletConfig interface.

param
name The new name of this servlet


        setName(name);

    
public voidstart()
Start this component, pre-loading the servlet if the load-on-startup value is set appropriately.

exception
LifecycleException if a fatal error occurs during startup

    
        // Send j2ee.state.starting notification 
        if (this.getObjectName() != null) {
            Notification notification = new Notification("j2ee.state.starting", 
                                                        this.getObjectName(), 
                                                        sequenceNumber++);
            broadcaster.sendNotification(notification);
        }
        
        // Start up this component
        super.start();

        if( oname != null )
            registerJMX((StandardContext)getParent());
        
        // Load and initialize an instance of this servlet if requested
        // MOVED TO StandardContext START() METHOD

        setAvailable(0L);
        
        // Send j2ee.state.running notification 
        if (this.getObjectName() != null) {
            Notification notification = 
                new Notification("j2ee.state.running", this.getObjectName(), 
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }

    
public voidstop()
Stop this component, gracefully shutting down the servlet if it has been initialized.

exception
LifecycleException if a fatal error occurs during shutdown


        setAvailable(Long.MAX_VALUE);
        
        // Send j2ee.state.stopping notification 
        if (this.getObjectName() != null) {
            Notification notification = 
                new Notification("j2ee.state.stopping", this.getObjectName(), 
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }
        
        // Shut down our servlet instance (if it has been initialized)
        try {
            unload();
        } catch (ServletException e) {
            getServletContext().log(sm.getString
                      ("standardWrapper.unloadException", getName()), e);
        }

        // Shut down this component
        super.stop();

        // Send j2ee.state.stoppped notification 
        if (this.getObjectName() != null) {
            Notification notification = 
                new Notification("j2ee.state.stopped", this.getObjectName(), 
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }
        
        if( oname != null ) {
            Registry.getRegistry(null, null).unregisterComponent(oname);
            
            // Send j2ee.object.deleted notification 
            Notification notification = 
                new Notification("j2ee.object.deleted", this.getObjectName(), 
                                sequenceNumber++);
            broadcaster.sendNotification(notification);
        }

        if (isJspServlet && jspMonitorON != null ) {
            Registry.getRegistry(null, null).unregisterComponent(jspMonitorON);
        }

    
public java.lang.StringtoString()
Return a String representation of this component.


        StringBuffer sb = new StringBuffer();
        if (getParent() != null) {
            sb.append(getParent().toString());
            sb.append(".");
        }
        sb.append("StandardWrapper[");
        sb.append(getName());
        sb.append("]");
        return (sb.toString());

    
public voidunavailable(javax.servlet.UnavailableException unavailable)
Process an UnavailableException, marking this servlet as unavailable for the specified amount of time.

param
unavailable The exception that occurred, or null to mark this servlet as permanently unavailable

        getServletContext().log(sm.getString("standardWrapper.unavailable", getName()));
        if (unavailable == null)
            setAvailable(Long.MAX_VALUE);
        else if (unavailable.isPermanent())
            setAvailable(Long.MAX_VALUE);
        else {
            int unavailableSeconds = unavailable.getUnavailableSeconds();
            if (unavailableSeconds <= 0)
                unavailableSeconds = 60;        // Arbitrary default
            setAvailable(System.currentTimeMillis() +
                         (unavailableSeconds * 1000L));
        }

    
public synchronized voidunload()
Unload all initialized instances of this servlet, after calling the destroy() method for each instance. This can be used, for example, prior to shutting down the entire servlet engine, or prior to reloading all of the classes from the Loader associated with our Loader's repository.

exception
ServletException if an exception is thrown by the destroy() method


        // Nothing to do if we have never loaded the instance
        if (!singleThreadModel && (instance == null))
            return;
        unloading = true;

        // Loaf a while if the current instance is allocated
        // (possibly more than once if non-STM)
        if (countAllocated > 0) {
            int nRetries = 0;
            long delay = unloadDelay / 20;
            while ((nRetries < 21) && (countAllocated > 0)) {
                if ((nRetries % 10) == 0) {
                    log.info(sm.getString("standardWrapper.waiting",
                                          new Integer(countAllocated)));
                }
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                    ;
                }
                nRetries++;
            }
        }

        PrintStream out = System.out;
        if (swallowOutput) {
            SystemLogHandler.startCapture();
        }

        // Call the servlet destroy() method
        try {
            instanceSupport.fireInstanceEvent
              (InstanceEvent.BEFORE_DESTROY_EVENT, instance);

            if( Globals.IS_SECURITY_ENABLED) {
                SecurityUtil.doAsPrivilege("destroy",
                                           instance);
                SecurityUtil.remove(instance);                           
            } else {
                instance.destroy();
            }
            
            instanceSupport.fireInstanceEvent
              (InstanceEvent.AFTER_DESTROY_EVENT, instance);

            // Annotation processing
            if (!((Context) getParent()).getIgnoreAnnotations()) {
               ((StandardContext)getParent()).getAnnotationProcessor().preDestroy(instance);
            }

        } catch (Throwable t) {
            instanceSupport.fireInstanceEvent
              (InstanceEvent.AFTER_DESTROY_EVENT, instance, t);
            instance = null;
            instancePool = null;
            nInstances = 0;
            fireContainerEvent("unload", this);
            unloading = false;
            throw new ServletException
                (sm.getString("standardWrapper.destroyException", getName()),
                 t);
        } finally {
            // Write captured output
            if (swallowOutput) {
                String log = SystemLogHandler.stopCapture();
                if (log != null && log.length() > 0) {
                    if (getServletContext() != null) {
                        getServletContext().log(log);
                    } else {
                        out.println(log);
                    }
                }
            }
        }

        // Deregister the destroyed instance
        instance = null;

        if (singleThreadModel && (instancePool != null)) {
            try {
                while (!instancePool.isEmpty()) {
                    Servlet s = (Servlet) instancePool.pop();
                    if (Globals.IS_SECURITY_ENABLED) {
                        SecurityUtil.doAsPrivilege("destroy", s);
                        SecurityUtil.remove(instance);                           
                    } else {
                        s.destroy();
                    }
                    // Annotation processing
                    if (!((Context) getParent()).getIgnoreAnnotations()) {
                       ((StandardContext)getParent()).getAnnotationProcessor().preDestroy(s);
                    }
                }
            } catch (Throwable t) {
                instancePool = null;
                nInstances = 0;
                unloading = false;
                fireContainerEvent("unload", this);
                throw new ServletException
                    (sm.getString("standardWrapper.destroyException",
                                  getName()), t);
            }
            instancePool = null;
            nInstances = 0;
        }

        singleThreadModel = false;

        unloading = false;
        fireContainerEvent("unload", this);