You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2006/05/20 04:12:52 UTC

svn commit: r407939 [4/8] - in /tomcat/sandbox/java/org/apache/coyote/servlet: ./ util/

Added: tomcat/sandbox/java/org/apache/coyote/servlet/ServletConfigImpl.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/java/org/apache/coyote/servlet/ServletConfigImpl.java?rev=407939&view=auto
==============================================================================
--- tomcat/sandbox/java/org/apache/coyote/servlet/ServletConfigImpl.java (added)
+++ tomcat/sandbox/java/org/apache/coyote/servlet/ServletConfigImpl.java Fri May 19 19:12:51 2006
@@ -0,0 +1,1799 @@
+/*
+ * Copyright 1999-2002,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.coyote.servlet;
+
+import java.io.PrintStream;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Stack;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.SingleThreadModel;
+import javax.servlet.UnavailableException;
+
+import org.apache.commons.logging.Log;
+import org.apache.coyote.servlet.util.Enumerator;
+import org.apache.tomcat.util.IntrospectionUtils;
+import org.apache.tomcat.util.log.SystemLogHandler;
+import org.apache.tomcat.util.res.StringManager;
+
+/**
+ * Based on Wrapper.
+ * 
+ * Standard implementation of the <b>Wrapper</b> 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: 345286 $ $Date: 2005-11-17 09:00:24 -0800 (Thu, 17 Nov 2005) $
+ */
+public class ServletConfigImpl implements ServletConfig {
+    
+    private static org.apache.commons.logging.Log log=
+        org.apache.commons.logging.LogFactory.getLog( ServletConfigImpl.class );
+
+    private static final String[] DEFAULT_SERVLET_METHODS = new String[] {
+                                                    "GET", "HEAD", "POST" };
+
+    static StringManager sm = StringManager.getManager("org.apache.coyote.servlet");
+  
+    public static final String JSP_SERVLET_CLASS =
+        "org.apache.jasper.servlet.JspServlet";
+    public static final String JSP_SERVLET_NAME = "jsp";
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Create a new StandardWrapper component with the default basic Valve.
+     */
+    public ServletConfigImpl() {
+
+        super();
+//        broadcaster = new NotificationBroadcasterSupport();
+
+    }
+
+
+    // ----------------------------------------------------- Instance Variables
+    String name;
+
+
+    /**
+     * 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.
+     */
+    private long available = 0L;
+    
+    /**
+     * The broadcaster that sends j2ee notifications. 
+     */
+    //private NotificationBroadcasterSupport broadcaster = null;
+    
+    /**
+     * 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).
+     */
+    private int countAllocated = 0;
+
+
+
+    /**
+     * The descriptive information string for this implementation.
+     */
+    private static final String info =
+        "org.apache.catalina.core.StandardWrapper/1.0";
+
+
+    /**
+     * The (single) initialized instance of this servlet.
+     */
+    private Servlet instance = null;
+
+
+
+    /**
+     * The context-relative URI of the JSP file for this servlet.
+     */
+    private String jspFile = null;
+
+
+    /**
+     * The load-on-startup order value (negative value means load on
+     * first call) for this servlet.
+     */
+    private int loadOnStartup = -1;
+
+
+    /**
+     * Mappings associated with the wrapper.
+     */
+    private ArrayList mappings = new ArrayList();
+
+
+    /**
+     * The initialization parameters for this servlet, keyed by
+     * parameter name.
+     */
+    private HashMap parameters = new HashMap();
+
+
+    /**
+     * 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.
+     */
+    private HashMap references = new HashMap();
+
+
+    /**
+     * The run-as identity for this servlet.
+     */
+    private String runAs = null;
+
+    /**
+     * The notification sequence number.
+     */
+    private long sequenceNumber = 0;
+
+    /**
+     * The fully qualified servlet class name for this servlet.
+     */
+    private String servletClass = null;
+
+
+    /**
+     * Does this servlet implement the SingleThreadModel interface?
+     */
+    private boolean singleThreadModel = false;
+
+
+    /**
+     * Are we unloading our servlet instance at the moment?
+     */
+    private boolean unloading = false;
+
+
+    /**
+     * Maximum number of STM instances.
+     */
+    private int maxInstances = 20;
+
+
+    /**
+     * Number of instances currently loaded for a STM servlet.
+     */
+    private int nInstances = 0;
+
+
+    /**
+     * Stack containing the STM instances.
+     */
+    private Stack instancePool = null;
+
+    
+    /**
+     * Wait time for servlet unload in ms.
+     */
+    private long unloadDelay = 2000;
+    
+
+    /**
+     * True if this StandardWrapper is for the JspServlet
+     */
+    private boolean isJspServlet;
+
+
+    /**
+     * The ObjectName of the JSP monitoring mbean
+     */
+    //private ObjectName jspMonitorON;
+
+
+    /**
+     * Should we swallow System.out
+     */
+    private boolean swallowOutput = false;
+
+    private long loadTime=0;
+    private int classLoadTime=0;
+
+    private ServletContextImpl parent;
+    
+    /**
+     * Static class array used when the SecurityManager is turned on and 
+     * <code>Servlet.init</code> is invoked.
+     */
+    private static Class[] classType = new Class[]{ServletConfig.class};
+    
+    
+    /**
+     * Static class array used when the SecurityManager is turned on and 
+     * <code>Servlet.service</code>  is invoked.
+     */                                                 
+    private static Class[] classTypeUsedInService = new Class[]{
+                                                         ServletRequest.class,
+                                                         ServletResponse.class};
+    // ------------------------------------------------------------- Properties
+
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * 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.
+     */
+    public long getAvailable() {
+
+        return (this.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
+     */
+    public void setAvailable(long available) {
+
+        long oldAvailable = this.available;
+        if (available > System.currentTimeMillis())
+            this.available = available;
+        else
+            this.available = 0L;
+
+    }
+
+
+    /**
+     * 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 <code>SingleThreadModel</code>.
+     */
+    public int getCountAllocated() {
+
+        return (this.countAllocated);
+
+    }
+
+
+//    public String getEngineName() {
+//        return ((StandardContext)getParent()).getEngineName();
+//    }
+
+
+    /**
+     * Return descriptive information about this Container implementation and
+     * the corresponding version number, in the format
+     * <code>&lt;description&gt;/&lt;version&gt;</code>.
+     */
+    public String getInfo() {
+
+        return (info);
+
+    }
+
+
+    /**
+     * Return the context-relative URI of the JSP file for this servlet.
+     */
+    public String getJspFile() {
+
+        return (this.jspFile);
+
+    }
+
+
+    /**
+     * Set the context-relative URI of the JSP file for this servlet.
+     *
+     * @param jspFile JSP file URI
+     */
+    public void setJspFile(String jspFile) {
+
+        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;
+
+    }
+
+
+    /**
+     * Return the load-on-startup order value (negative value means
+     * load on first call).
+     */
+    public int getLoadOnStartup() {
+
+        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);
+        }
+    }
+
+
+    /**
+     * Set the load-on-startup order value (negative value means
+     * load on first call).
+     *
+     * @param value New load-on-startup value
+     */
+    public void setLoadOnStartup(int value) {
+
+        int oldLoadOnStartup = this.loadOnStartup;
+        this.loadOnStartup = value;
+//        support.firePropertyChange("loadOnStartup",
+//                                   new Integer(oldLoadOnStartup),
+//                                   new Integer(this.loadOnStartup));
+
+    }
+
+
+
+    /**
+     * 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
+     */
+    public void setLoadOnStartupString(String value) {
+
+        try {
+            setLoadOnStartup(Integer.parseInt(value));
+        } catch (NumberFormatException e) {
+            setLoadOnStartup(0);
+        }
+    }
+
+    public String getLoadOnStartupString() {
+        return Integer.toString( getLoadOnStartup());
+    }
+
+
+    /**
+     * Return maximum number of instances that will be allocated when a single
+     * thread model servlet is used.
+     */
+    public int getMaxInstances() {
+
+        return (this.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
+     */
+    public void setMaxInstances(int maxInstances) {
+
+        int oldMaxInstances = this.maxInstances;
+        this.maxInstances = maxInstances;
+//        support.firePropertyChange("maxInstances", oldMaxInstances,
+//                                   this.maxInstances);
+
+    }
+
+
+    /**
+     * Set the parent Container of this Wrapper, but only if it is a Context.
+     *
+     * @param container Proposed parent Container
+     */
+    public void setParent(ServletContextImpl container) {
+
+        swallowOutput = container.getSwallowOutput();
+        unloadDelay = container.getUnloadDelay();
+        this.parent = container;
+
+    }
+
+    public ServletContextImpl getParent() {
+        return parent;
+    }
+
+    /**
+     * Return the run-as identity for this servlet.
+     */
+    public String getRunAs() {
+
+        return (this.runAs);
+
+    }
+
+
+    /**
+     * Set the run-as identity for this servlet.
+     *
+     * @param runAs New run-as identity value
+     */
+    public void setRunAs(String runAs) {
+
+        String oldRunAs = this.runAs;
+        this.runAs = runAs;
+//        support.firePropertyChange("runAs", oldRunAs, this.runAs);
+
+    }
+
+
+    /**
+     * Return the fully qualified servlet class name for this servlet.
+     */
+    public String getServletClass() {
+
+        return (this.servletClass);
+
+    }
+
+
+    /**
+     * Set the fully qualified servlet class name for this servlet.
+     *
+     * @param servletClass Servlet class name
+     */
+    public void setServletClass(String servletClass) {
+
+        String oldServletClass = this.servletClass;
+        this.servletClass = servletClass;
+//        support.firePropertyChange("servletClass", oldServletClass,
+//                                   this.servletClass);
+        // TODO(costin): how does this work for precompiled JspC ??
+        if (JSP_SERVLET_CLASS.equals(servletClass)) {
+            isJspServlet = true;
+        }
+    }
+
+
+
+    /**
+     * Set the name of this servlet.  This is an alias for the normal
+     * <code>Container.setName()</code> method, and complements the
+     * <code>getServletName()</code> method required by the
+     * <code>ServletConfig</code> interface.
+     *
+     * @param name The new name of this servlet
+     */
+    public void setServletName(String name) {
+
+        this.name = name;
+
+    }
+
+
+    /**
+     * Return <code>true</code> if the servlet class represented by this
+     * component implements the <code>SingleThreadModel</code> interface.
+     */
+    public boolean isSingleThreadModel() {
+
+        try {
+            loadServlet();
+        } catch (Throwable t) {
+            ;
+        }
+        return (singleThreadModel);
+
+    }
+
+
+    /**
+     * Is this servlet currently unavailable?
+     */
+    public boolean isUnavailable() {
+
+        if (available == 0L)
+            return (false);
+        else if (available <= System.currentTimeMillis()) {
+            available = 0L;
+            return (false);
+        } else
+            return (true);
+
+    }
+
+
+    /**
+     * 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
+     */
+    public String[] getServletMethods() throws ServletException {
+
+        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 Methods
+
+
+    /**
+     * Extract the root cause from a servlet exception.
+     * 
+     * @param e The servlet exception
+     */
+    public static Throwable getRootCause(ServletException e) {
+        Throwable rootCause = e;
+        Throwable rootCauseCheck = null;
+        // Extra aggressive rootCause finding
+        do {
+            try {
+                rootCauseCheck = (Throwable)IntrospectionUtils.getProperty
+                                            (rootCause, "rootCause");
+                if (rootCauseCheck!=null)
+                    rootCause = rootCauseCheck;
+
+            } catch (ClassCastException ex) {
+                rootCauseCheck = null;
+            }
+        } while (rootCauseCheck != null);
+        return rootCause;
+    }
+
+
+    /**
+     * 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
+     */
+    public void addInitParameter(String name, String value) {
+
+        synchronized (parameters) {
+            parameters.put(name, value);
+        }
+//        fireContainerEvent("addInitParameter", name);
+
+    }
+
+
+    /**
+     * Add a mapping associated with the Wrapper.
+     *
+     * @param mapping The new wrapper mapping
+     */
+    public void addMapping(String mapping) {
+
+        synchronized (mappings) {
+            mappings.add(mapping);
+        }
+//        fireContainerEvent("addMapping", mapping);
+
+    }
+
+
+    /**
+     * 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
+     */
+    public void addSecurityReference(String name, String link) {
+
+        synchronized (references) {
+            references.put(name, link);
+        }
+//        fireContainerEvent("addSecurityReference", name);
+
+    }
+
+    /**
+     * Allocate an initialized instance of this Servlet that is ready to have
+     * its <code>service()</code> method called.  If the servlet class does
+     * not implement <code>SingleThreadModel</code>, the (only) initialized
+     * instance may be returned immediately.  If the servlet class implements
+     * <code>SingleThreadModel</code>, the Wrapper implementation must ensure
+     * that this instance is not allocated again until it is deallocated by a
+     * call to <code>deallocate()</code>.
+     *
+     * @exception ServletException if the servlet init() method threw
+     *  an exception
+     * @exception ServletException if a loading error occurs
+     */
+    public Servlet allocate() throws ServletException {
+
+        // 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();
+
+        }
+
+    }
+
+
+    /**
+     * 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
+     */
+    public void deallocate(Servlet servlet) throws ServletException {
+
+        // If not SingleThreadModel, no action is required
+        if (!singleThreadModel) {
+            countAllocated--;
+            return;
+        }
+
+        // Unlock and free this instance
+        synchronized (instancePool) {
+            countAllocated--;
+            instancePool.push(servlet);
+            instancePool.notify();
+        }
+
+    }
+
+
+    /**
+     * Return the value for the specified initialization parameter name,
+     * if any; otherwise return <code>null</code>.
+     *
+     * @param name Name of the requested initialization parameter
+     */
+    public String findInitParameter(String name) {
+
+        synchronized (parameters) {
+            return ((String) parameters.get(name));
+        }
+
+    }
+
+
+    /**
+     * Return the names of all defined initialization parameters for this
+     * servlet.
+     */
+    public String[] findInitParameters() {
+
+        synchronized (parameters) {
+            String results[] = new String[parameters.size()];
+            return ((String[]) parameters.keySet().toArray(results));
+        }
+
+    }
+
+
+    /**
+     * Return the mappings associated with this wrapper.
+     */
+    public String[] findMappings() {
+
+        synchronized (mappings) {
+            return (String[]) mappings.toArray(new String[mappings.size()]);
+        }
+
+    }
+
+
+    /**
+     * Return the security role link for the specified security role
+     * reference name, if any; otherwise return <code>null</code>.
+     *
+     * @param name Security role reference used within this servlet
+     */
+    public String findSecurityReference(String name) {
+
+        synchronized (references) {
+            return ((String) references.get(name));
+        }
+
+    }
+
+
+    /**
+     * Return the set of security role reference names associated with
+     * this servlet, if any; otherwise return a zero-length array.
+     */
+    public String[] findSecurityReferences() {
+
+        synchronized (references) {
+            String results[] = new String[references.size()];
+            return ((String[]) references.keySet().toArray(results));
+        }
+
+    }
+
+
+//    /**
+//     * FIXME: Fooling introspection ...
+//     */
+//    public Wrapper findMappingObject() {
+//        return (Wrapper) getMappingObject();
+//    }
+
+
+    /**
+     * 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.
+     * <p>
+     * <b>IMPLEMENTATION NOTE</b>:  Servlets whose classnames begin with
+     * <code>org.apache.catalina.</code> (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
+     */
+    public synchronized void load() throws ServletException {
+        if(instance == null) { 
+            instance = loadServlet();
+        }
+    }
+
+
+    /**
+     * 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.
+     */
+    public synchronized Servlet loadServlet() throws ServletException {
+        
+        // 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)) {
+                ServletConfigImpl jspWrapper = (ServletConfigImpl)
+                    ((ServletContextImpl) getParent()).findChild(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();
+
+            // TODO(costin): use real loader if multiple webapps
+            ClassLoader classLoader = this.getClass().getClassLoader();
+            
+            // Special case class loader for a container provided servlet
+            //  
+            if (isContainerProvidedServlet(actualClass) && 
+                    ! ((ServletContextImpl)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();
+            } 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( System.getSecurityManager() != null) {
+//
+//                    Object[] args = new Object[]{((ServletConfig)facade)};
+//                    SecurityUtil.doAsPrivilege("init",
+//                                               servlet,
+//                                               classType,
+//                                               args);
+//                    args = null;
+//                } else {
+                    servlet.init(this);
+//                }
+
+                // Invoke jspInit on JSP pages
+                if ((loadOnStartup >= 0) && (jspFile != null)) {
+                    // Invoking jspInit
+                    ServletRequestImpl req = new ServletRequestImpl();
+                    req.setServletPath(jspFile);
+                    req.setQueryString("jsp_precompile=true");
+                    ServletResponseImpl res = new ServletResponseImpl();
+
+//                    if( System.getSecurityManager() != null) {
+//                        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;
+
+    }
+
+
+    /**
+     * Remove the specified initialization parameter from this servlet.
+     *
+     * @param name Name of the initialization parameter to remove
+     */
+    public void removeInitParameter(String name) {
+
+        synchronized (parameters) {
+            parameters.remove(name);
+        }
+//        fireContainerEvent("removeInitParameter", name);
+
+    }
+
+
+//    /**
+//     * Remove a listener no longer interested in InstanceEvents.
+//     *
+//     * @param listener The listener to remove
+//     */
+//    public void removeInstanceListener(InstanceListener listener) {
+//
+//        instanceSupport.removeInstanceListener(listener);
+//
+//    }
+
+
+    /**
+     * Remove a mapping associated with the wrapper.
+     *
+     * @param mapping The pattern to remove
+     */
+    public void removeMapping(String mapping) {
+
+        synchronized (mappings) {
+            mappings.remove(mapping);
+        }
+//        fireContainerEvent("removeMapping", mapping);
+
+    }
+
+
+    /**
+     * Remove any security role reference for the specified role name.
+     *
+     * @param name Security role used within this servlet to be removed
+     */
+    public void removeSecurityReference(String name) {
+
+        synchronized (references) {
+            references.remove(name);
+        }
+//        fireContainerEvent("removeSecurityReference", name);
+
+    }
+
+
+    /**
+     * Return a String representation of this component.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer();
+        if (getParent() != null) {
+            sb.append(getParent().toString());
+            sb.append(".");
+        }
+        sb.append("StandardWrapper[");
+        sb.append(getName());
+        sb.append("]");
+        return (sb.toString());
+
+    }
+
+
+    /**
+     * Process an UnavailableException, marking this servlet as unavailable
+     * for the specified amount of time.
+     *
+     * @param unavailable The exception that occurred, or <code>null</code>
+     *  to mark this servlet as permanently unavailable
+     */
+    public void unavailable(UnavailableException 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));
+        }
+
+    }
+
+
+    /**
+     * Unload all initialized instances of this servlet, after calling the
+     * <code>destroy()</code> 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
+     */
+    public synchronized void unload() throws ServletException {
+
+        // 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++;
+            }
+        }
+
+        ClassLoader oldCtxClassLoader =
+            Thread.currentThread().getContextClassLoader();
+        ClassLoader classLoader = instance.getClass().getClassLoader();
+
+        PrintStream out = System.out;
+        if (swallowOutput) {
+            SystemLogHandler.startCapture();
+        }
+
+        // Call the servlet destroy() method
+        try {
+//            instanceSupport.fireInstanceEvent
+//              (InstanceEvent.BEFORE_DESTROY_EVENT, instance);
+
+            Thread.currentThread().setContextClassLoader(classLoader);
+//            if( System.getSecurityManager() != null) {
+//                SecurityUtil.doAsPrivilege("destroy",
+//                                           instance);
+//                SecurityUtil.remove(instance);                           
+//            } else {
+                instance.destroy();
+//            }
+
+//            instanceSupport.fireInstanceEvent
+//              (InstanceEvent.AFTER_DESTROY_EVENT, 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 {
+            // restore the context ClassLoader
+            Thread.currentThread().setContextClassLoader(oldCtxClassLoader);
+            // 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 {
+                Thread.currentThread().setContextClassLoader(classLoader);
+                while (!instancePool.isEmpty()) {
+//                    if( System.getSecurityManager() != null) {
+//                        SecurityUtil.doAsPrivilege("destroy",
+//                                                   ((Servlet) instancePool.pop()));
+//                        SecurityUtil.remove(instance);                           
+//                    } else {
+                        ((Servlet) instancePool.pop()).destroy();
+//                    }
+                }
+            } catch (Throwable t) {
+                instancePool = null;
+                nInstances = 0;
+                unloading = false;
+//                fireContainerEvent("unload", this);
+                throw new ServletException
+                    (sm.getString("standardWrapper.destroyException",
+                                  getName()), t);
+            } finally {
+                // restore the context ClassLoader
+                Thread.currentThread().setContextClassLoader
+                    (oldCtxClassLoader);
+            }
+            instancePool = null;
+            nInstances = 0;
+        }
+
+        singleThreadModel = false;
+
+        unloading = false;
+//        fireContainerEvent("unload", this);
+
+    }
+
+
+    // -------------------------------------------------- ServletConfig Methods
+
+
+    /**
+     * Return the initialization parameter value for the specified name,
+     * if any; otherwise return <code>null</code>.
+     *
+     * @param name Name of the initialization parameter to retrieve
+     */
+    public String getInitParameter(String name) {
+
+        return (findInitParameter(name));
+
+    }
+
+
+    /**
+     * Return the set of initialization parameter names defined for this
+     * servlet.  If none are defined, an empty Enumeration is returned.
+     */
+    public Enumeration getInitParameterNames() {
+
+        synchronized (parameters) {
+            return (new Enumerator(parameters.keySet()));
+        }
+
+    }
+
+
+    /**
+     * Return the servlet context with which this servlet is associated.
+     */
+    public ServletContext getServletContext() {
+
+        if (parent == null)
+            return (null);
+        else if (!(parent instanceof ServletContextImpl))
+            return (null);
+        else
+            return (((ServletContextImpl) parent).getServletContext());
+
+    }
+
+
+    /**
+     * Return the name of this servlet.
+     */
+    public String getServletName() {
+
+        return (getName());
+
+    }
+
+//    public long getProcessingTime() {
+//        return swValve.getProcessingTime();
+//    }
+//
+//    public void setProcessingTime(long processingTime) {
+//        swValve.setProcessingTime(processingTime);
+//    }
+//
+//    public long getMaxTime() {
+//        return swValve.getMaxTime();
+//    }
+//
+//    public void setMaxTime(long maxTime) {
+//        swValve.setMaxTime(maxTime);
+//    }
+//
+//    public long getMinTime() {
+//        return swValve.getMinTime();
+//    }
+//
+//    public void setMinTime(long minTime) {
+//        swValve.setMinTime(minTime);
+//    }
+//
+//    public int getRequestCount() {
+//        return swValve.getRequestCount();
+//    }
+//
+//    public void setRequestCount(int requestCount) {
+//        swValve.setRequestCount(requestCount);
+//    }
+//
+//    public int getErrorCount() {
+//        return swValve.getErrorCount();
+//    }
+//
+//    public void setErrorCount(int errorCount) {
+//           swValve.setErrorCount(errorCount);
+//    }
+//
+//    /**
+//     * Increment the error count used for monitoring.
+//     */
+//    public void incrementErrorCount(){
+//        swValve.setErrorCount(swValve.getErrorCount() + 1);
+//    }
+//
+//    public long getLoadTime() {
+//        return loadTime;
+//    }
+//
+//    public void setLoadTime(long loadTime) {
+//        this.loadTime = loadTime;
+//    }
+//
+//    public int getClassLoadTime() {
+//        return classLoadTime;
+//    }
+
+    // -------------------------------------------------------- Package Methods
+
+
+    // -------------------------------------------------------- Private Methods
+
+
+    /**
+     * Add a default Mapper implementation if none have been configured
+     * explicitly.
+     *
+     * @param mapperClass Java class name of the default Mapper
+     */
+    protected void addDefaultMapper(String mapperClass) {
+
+        ;       // No need for a default Mapper on a Wrapper
+
+    }
+
+
+    /**
+     * Return <code>true</code> 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
+     */
+    private boolean isContainerProvidedServlet(String classname) {
+
+        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);
+//        }
+
+       return false;
+    }
+
+
+    /**
+     * Return <code>true</code> if loading this servlet is allowed.
+     */
+    private boolean isServletAllowed(Object servlet) {
+
+//        if (servlet instanceof ContainerServlet) {
+//            if (((Context) getParent()).getPrivileged()
+//                || (servlet.getClass().getName().equals
+//                    ("org.apache.catalina.servlets.InvokerServlet"))) {
+//                return (true);
+//            } else {
+//                return (false);
+//            }
+//        }
+
+        return (true);
+
+    }
+
+
+    private Method[] getAllDeclaredMethods(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;
+    }
+
+
+    // ------------------------------------------------------ Lifecycle Methods
+
+
+    /**
+     * 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
+     */
+    public void start() {
+    
+        // 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);
+//        }
+
+    }
+
+
+    /**
+     * Stop this component, gracefully shutting down the servlet if it has
+     * been initialized.
+     *
+     * @exception LifecycleException if a fatal error occurs during shutdown
+     */
+    public void stop() {
+
+        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);
+//        }
+
+    }
+
+//    protected void registerJMX(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);
+//            }
+//        }
+//    }
+    
+
+    /* Remove a JMX notficationListener 
+     * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
+     */
+//    public void removeNotificationListener(NotificationListener listener, 
+//    		NotificationFilter filter, Object object) throws ListenerNotFoundException {
+//    	broadcaster.removeNotificationListener(listener,filter,object);
+//    	
+//    }
+    
+//    private MBeanNotificationInfo[] notificationInfo;
+    
+//    /* Get JMX Broadcaster Info
+//     * @TODO use StringManager for international support!
+//     * @TODO This two events we not send j2ee.state.failed and j2ee.attribute.changed!
+//     * @see javax.management.NotificationBroadcaster#getNotificationInfo()
+//     */
+//    public 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;
+//    }
+    
+    
+//    /* Add a JMX-NotificationListener
+//     * @see javax.management.NotificationBroadcaster#addNotificationListener(javax.management.NotificationListener, javax.management.NotificationFilter, java.lang.Object)
+//     */
+//    public void addNotificationListener(NotificationListener listener, 
+//            NotificationFilter filter, Object object) throws IllegalArgumentException {
+//    	broadcaster.addNotificationListener(listener,filter,object);
+//    }
+//    
+//    
+//    /**
+//     * Remove a JMX-NotificationListener 
+//     * @see javax.management.NotificationBroadcaster#removeNotificationListener(javax.management.NotificationListener)
+//     */
+//    public void removeNotificationListener(NotificationListener listener) 
+//        throws ListenerNotFoundException {
+//    	broadcaster.removeNotificationListener(listener);
+//    }
+    
+    
+     // ------------------------------------------------------------- Attributes
+        
+        
+    public boolean isEventProvider() {
+        return false;
+    }
+    
+    public boolean isStateManageable() {
+        return false;
+    }
+    
+    public boolean isStatisticsProvider() {
+        return false;
+    }
+
+    public Log getLogger() {
+        return parent.getLogger();
+    }
+
+    /** Specify the instance. Avoids the class lookup, disables unloading.
+     *  Use for embedded case, or to control the allocation.
+     * 
+     * @param servlet
+     */
+    public void setServlet(Servlet servlet) {
+        instance = servlet;
+    }
+
+
+}



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org