/*
 * Copyright (c) 1997-2018 Oracle and/or its affiliates. All rights reserved.
 * Copyright 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.catalina.core;

import java.io.IOException;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.Principal;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.logging.Level;
import java.text.MessageFormat;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.ObjectName;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.UnavailableException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import static com.sun.logging.LogCleanerUtil.neutralizeForLog;
import org.apache.catalina.Container;
import org.apache.catalina.ContainerServlet;
import org.apache.catalina.Context;
import static org.apache.catalina.InstanceEvent.EventType.AFTER_DESTROY_EVENT;
import static org.apache.catalina.InstanceEvent.EventType.AFTER_INIT_EVENT;
import static org.apache.catalina.InstanceEvent.EventType.AFTER_SERVICE_EVENT;
import static org.apache.catalina.InstanceEvent.EventType.BEFORE_DESTROY_EVENT;
import static org.apache.catalina.InstanceEvent.EventType.BEFORE_INIT_EVENT;
import static org.apache.catalina.InstanceEvent.EventType.BEFORE_SERVICE_EVENT;
import org.apache.catalina.InstanceListener;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.Loader;
import org.apache.catalina.LogFacade;
import org.apache.catalina.Wrapper;
import org.apache.catalina.security.SecurityUtil;
import org.apache.catalina.util.Enumerator;
import org.apache.catalina.util.InstanceSupport;
import org.glassfish.web.valve.GlassFishValve;
// END GlassFish 1343

/**
 * 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: 1.12.2.1 $ $Date: 2008/04/17 18:37:09 $
 */
public class StandardWrapper
        extends ContainerBase
        implements ServletConfig, Wrapper {

    private static final String[] DEFAULT_SERVLET_METHODS = new String[] {
                                                    "GET", "HEAD", "POST" };

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


    /**
     * Create a new StandardWrapper component with the default basic Valve.
     */
    public StandardWrapper() {

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

    }


    // ----------------------------------------------------- Instance Variables


    /**
     * 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 AtomicInteger countAllocated = new AtomicInteger(0);


    /**
     * The debugging detail level for this component.
     */
    private int debug = 0;


    /**
     * The facade associated with this wrapper.
     */
    private StandardWrapperFacade facade =
        new StandardWrapperFacade(this);


    /**
     * 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 volatile Servlet instance = null;


    /**
     * Flag that indicates if this instance has been initialized
     */
    protected volatile boolean instanceInitialized = false;


    /**
     * The support object for our instance listeners.
     */
    private InstanceSupport instanceSupport = new InstanceSupport(this);


    /**
     * 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<String> mappings = new ArrayList<String>();


    /**
     * The initialization parameters for this servlet, keyed by
     * parameter name.
     */
    private Map<String, String> parameters = new HashMap<String, String>();


    /**
     * 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<String, String> references = new HashMap<String, String>();


    /**
     * 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 servletClassName = null;


    /**
     * The class from which this servlet will be instantiated
     */
    private Class <? extends Servlet> servletClass = null;


    /**
     * Does this servlet implement the SingleThreadModel interface?
     */
    private volatile 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.
     * TODO: remove
     */
    private Stack<Servlet> instancePool = null;


    /**
     * Wait time for servlet unload in ms.
     */
    protected long unloadDelay = 2000;


    /**
     * True if this StandardWrapper is for the JspServlet
     */
    private boolean isJspServlet;


    /**
     * The ObjectName of the JSP monitoring mbean
     */
    private ObjectName jspMonitorON;


    // To support jmx attributes
    private StandardWrapperValve swValve;
    private long loadTime=0;
    private int classLoadTime=0;

    private String description;


    /**
     * Async support
     */
    private boolean isAsyncSupported = false;
    //private long asyncTimeout;


    /**
     * 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};

    /**
     * File upload (multipart) support
     */
    private boolean multipartConfigured = false;
    private String multipartLocation = null;
    private long multipartMaxFileSize = -1L;
    private long multipartMaxRequestSize = -1L;
    private int multipartFileSizeThreshold = 10240;  // 10K

    private boolean osgi = false;


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

    /**
     * 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.
     */
    @Override
    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
     */
    @Override
    public void setAvailable(long available) {

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

    }


    /**
     * 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.get());

    }


    /**
     * Return the debugging detail level for this component.
     */
    @Override
    public int getDebug() {
        return (this.debug);
    }


    /**
     * Set the debugging detail level for this component.
     *
     * @param debug The new debugging detail level
     */
    @Override
    public void setDebug(int debug) {
        int oldDebug = this.debug;
        this.debug = debug;
        support.firePropertyChange("debug", oldDebug,
                (long) this.debug);
    }


    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>.
     */
    @Override
    public String getInfo() {
        return (info);
    }


    /**
     * Return the InstanceSupport object for this Wrapper instance.
     */
    public InstanceSupport getInstanceSupport() {
        return (this.instanceSupport);
    }


    /**
     * Return the context-relative URI of the JSP file for this servlet.
     */
    @Override
    public String getJspFile() {
        return (this.jspFile);
    }


    /**
     * Set the context-relative URI of the JSP file for this servlet.
     *
     * @param jspFile JSP file URI
     */
    @Override
    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).
     */
    @Override
    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
     */
    @Override
    public void setLoadOnStartup(int value) {

        int oldLoadOnStartup = this.loadOnStartup;
        this.loadOnStartup = value;
        support.firePropertyChange("loadOnStartup",
                                   Integer.valueOf(oldLoadOnStartup),
                                   Integer.valueOf(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());
    }


    /**
     * Sets the description of this servlet.
     */
    @Override
    public void setDescription(String description) {
        this.description = description;
    }


    /**
     * Gets the description of this servlet.
     */
    @Override
    public String getDescription() {
        return description;
    }


    /**
     * 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
     */
    @Override
    public void setParent(Container container) {
        if ((container != null) &&
            !(container instanceof Context))
            throw new IllegalArgumentException
                    (rb.getString(LogFacade.PARENT_CONTAINER_MUST_BE_CONTEXT_EXCEPTION));
        if (container instanceof StandardContext) {
            unloadDelay = ((StandardContext)container).getUnloadDelay();
            notifyContainerListeners =
                ((StandardContext)container).isNotifyContainerListeners();
        }
        super.setParent(container);
    }


    /**
     * Return the run-as identity for this servlet.
     */
    @Override
    public String getRunAs() {
        return (this.runAs);
    }


    /**
     * Set the run-as identity for this servlet.
     *
     * @param runAs New run-as identity value
     */
    @Override
    public void setRunAs(String runAs) {
        String oldRunAs = this.runAs;
        this.runAs = runAs;
        support.firePropertyChange("runAs", oldRunAs, this.runAs);
    }


    /**
     * Marks the wrapped servlet as supporting async operations or not.
     *
     * @param isAsyncSupported true if the wrapped servlet supports async mode,
     * false otherwise
     */
    @Override
    public void setIsAsyncSupported(boolean isAsyncSupported) {
        this.isAsyncSupported = isAsyncSupported;
    }


    /**
     * Checks if the wrapped servlet has been annotated or flagged in the
     * deployment descriptor as being able to support asynchronous operations.
     *
     * @return true if the wrapped servlet supports async operations, and
     * false otherwise
     */
    @Override
    public boolean isAsyncSupported() {
        return isAsyncSupported;
    }


    /**
     * Return the fully qualified servlet class name for this servlet.
     */
    @Override
    public String getServletClassName() {
        return this.servletClassName;
    }


    /**
     * Set the fully qualified servlet class name for this servlet.
     *
     * @param className Servlet class name
     */
    @Override
    public void setServletClassName(String className) {
        if (className == null) {
            throw new NullPointerException("Null servlet class name");
        }
        if (servletClassName != null) {
            throw new IllegalStateException(
                "Wrapper already initialized with servlet instance, " +
                "class, or name");
        }
        servletClassName = className;
        // oldServletClassName is null
        support.firePropertyChange("servletClassName", null,
                                   servletClassName);
        if (Constants.JSP_SERVLET_CLASS.equals(servletClassName)) {
            isJspServlet = true;
        }
    }


    /**
     * @return the servlet class, or null if the servlet class has not
     * been loaded yet
     */
    public Class <? extends Servlet> getServletClass() {
        return servletClass;
    }

    /**
     * Sets the class object from which this servlet will be instantiated.
     *
     * @param clazz The class object from which this servlet will
     * be instantiated
     */
    @Override
    public void setServletClass(Class <? extends Servlet> clazz) {
        if (clazz == null) {
            throw new NullPointerException("Null servlet class");
        }
        if ((servletClass != null) ||
                servletClassName != null &&
                    !servletClassName.equals(clazz.getName())) {
            throw new IllegalStateException(
                "Wrapper already initialized with servlet instance, " +
                "class, or name");
        }
        servletClass = clazz;
        servletClassName = clazz.getName();
        if (Constants.JSP_SERVLET_CLASS.equals(servletClassName)) {
            isJspServlet = true;
        }
    }


    /**
     * @return the servlet instance, or null if the servlet has not yet
     * been instantiated
     */
    public Servlet getServlet() {
        return instance;
    }


    /**
     * Sets the servlet instance for this wrapper.
     *
     * @param instance the servlet instance
     */
    public void setServlet(Servlet instance) {
        if (instance == null) {
            throw new NullPointerException("Null servlet instance");
        }
        if (servletClassName != null) {
            throw new IllegalStateException(
                "Wrapper already initialized with servlet instance, " +
                "class, or name");
        }
        this.instance = instance;
        servletClass = instance.getClass();
        servletClassName = servletClass.getName();
        if (Constants.JSP_SERVLET_CLASS.equals(servletClassName)) {
            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) {
        setName(name);
    }


    /**
     * Is this servlet currently unavailable?
     */
    @Override
    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
     */
    @Override
    public String[] getServletMethods() throws ServletException {

        loadServletClass();

        if (!jakarta.servlet.http.HttpServlet.class.isAssignableFrom(
                                                        servletClass)) {
            return DEFAULT_SERVLET_METHODS;
        }

        HashSet<String> allow = new HashSet<String>();
        allow.add("TRACE");
        allow.add("OPTIONS");

        Method[] methods = getAllDeclaredMethods(servletClass);
        for (int i=0; methods != null && i<methods.length; i++) {
            Method m = methods[i];
            Class<?> params[] = m.getParameterTypes();

            if (!(params.length == 2 &&
                    params[0] == HttpServletRequest.class &&
                    params[1] == HttpServletResponse.class)) {
                continue;
            }

            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 allow.toArray(methodNames);
    }


    public boolean isMultipartConfigured() {
        return multipartConfigured;
    }

    /**
     * Sets the multipart location
     */
    @Override
    public void setMultipartLocation(String location) {
        multipartConfigured = true;
        multipartLocation = location;
    }


    /**
     * Gets the multipart location
     */
    @Override
    public String getMultipartLocation(){
        return multipartLocation;
    }


    /**
     * Sets the multipart max-file-size
     */
    @Override
    public void setMultipartMaxFileSize(long maxFileSize) {
        multipartConfigured = true;
        multipartMaxFileSize = maxFileSize;
    }


    /**
     * Gets the multipart max-file-size
     */
    @Override
    public long getMultipartMaxFileSize() {
        return multipartMaxFileSize;
    }


    /**
     * Sets the multipart max-request-size
     */
    @Override
    public void setMultipartMaxRequestSize(long maxRequestSize) {
        multipartConfigured = true;
        multipartMaxRequestSize = maxRequestSize;
    }


    /**
     * Gets the multipart max-request-Size
     */
    @Override
    public long getMultipartMaxRequestSize() {
        return multipartMaxRequestSize;
    }


    /**
     * Sets the multipart file-size-threshold
     */
    @Override
    public void setMultipartFileSizeThreshold(int fileSizeThreshold) {
        multipartConfigured = true;
        multipartFileSizeThreshold = fileSizeThreshold;
    }


    /**
     * Gets the multipart file-size-threshol
     */
    @Override
    public int getMultipartFileSizeThreshold() {
        return multipartFileSizeThreshold;
    }


    protected boolean isOSGi() {
        return osgi;
    }


    protected void setOSGi(boolean osgi) {
        this.osgi = osgi;
    }


    // --------------------------------------------------------- Public Methods


    // START GlassFish 1343
    @Override
    public synchronized void addValve(GlassFishValve valve) {
        /*
         * This exception should never be thrown in reality, because we never
         * add any valves to a StandardWrapper.
         * This exception is added here as an alert mechanism only, should
         * there ever be a need to add valves to a StandardWrapper in the
         * future.
         * In that case, the optimization in StandardContextValve related to
         * GlassFish 1343 will need to be adjusted, by calling
         * pipeline.getValves() and checking the pipeline's length to
         * determine whether the basic valve may be invoked directly. The
         * optimization currently avoids a call to pipeline.getValves(),
         * because it is expensive.
         */
        throw new UnsupportedOperationException(
            "Adding valves to wrappers not supported");
    }
    // END GlassFish 1343


    /**
     * Extract the root cause from a servlet exception.
     *
     * @param e The servlet exception
     */
    public static Throwable getRootCause(ServletException e) {
        Throwable rootCause = e;
        Throwable rootCauseCheck;
        // Extra aggressive rootCause finding
        int loops = 0;
        do {
            loops++;
            rootCauseCheck = rootCause.getCause();
            if (rootCauseCheck != null)
                rootCause = rootCauseCheck;
        } while (rootCauseCheck != null && (loops < 20));
        return rootCause;
    }


    /**
     * Refuse to add a child Container, because Wrappers are the lowest level
     * of the Container hierarchy.
     *
     * @param child Child container to be added
     */
    @Override
    public void addChild(Container child) {
        throw new IllegalStateException
                (rb.getString(LogFacade.WRAPPER_CONTAINER_NO_CHILD_EXCEPTION));
    }


    /**
     * Adds the initialization parameter with the given name and value
     * to this servlet.
     *
     * @param name the name of the init parameter
     * @param value the value of the init parameter
     */
    @Override
    public void addInitParameter(String name, String value) {
        setInitParameter(name, value, true);
        if (notifyContainerListeners) {
            fireContainerEvent("addInitParameter", name);
        }
    }


    /**
     * Sets the init parameter with the given name and value
     * on this servlet.
     *
     * @param name the init parameter name
     * @param value the init parameter value
     * @param override true if the given init param is supposed to
     * override an existing init param with the same name, and false
     * otherwise
     *
     * @return true if the init parameter with the given name and value
     * was set, false otherwise
     */
    public boolean setInitParameter(String name, String value,
                                    boolean override) {
        if (null == name || null == value) {
            throw new IllegalArgumentException(
                "Null servlet init parameter name or value");
        }

        synchronized (parameters) {
            if (override || !parameters.containsKey(name)) {
                parameters.put(name, value);
                return true;
            } else {
                return false;
            }
        }
    }


    /**
     * Sets the initialization parameters contained in the given map
     * on this servlet.
     *
     * @param initParameters the map with the init params to set
     *
     * @return the (possibly empty) Set of initialization parameter names
     * that are in conflict
     */
    public Set<String> setInitParameters(Map<String, String> initParameters) {
        if (null == initParameters) {
            throw new IllegalArgumentException("Null init parameters");
        }

        synchronized (parameters) {
            Set<String> conflicts = null;
            for (Map.Entry<String, String> e : initParameters.entrySet()) {
                if (e.getKey() == null || e.getValue() == null) {
                    throw new IllegalArgumentException(
                        "Null parameter name or value");
                }
                if (parameters.containsKey(e.getKey())) {
                    if (conflicts == null) {
                        conflicts = new HashSet<String>();
                    }
                    conflicts.add(e.getKey());
                }
            }

            if (conflicts != null) {
                return conflicts;
            }

            for (Map.Entry<String, String> e : initParameters.entrySet()) {
                setInitParameter(e.getKey(), e.getValue(), true);
            }

            return Collections.emptySet();
        }
    }


    /**
     * Add a new listener interested in InstanceEvents.
     *
     * @param listener The new listener
     */
    @Override
    public void addInstanceListener(InstanceListener listener) {
        instanceSupport.addInstanceListener(listener);
    }


    /**
     * Add a mapping associated with the Wrapper.
     *
     * @param mapping The new wrapper mapping
     */
    @Override
    public void addMapping(String mapping) {
        synchronized (mappings) {
            mappings.add(mapping);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("addMapping", mapping);
        }
    }


    public Collection<String> getMappings() {
        synchronized (mappings) {
            return Collections.unmodifiableList(mappings);
        }
    }


    /**
     * 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
     */
    @Override
    public void addSecurityReference(String name, String link) {
        synchronized (references) {
            references.put(name, link);
        }

        if (notifyContainerListeners) {
            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
     */
    @Override
    public synchronized Servlet allocate() throws ServletException {

        // If we are currently unloading this servlet, throw an exception
        if (unloading) {
            String msg = MessageFormat.format(rb.getString(LogFacade.CANNOT_ALLOCATE_SERVLET_EXCEPTION), getName());
            throw new ServletException(msg);
        }

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

            // Load and initialize our instance if necessary
            if (instance == null) {
                // No instance. Instantiate and initialize
                try {
                    if (log.isLoggable(Level.FINEST))
                        log.log(Level.FINEST, "Allocating non-STM instance");
                    instance = loadServlet();
                    initServlet(instance);
                } catch (ServletException e) {
                    throw e;
                } catch (Throwable e) {
                    throw new ServletException
                            (rb.getString(LogFacade.ERROR_ALLOCATE_SERVLET_INSTANCE_EXCEPTION), e);
                }
            } else if (!instanceInitialized) {
                /*
                 * Instance not yet initialized. This is the case
                 * when the instance was registered via
                 * ServletContext#addServlet
                 */
                initServlet(instance);
            }

            if (!singleThreadModel) {
                if (log.isLoggable(Level.FINEST))
                    log.log(Level.FINEST, "Returning non-STM instance");
                countAllocated.incrementAndGet();
                return (instance);
            }
        }

        synchronized (instancePool) {

            while (countAllocated.get() >= nInstances) {
                // Allocate a new instance if possible, or else wait
                if (nInstances < maxInstances) {
                    try {
                        Servlet servlet = loadServlet();
                        initServlet(servlet);
                        instancePool.push(servlet);
                        nInstances++;
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        throw new ServletException
                                (rb.getString(LogFacade.ERROR_ALLOCATE_SERVLET_INSTANCE_EXCEPTION), e);
                    }
                } else {
                    try {
                        instancePool.wait();
                    } catch (InterruptedException e) {
                        // Ignore
                    }
                }
            }
            if (log.isLoggable(Level.FINEST)) {
                log.log(Level.FINEST, "Returning allocated STM instance");
            }
            countAllocated.incrementAndGet();
            return 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
     */
    @Override
    public void deallocate(Servlet servlet) throws ServletException {

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

        // Unlock and free this instance
        synchronized (instancePool) {
            countAllocated.decrementAndGet();
            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
     */
    @Override
    public String findInitParameter(String name) {
        synchronized (parameters) {
            return parameters.get(name);
        }
    }


    /**
     * Return the names of all defined initialization parameters for this
     * servlet.
     */
    @Override
    public String[] findInitParameters() {
        synchronized (parameters) {
            String results[] = new String[parameters.size()];
            return parameters.keySet().toArray(results);
        }
    }


    /**
     * Return the mappings associated with this wrapper.
     */
    @Override
    public String[] findMappings() {
        synchronized (mappings) {
            return 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
     */
    @Override
    public String findSecurityReference(String name) {
        synchronized (references) {
            return references.get(name);
        }
    }


    /**
     * Return the set of security role reference names associated with
     * this servlet, if any; otherwise return a zero-length array.
     */
    @Override
    public String[] findSecurityReferences() {
        synchronized (references) {
            String results[] = new String[references.size()];
            return references.keySet().toArray(results);
        }
    }


    /**
     * FIXME: Fooling introspection ...
     */
    public Wrapper findMappingObject() {
        return (Wrapper) getMappingObject();
    }


    /**
     * Loads and initializes an instance of the 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
     */
    @Override
    public synchronized void load() throws ServletException {
        instance = loadServlet();
        initServlet(instance);
    }


    /**
     * Creates an instance of the servlet, if there is not already
     * at least one initialized instance.
     */
    private synchronized Servlet loadServlet() throws ServletException {

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

        long t1 = System.currentTimeMillis();

        loadServletClass();

        // Instantiate the servlet class
        Servlet servlet = null;
        try {
            servlet = ((StandardContext)getParent()).createServletInstance(
                servletClass);
        } catch (ClassCastException e) {
            unavailable(null);
            // Restore the context ClassLoader
            String msg = MessageFormat.format(rb.getString(LogFacade.CLASS_IS_NOT_SERVLET_EXCEPTION), servletClass.getName());
            throw new ServletException(msg, e);
        } catch (Throwable e) {
            unavailable(null);
            // Restore the context ClassLoader
            String msg = MessageFormat.format(rb.getString(LogFacade.ERROR_INSTANTIATE_SERVLET_CLASS_EXCEPTION), servletClass.getName());
            throw new ServletException(msg, e);
        }

        // Check if loading the servlet in this web application should be
        // allowed
        if (!isServletAllowed(servlet)) {
            String msg = MessageFormat.format(rb.getString(LogFacade.PRIVILEGED_SERVLET_CANNOT_BE_LOADED_EXCEPTION), servletClass.getName());
            throw new SecurityException(msg);
        }

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

        classLoadTime = (int) (System.currentTimeMillis() -t1);

        // Register our newly initialized instance
        if (notifyContainerListeners) {
            fireContainerEvent("load", this);
        }

        loadTime = System.currentTimeMillis() - t1;

        return servlet;
    }


    /*
     * Loads the servlet class
     */
    private synchronized void loadServletClass() throws ServletException {
        if (servletClass != null) {
            return;
        }

        // If this "servlet" is really a JSP file, get the right class.
        String actualClass = servletClassName;
        if ((actualClass == null) && (jspFile != null)) {
            Wrapper jspWrapper = (Wrapper)
                ((Context) getParent()).findChild(Constants.JSP_SERVLET_NAME);
            if (jspWrapper != null) {
                actualClass = jspWrapper.getServletClassName();
                // Merge init parameters
                String paramNames[] = jspWrapper.findInitParameters();
                for (String paramName : paramNames) {
                    if (parameters.get(paramName) == null) {
                        parameters.put(paramName,
                                       jspWrapper.findInitParameter(paramName));
                    }
                }
            }
        }

        // Complain if no servlet class has been specified
        if (actualClass == null) {
            unavailable(null);
            String msg = MessageFormat.format(rb.getString(LogFacade.NO_SERVLET_BE_SPECIFIED_EXCEPTION), getName());
            throw new ServletException(msg);
        }

        // Acquire an instance of the class loader to be used
        Loader loader = getLoader();
        if (loader == null) {
            unavailable(null);
            String msg = MessageFormat.format(rb.getString(LogFacade.CANNOT_FIND_LOADER_EXCEPTION), getName());
            throw new ServletException(msg);
        }

        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 clazz = null;
        try {
            if (SecurityUtil.isPackageProtectionEnabled()){
                final ClassLoader fclassLoader = classLoader;
                final String factualClass = actualClass;
                try{
                    clazz = AccessController.doPrivileged(
                        new PrivilegedExceptionAction<Class>(){
                            @Override
                            public Class 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 {
                        String msgErrorLoadingInfo = MessageFormat.format(rb.getString(LogFacade.ERROR_LOADING_INFO),
                                                          new Object[] {fclassLoader, factualClass});
                        getServletContext().log(msgErrorLoadingInfo, ex );
                    }
                }
            } else {
                if (classLoader != null) {
                    clazz = classLoader.loadClass(actualClass);
                } else {
                    clazz = Class.forName(actualClass);
                }
            }
        } catch (ClassNotFoundException e) {
            unavailable(null);
            String msgErrorLoadingInfo = MessageFormat.format(rb.getString(LogFacade.ERROR_LOADING_INFO),
                    new Object[] {classLoader, actualClass});
            getServletContext().log(msgErrorLoadingInfo, e );
            String msg = MessageFormat.format(rb.getString(LogFacade.CANNOT_FIND_SERVLET_CLASS_EXCEPTION), actualClass);
            throw new ServletException(msg, e);
        }

        if (clazz == null) {
            String msg = MessageFormat.format(rb.getString(LogFacade.CANNOT_FIND_SERVLET_CLASS_EXCEPTION), actualClass);
            unavailable(null);
            throw new ServletException(msg);
        }

        servletClass = castToServletClass(clazz);
    }

    @SuppressWarnings("unchecked")
    private Class<? extends Servlet> castToServletClass(Class<?> clazz) {
        return (Class<? extends Servlet>)clazz;
    }


    /**
     * Initializes the given servlet instance, by calling its init method.
     */
    private void initServlet(Servlet servlet) throws ServletException {
        if (instanceInitialized && !singleThreadModel) {
            // Servlet has already been initialized
            return;
        }

        try {
            instanceSupport.fireInstanceEvent(BEFORE_INIT_EVENT, servlet);
            // START SJS WS 7.0 6236329
            //if( System.getSecurityManager() != null) {
            if ( SecurityUtil.executeUnderSubjectDoAs() ){
            // END OF SJS WS 7.0 6236329
                Object[] initType = new Object[1];
                initType[0] = facade;
                SecurityUtil.doAsPrivilege("init", servlet, classType,
                                           initType);
                initType = null;
            } else {
                servlet.init(facade);
            }

            instanceInitialized = true;

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

                // START PWC 4707989
                String allowedMethods = parameters.get("httpMethods");
                if (allowedMethods != null
                        && allowedMethods.length() > 0) {
                    String[] s = allowedMethods.split(",");
                    if (s.length > 0) {
                        req.setMethod(s[0].trim());
                    }
                }
                // END PWC 4707989

                DummyResponse res = new DummyResponse();

                // START SJS WS 7.0 6236329
                //if( System.getSecurityManager() != null) {
                if ( SecurityUtil.executeUnderSubjectDoAs() ){
                // END OF SJS WS 7.0 6236329
                    Object[] serviceType = new Object[2];
                    serviceType[0] = req;
                    serviceType[1] = res;
                    SecurityUtil.doAsPrivilege("service", servlet,
                                               classTypeUsedInService,
                                               serviceType);
                } else {
                    servlet.service(req, res);
                }
            }
            instanceSupport.fireInstanceEvent(AFTER_INIT_EVENT,servlet);

        } catch (UnavailableException f) {
            instanceSupport.fireInstanceEvent(AFTER_INIT_EVENT,servlet, f);
            unavailable(f);
            throw f;

        } catch (ServletException f) {
            instanceSupport.fireInstanceEvent(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(AFTER_INIT_EVENT,servlet, f);
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            String msg = MessageFormat.format(rb.getString(LogFacade.SERVLET_INIT_EXCEPTION), getName());
            throw new ServletException(msg, f);
        }
    }


    // START IASRI 4665318
    void service(ServletRequest request, ServletResponse response,
                 Servlet serv)
             throws IOException, ServletException {

        InstanceSupport supp = getInstanceSupport();

        try {
            supp.fireInstanceEvent(BEFORE_SERVICE_EVENT,
                                   serv, request, response);
            if (!isAsyncSupported()) {
                RequestFacadeHelper reqFacHelper =
                    RequestFacadeHelper.getInstance(request);
                if (reqFacHelper != null) {
                    reqFacHelper.disableAsyncSupport();
                }
            }
            if ((request instanceof HttpServletRequest) &&
                (response instanceof HttpServletResponse)) {

                if ( SecurityUtil.executeUnderSubjectDoAs() ){
                    final ServletRequest req = request;
                    final ServletResponse res = response;
                    Principal principal =
                        ((HttpServletRequest) req).getUserPrincipal();

                    Object[] serviceType = new Object[2];
                    serviceType[0] = req;
                    serviceType[1] = res;

                    SecurityUtil.doAsPrivilege("service",
                                               serv,
                                               classTypeUsedInService,
                                               serviceType,
                                               principal);
                } else {
                    serv.service(request,
                                 response);
                }
            } else {
                serv.service(request, response);
            }
            supp.fireInstanceEvent(AFTER_SERVICE_EVENT,
                                   serv, request, response);
        } catch (IOException e) {
            // Set response status before firing event, see IT 10022
            if (response instanceof HttpServletResponse) {
                ((HttpServletResponse)response).setStatus(
                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            supp.fireInstanceEvent(AFTER_SERVICE_EVENT,
                                   serv, request, response, e);
            throw e;
        } catch (ServletException e) {
            // Set response status before firing event, see IT 10022
            if (response instanceof HttpServletResponse) {
                ((HttpServletResponse)response).setStatus(
                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            supp.fireInstanceEvent(AFTER_SERVICE_EVENT,
                                   serv, request, response, e);
            throw e;
        } catch (RuntimeException e) {
            // Set response status before firing event, see IT 10022
            if (response instanceof HttpServletResponse) {
                ((HttpServletResponse)response).setStatus(
                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            supp.fireInstanceEvent(AFTER_SERVICE_EVENT,
                                   serv, request, response, e);
            throw e;
        } catch (Error e) {
            // Set response status before firing event, see IT 10022
            if (response instanceof HttpServletResponse) {
                ((HttpServletResponse)response).setStatus(
                    HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            }
            supp.fireInstanceEvent(AFTER_SERVICE_EVENT,
                                   serv, request, response, e);
            throw e;
        } catch (Throwable e) {
            // Set response status before firing event, see IT 10022
            ((HttpServletResponse)response).setStatus(
                HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            supp.fireInstanceEvent(AFTER_SERVICE_EVENT,
                                   serv, request, response, e);
            throw new ServletException(rb.getString(LogFacade.SERVLET_EXECUTION_EXCEPTION), e);
        }

    }
    // END IASRI 4665318


    /**
     * Remove the specified initialization parameter from this servlet.
     *
     * @param name Name of the initialization parameter to remove
     */
    @Override
    public void removeInitParameter(String name) {

        synchronized (parameters) {
            parameters.remove(name);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("removeInitParameter", name);
        }
    }


    /**
     * Remove a listener no longer interested in InstanceEvents.
     *
     * @param listener The listener to remove
     */
    @Override
    public void removeInstanceListener(InstanceListener listener) {

        instanceSupport.removeInstanceListener(listener);

    }


    /**
     * Remove a mapping associated with the wrapper.
     *
     * @param mapping The pattern to remove
     */
    @Override
    public void removeMapping(String mapping) {

        synchronized (mappings) {
            mappings.remove(mapping);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("removeMapping", mapping);
        }
    }


    /**
     * Remove any security role reference for the specified role name.
     *
     * @param name Security role used within this servlet to be removed
     */
    @Override
    public void removeSecurityReference(String name) {

        synchronized (references) {
            references.remove(name);
        }

        if (notifyContainerListeners) {
            fireContainerEvent("removeSecurityReference", name);
        }
    }


    /**
     * Return a String representation of this component.
     */
    @Override
    public String toString() {

        StringBuilder sb = new StringBuilder();
        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
     */
    @Override
    public void unavailable(UnavailableException unavailable) {
        String msg = MessageFormat.format(rb.getString(LogFacade.MARK_SERVLET_UNAVAILABLE), neutralizeForLog(getName()));
        getServletContext().log(msg);
        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
     */
    @Override
    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.get() > 0) {
            int nRetries = 0;
            long delay = unloadDelay / 20;
            while ((nRetries < 21) && (countAllocated.get() > 0)) {
                if ((nRetries % 10) == 0) {
                    if (log.isLoggable(Level.FINE)) {
                        log.log(Level.FINE, LogFacade.WAITING_INSTANCE_BE_DEALLOCATED, new Object[] {countAllocated.toString(),
                                instance.getClass().getName()});
                    }
                }
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                    // Ignore
                }
                nRetries++;
            }
        }

        ClassLoader oldCtxClassLoader =
            Thread.currentThread().getContextClassLoader();
        ClassLoader classLoader = instance.getClass().getClassLoader();

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

            Thread.currentThread().setContextClassLoader(classLoader);
            // START SJS WS 7.0 6236329
            //if( System.getSecurityManager() != null) {
            if ( SecurityUtil.executeUnderSubjectDoAs() ){
            // END OF SJS WS 7.0 6236329
                SecurityUtil.doAsPrivilege("destroy", instance);
                SecurityUtil.remove(instance);
            } else {
                instance.destroy();
            }

            instanceSupport.fireInstanceEvent(AFTER_DESTROY_EVENT, instance);
        } catch (Throwable t) {
            instanceSupport.fireInstanceEvent(AFTER_DESTROY_EVENT, instance, t);
            instance = null;
            instancePool = null;
            nInstances = 0;
            if (notifyContainerListeners) {
                fireContainerEvent("unload", this);
            }
            unloading = false;
            String msg = MessageFormat.format(rb.getString(LogFacade.DESTROY_SERVLET_EXCEPTION), getName());
            throw new ServletException(msg, t);
        } finally {
            // restore the context ClassLoader
            Thread.currentThread().setContextClassLoader(oldCtxClassLoader);
        }

        // Deregister the destroyed instance
        instance = null;

        if (singleThreadModel && (instancePool != null)) {
            try {
                Thread.currentThread().setContextClassLoader(classLoader);
                while (!instancePool.isEmpty()) {
                    // START SJS WS 7.0 6236329
                    //if( System.getSecurityManager() != null) {
                    if ( SecurityUtil.executeUnderSubjectDoAs() ){
                    // END OF SJS WS 7.0 6236329
                        SecurityUtil.doAsPrivilege("destroy",
                                                   instancePool.pop());
                        SecurityUtil.remove(instance);
                    } else {
                        instancePool.pop().destroy();
                    }
                }
            } catch (Throwable t) {
                instancePool = null;
                nInstances = 0;
                unloading = false;
                if (notifyContainerListeners) {
                    fireContainerEvent("unload", this);
                }
                String msg = MessageFormat.format(rb.getString(LogFacade.DESTROY_SERVLET_EXCEPTION), getName());
                throw new ServletException(msg, t);
            } finally {
                // restore the context ClassLoader
                Thread.currentThread().setContextClassLoader
                    (oldCtxClassLoader);
            }
            instancePool = null;
            nInstances = 0;
        }

        singleThreadModel = false;

        unloading = false;

        if (notifyContainerListeners) {
            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
     */
    @Override
    public String getInitParameter(String name) {
        return findInitParameter(name);
    }


    public Map<String, String> getInitParameters() {
        synchronized (parameters) {
            return Collections.unmodifiableMap(parameters);
        }
    }


    /**
     * Return the set of initialization parameter names defined for this
     * servlet.  If none are defined, an empty Enumeration is returned.
     */
    @Override
    public Enumeration<String> getInitParameterNames() {
        synchronized (parameters) {
            return (new Enumerator<String>(parameters.keySet()));
        }
    }


    /**
     * Return the servlet context with which this servlet is associated.
     */
    @Override
    public ServletContext getServletContext() {
        if (parent == null)
            return (null);
        else if (!(parent instanceof Context))
            return (null);
        else
            return (((Context) parent).getServletContext());
    }


    /**
     * Return the name of this servlet.
     */
    @Override
    public String getServletName() {
        return (getName());
    }

    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 <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);

    }


    /**
     * Log the abbreviated name of this Container for logging messages.
     */
    @Override
    protected String logName() {

        StringBuilder sb = new StringBuilder("StandardWrapper[");
        if (getParent() != null)
            sb.append(getParent().getName());
        else
            sb.append("null");
        sb.append(':');
        sb.append(getName());
        sb.append(']');
        return (sb.toString());

    }


    private Method[] getAllDeclaredMethods(Class<?> c) {

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

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

        Method[] thisMethods = c.getDeclaredMethods();
        if (thisMethods.length == 0) {
            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
     */
    @Override
    public void start() throws LifecycleException {

        // Send j2ee.state.starting notification
        if (this.getObjectName() != null) {
            Notification notification = new Notification("j2ee.state.starting", this, sequenceNumber++);
            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, sequenceNumber++);
            sendNotification(notification);
        }

    }


    /**
     * Stop this component, gracefully shutting down the servlet if it has
     * been initialized.
     *
     * @exception LifecycleException if a fatal error occurs during shutdown
     */
    @Override
    public void stop() throws LifecycleException {

        setAvailable(Long.MAX_VALUE);

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

        // Shut down our servlet instance (if it has been initialized)
        try {
            unload();
        } catch (ServletException e) {
            String msg = MessageFormat.format(rb.getString(LogFacade.SERVLET_UNLOAD_EXCEPTION), neutralizeForLog(getName()));
            getServletContext().log(msg, e);
        }

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

        // Send j2ee.state.stoppped notification
        if (this.getObjectName() != null) {
            Notification notification =
                new Notification("j2ee.state.stopped", this, sequenceNumber++);
            sendNotification(notification);
        }

        if( oname != null ) {

            // Send j2ee.object.deleted notification
            Notification notification =
                new Notification("j2ee.object.deleted", this, sequenceNumber++);
            sendNotification(notification);
        }

    }

    protected void registerJMX(StandardContext ctx) {

        String parentName = ctx.getEncodedPath();
        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();
        if (isOSGi()) {
            onameStr += ",osgi=true";
        }

        try {
            oname=new ObjectName(onameStr);
            controller=oname;

            // Send j2ee.object.created notification
            if (this.getObjectName() != null) {
                Notification notification = new Notification( "j2ee.object.created", this, sequenceNumber++);
                sendNotification(notification);
            }
        } catch( Exception ex ) {
            if (log.isLoggable(Level.INFO)) {
                log.log(Level.INFO,
                    "Error registering servlet with jmx " + this, ex);
            }
        }

        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);
            } catch( Exception ex ) {
                if (log.isLoggable(Level.INFO)) {
                    log.log(Level.INFO,
                        "Error registering JSP monitoring with jmx " +
                        instance, ex);
                }
            }
        }

    }

    public void sendNotification(Notification notification) {

        if (broadcaster == null) {
            broadcaster = ((StandardEngine)getParent().getParent().getParent()).getService().getBroadcaster();
        }
        if (broadcaster != null) {
            broadcaster.sendNotification(notification);
        }
        return;
    }


    // ------------------------------------------------------------- Attributes


    public boolean isEventProvider() {
        return false;
    }

    public boolean isStateManageable() {
        return false;
    }

    public boolean isStatisticsProvider() {
        return false;
    }


}
