Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Tomcat/java/org/apache/catalina/core/   (Apache Software Stiftung Version 2.4.65©)  Datei vom 10.10.2023 mit Größe 47 kB image not shown  

Quelle  StandardWrapper.java   Sprache: JAVA

 
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.PrintStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;

import jakarta.servlet.MultipartConfigElement;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletContext;
import jakarta.servlet.ServletException;
import jakarta.servlet.UnavailableException;
import jakarta.servlet.annotation.MultipartConfig;

import org.apache.catalina.Container;
import org.apache.catalina.ContainerServlet;
import org.apache.catalina.Context;
import org.apache.catalina.Globals;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Wrapper;
import org.apache.catalina.security.SecurityUtil;
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.InstanceManager;
import org.apache.tomcat.PeriodicEventListener;
import org.apache.tomcat.util.ExceptionUtils;
import org.apache.tomcat.util.log.SystemLogHandler;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.modeler.Util;

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

public class StandardWrapper extends ContainerBase implements ServletConfig, Wrapper, NotificationEmitter {

    private final Log log = LogFactory.getLog(StandardWrapper.class); // must not be static

    protected 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);
        broadcaster = new NotificationBroadcasterSupport();

    }


    // ----------------------------------------------------- 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.
     */

    protected long available = 0L;

    /**
     * The broadcaster that sends j2ee notifications.
     */

    protected final NotificationBroadcasterSupport broadcaster;

    /**
     * The count of allocations that are currently active.
     */

    protected final AtomicInteger countAllocated = new AtomicInteger(0);


    /**
     * The facade associated with this wrapper.
     */

    protected final StandardWrapperFacade facade = new StandardWrapperFacade(this);


    /**
     * The (single) possibly uninitialized instance of this servlet.
     */

    protected volatile Servlet instance = null;


    /**
     * Flag that indicates if this instance has been initialized
     */

    protected volatile boolean instanceInitialized = false;


    /**
     * The load-on-startup order value (negative value means load on first call) for this servlet.
     */

    protected int loadOnStartup = -1;


    /**
     * Mappings associated with the wrapper.
     */

    protected final ArrayList<String> mappings = new ArrayList<>();


    /**
     * The initialization parameters for this servlet, keyed by parameter name.
     */

    protected HashMap<String,String> 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.
     */

    protected HashMap<String,String> references = new HashMap<>();


    /**
     * The run-as identity for this servlet.
     */

    protected String runAs = null;

    /**
     * The notification sequence number.
     */

    protected long sequenceNumber = 0;

    /**
     * The fully qualified servlet class name for this servlet.
     */

    protected String servletClass = null;


    /**
     * Are we unloading our servlet instance at the moment?
     */

    protected volatile boolean unloading = false;


    /**
     * Wait time for servlet unload in ms.
     */

    protected long unloadDelay = 2000;


    /**
     * True if this StandardWrapper is for the JspServlet
     */

    protected boolean isJspServlet;


    /**
     * The ObjectName of the JSP monitoring mbean
     */

    protected ObjectName jspMonitorON;


    /**
     * Should we swallow System.out
     */

    protected boolean swallowOutput = false;

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

    /**
     * Multipart config
     */

    protected MultipartConfigElement multipartConfigElement = null;

    /**
     * Async support
     */

    protected boolean asyncSupported = false;

    /**
     * Enabled
     */

    protected boolean enabled = true;

    private boolean overridable = false;

    /**
     * Static class array used when the SecurityManager is turned on and <code>Servlet.init</code> is invoked.
     */

    protected static Class<?>[] classType = new Class[] { ServletConfig.class };

    private final ReentrantReadWriteLock parametersLock = new ReentrantReadWriteLock();

    private final ReentrantReadWriteLock mappingsLock = new ReentrantReadWriteLock();

    private final ReentrantReadWriteLock referencesLock = new ReentrantReadWriteLock();


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

    @Override
    public boolean isOverridable() {
        return overridable;
    }

    @Override
    public void setOverridable(boolean overridable) {
        this.overridable = overridable;
    }

    /**
     * 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"Long.valueOf(oldAvailable), Long.valueOf(this.available));
    }


    /**
     * @return the number of active allocations of this servlet.
     */

    public int getCountAllocated() {
        return this.countAllocated.get();
    }


    /**
     * @return the load-on-startup order value (negative value means load on first call).
     */

    @Override
    public int getLoadOnStartup() {

        if (isJspServlet && loadOnStartup == -1) {
            /*
             * 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);
        }
    }

    /**
     * @return the load-on-startup value that was parsed
     */

    public String getLoadOnStartupString() {
        return Integer.toString(getLoadOnStartup());
    }


    /**
     * 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(sm.getString("standardWrapper.notContext"));
        }
        if (container instanceof StandardContext) {
            swallowOutput = ((StandardContext) container).getSwallowOutput();
            unloadDelay = ((StandardContext) container).getUnloadDelay();
        }
        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);

    }


    /**
     * @return the fully qualified servlet class name for this servlet.
     */

    @Override
    public String getServletClass() {
        return this.servletClass;
    }


    /**
     * Set the fully qualified servlet class name for this servlet.
     *
     * @param servletClass Servlet class name
     */

    @Override
    public void setServletClass(String servletClass) {

        String oldServletClass = this.servletClass;
        this.servletClass = servletClass;
        support.firePropertyChange("servletClass", oldServletClass, this.servletClass);
        if (Constants.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) {

        setName(name);

    }


    /**
     * @return <code>true</code> if the Servlet has been marked unavailable.
     */

    @Override
    public boolean isUnavailable() {

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

    }


    @Override
    public String[] getServletMethods() throws ServletException {

        instance = loadServlet();

        Class<? extends Servlet> servletClazz = instance.getClass();
        if (!jakarta.servlet.http.HttpServlet.class.isAssignableFrom(servletClazz)) {
            return DEFAULT_SERVLET_METHODS;
        }

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

        if (isJspServlet) {
            allow.add("GET");
            allow.add("HEAD");
            allow.add("POST");
        } else {
            allow.add("TRACE");

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

        return allow.toArray(new String[0]);
    }


    /**
     * @return the associated servlet instance.
     */

    @Override
    public Servlet getServlet() {
        return instance;
    }


    /**
     * Set the associated servlet instance.
     */

    @Override
    public void setServlet(Servlet servlet) {
        instance = servlet;
    }


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

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

    @Override
    public void backgroundProcess() {
        super.backgroundProcess();

        if (!getState().isAvailable()) {
            return;
        }

        if (getServlet() instanceof PeriodicEventListener) {
            ((PeriodicEventListener) getServlet()).periodicEvent();
        }
    }


    /**
     * Extract the root cause from a servlet exception.
     *
     * @param e The servlet exception
     *
     * @return the root cause of the Servlet exception
     */

    public static Throwable getRootCause(ServletException e) {
        Throwable rootCause = e;
        Throwable rootCauseCheck = null;
        // Extra aggressive rootCause finding
        int loops = 0;
        do {
            loops++;
            rootCauseCheck = rootCause.getCause();
            if (rootCauseCheck != null) {
                rootCause = rootCauseCheck;
            }
        } while (rootCauseCheck != null && (loops < 20));
        return rootCause;
    }


    /**
     * 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(sm.getString("standardWrapper.notChild"));

    }


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

    @Override
    public void addInitParameter(String name, String value) {

        parametersLock.writeLock().lock();
        try {
            parameters.put(name, value);
        } finally {
            parametersLock.writeLock().unlock();
        }
        fireContainerEvent("addInitParameter", name);

    }


    /**
     * Add a mapping associated with the Wrapper.
     *
     * @param mapping The new wrapper mapping
     */

    @Override
    public void addMapping(String mapping) {

        mappingsLock.writeLock().lock();
        try {
            mappings.add(mapping);
        } finally {
            mappingsLock.writeLock().unlock();
        }
        if (parent.getState().equals(LifecycleState.STARTED)) {
            fireContainerEvent(ADD_MAPPING_EVENT, 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
     */

    @Override
    public void addSecurityReference(String name, String link) {

        referencesLock.writeLock().lock();
        try {
            references.put(name, link);
        } finally {
            referencesLock.writeLock().unlock();
        }
        fireContainerEvent("addSecurityReference", name);

    }


    /**
     * Allocate an initialized instance of this Servlet that is ready to have its <code>service()</code> method called.
     *
     * @exception ServletException if the servlet init() method threw an exception
     * @exception ServletException if a loading error occurs
     */

    @Override
    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()));
        }

        boolean newInstance = false;

        // Load and initialize our instance if necessary
        if (instance == null || !instanceInitialized) {
            synchronized (this) {
                if (instance == null) {
                    try {
                        if (log.isDebugEnabled()) {
                            log.debug("Allocating instance");
                        }
                        instance = loadServlet();
                        newInstance = true;
                        // Increment here to prevent a race condition
                        // with unload. Bug 43683, test case #3
                        countAllocated.incrementAndGet();
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        ExceptionUtils.handleThrowable(e);
                        throw new ServletException(sm.getString("standardWrapper.allocate"), e);
                    }
                }
                if (!instanceInitialized) {
                    initServlet(instance);
                }
            }
        }

        if (log.isTraceEnabled()) {
            log.trace(" Returning instance");
        }
        // For new instances, count will have been incremented at the
        // time of creation
        if (!newInstance) {
            countAllocated.incrementAndGet();
        }
        return instance;
    }


    /**
     * Decrement the allocation count for this servlet.
     *
     * @param servlet The servlet to be returned
     *
     * @exception ServletException if a deallocation error occurs
     */

    @Override
    public void deallocate(Servlet servlet) throws ServletException {
        countAllocated.decrementAndGet();
    }


    /**
     * 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) {

        parametersLock.readLock().lock();
        try {
            return parameters.get(name);
        } finally {
            parametersLock.readLock().unlock();
        }

    }


    /**
     * Return the names of all defined initialization parameters for this servlet.
     */

    @Override
    public String[] findInitParameters() {

        parametersLock.readLock().lock();
        try {
            return parameters.keySet().toArray(new String[0]);
        } finally {
            parametersLock.readLock().unlock();
        }

    }


    /**
     * Return the mappings associated with this wrapper.
     */

    @Override
    public String[] findMappings() {

        mappingsLock.readLock().lock();
        try {
            return mappings.toArray(new String[0]);
        } finally {
            mappingsLock.readLock().unlock();
        }

    }


    /**
     * 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) {
        String reference = null;

        referencesLock.readLock().lock();
        try {
            reference = references.get(name);
        } finally {
            referencesLock.readLock().unlock();
        }

        // If not specified on the Wrapper, check the Context
        if (getParent() instanceof Context) {
            Context context = (Context) getParent();
            if (reference != null) {
                reference = context.findRoleMapping(reference);
            } else {
                reference = context.findRoleMapping(name);
            }
        }

        return reference;
    }


    /**
     * Return the set of security role reference names associated with this servlet, if any; otherwise return a
     * zero-length array.
     */

    @Override
    public String[] findSecurityReferences() {

        referencesLock.readLock().lock();
        try {
            return references.keySet().toArray(new String[0]);
        } finally {
            referencesLock.readLock().unlock();
        }

    }


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

    @Override
    public synchronized void load() throws ServletException {
        instance = loadServlet();

        if (!instanceInitialized) {
            initServlet(instance);
        }

        if (isJspServlet) {
            StringBuilder oname = new StringBuilder(getDomain());

            oname.append(":type=JspMonitor");

            oname.append(getWebModuleKeyProperties());

            oname.append(",name=");
            oname.append(getName());

            oname.append(getJ2EEKeyProperties());

            try {
                jspMonitorON = new ObjectName(oname.toString());
                Registry.getRegistry(nullnull).registerComponent(instance, jspMonitorON, null);
            } catch (Exception ex) {
                log.warn(sm.getString("standardWrapper.jspMonitorError", instance));
            }
        }
    }


    /**
     * Load and initialize an instance of this servlet, if there is not already an 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.
     *
     * @return the loaded Servlet instance
     *
     * @throws ServletException for a Servlet load error
     */

    public synchronized Servlet loadServlet() throws ServletException {

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

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

        Servlet servlet;
        try {
            long t1 = System.currentTimeMillis();
            // Complain if no servlet class has been specified
            if (servletClass == null) {
                unavailable(null);
                throw new ServletException(sm.getString("standardWrapper.notClass", getName()));
            }

            InstanceManager instanceManager = ((StandardContext) getParent()).getInstanceManager();
            try {
                servlet = (Servlet) instanceManager.newInstance(servletClass);
            } catch (ClassCastException e) {
                unavailable(null);
                // Restore the context ClassLoader
                throw new ServletException(sm.getString("standardWrapper.notServlet", servletClass), e);
            } catch (Throwable e) {
                e = ExceptionUtils.unwrapInvocationTargetException(e);
                ExceptionUtils.handleThrowable(e);
                unavailable(null);

                // Added extra log statement for Bugzilla 36630:
                // https://bz.apache.org/bugzilla/show_bug.cgi?id=36630
                if (log.isDebugEnabled()) {
                    log.debug(sm.getString("standardWrapper.instantiate", servletClass), e);
                }

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

            if (multipartConfigElement == null) {
                MultipartConfig annotation = servlet.getClass().getAnnotation(MultipartConfig.class);
                if (annotation != null) {
                    multipartConfigElement = new MultipartConfigElement(annotation);
                }
            }

            // Special handling for ContainerServlet instances
            // Note: The InstanceManager checks if the application is permitted
            // to load ContainerServlets
            if (servlet instanceof ContainerServlet) {
                ((ContainerServlet) servlet).setWrapper(this);
            }

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

            initServlet(servlet);

            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;

    }


    private synchronized void initServlet(Servlet servlet) throws ServletException {

        if (instanceInitialized) {
            return;
        }

        // Call the initialization method of this servlet
        try {
            if (Globals.IS_SECURITY_ENABLED) {
                boolean success = false;
                try {
                    Object[] args = new Object[] { facade };
                    SecurityUtil.doAsPrivilege("init", servlet, classType, args);
                    success = true;
                } finally {
                    if (!success) {
                        // destroy() will not be called, thus clear the reference now
                        SecurityUtil.remove(servlet);
                    }
                }
            } else {
                servlet.init(facade);
            }

            instanceInitialized = true;
        } catch (UnavailableException f) {
            unavailable(f);
            throw f;
        } catch (ServletException f) {
            // If the servlet wanted to be unavailable it would have
            // said so, so do not call unavailable(null).
            throw f;
        } catch (Throwable f) {
            ExceptionUtils.handleThrowable(f);
            getServletContext().log(sm.getString("standardWrapper.initException", getName()), 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);
        }
    }

    /**
     * Remove the specified initialization parameter from this servlet.
     *
     * @param name Name of the initialization parameter to remove
     */

    @Override
    public void removeInitParameter(String name) {

        parametersLock.writeLock().lock();
        try {
            parameters.remove(name);
        } finally {
            parametersLock.writeLock().unlock();
        }
        fireContainerEvent("removeInitParameter", name);

    }


    /**
     * Remove a mapping associated with the wrapper.
     *
     * @param mapping The pattern to remove
     */

    @Override
    public void removeMapping(String mapping) {

        mappingsLock.writeLock().lock();
        try {
            mappings.remove(mapping);
        } finally {
            mappingsLock.writeLock().unlock();
        }
        if (parent.getState().equals(LifecycleState.STARTED)) {
            fireContainerEvent(REMOVE_MAPPING_EVENT, 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) {

        referencesLock.writeLock().lock();
        try {
            references.remove(name);
        } finally {
            referencesLock.writeLock().unlock();
        }
        fireContainerEvent("removeSecurityReference", name);

    }


    /**
     * 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) {
        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
     */

    @Override
    public synchronized void unload() throws ServletException {

        // Nothing to do if we have never loaded the instance
        if (instance == null) {
            return;
        }
        unloading = true;

        // Loaf a while if the current instance is allocated
        if (countAllocated.get() > 0) {
            int nRetries = 0;
            long delay = unloadDelay / 20;
            while ((nRetries < 21) && (countAllocated.get() > 0)) {
                if ((nRetries % 10) == 0) {
                    log.info(sm.getString("standardWrapper.waiting", countAllocated.toString(), getName()));
                }
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                    // Ignore
                }
                nRetries++;
            }
        }

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

            // Call the servlet destroy() method
            try {
                if (Globals.IS_SECURITY_ENABLED) {
                    try {
                        SecurityUtil.doAsPrivilege("destroy", instance);
                    } finally {
                        SecurityUtil.remove(instance);
                    }
                } else {
                    instance.destroy();
                }

            } catch (Throwable t) {
                t = ExceptionUtils.unwrapInvocationTargetException(t);
                ExceptionUtils.handleThrowable(t);
                fireContainerEvent("unload"this);
                unloading = false;
                throw new ServletException(sm.getString("standardWrapper.destroyException", getName()), t);
            } finally {
                // Annotation processing
                if (!((Context) getParent()).getIgnoreAnnotations()) {
                    try {
                        ((Context) getParent()).getInstanceManager().destroyInstance(instance);
                    } catch (Throwable t) {
                        ExceptionUtils.handleThrowable(t);
                        log.error(sm.getString("standardWrapper.destroyInstance", getName()), t);
                    }
                }
                // 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);
                        }
                    }
                }
                instance = null;
                instanceInitialized = false;
            }
        }

        // Deregister the destroyed instance
        instance = null;

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

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

    @Override
    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.
     */

    @Override
    public Enumeration<String> getInitParameterNames() {

        parametersLock.readLock().lock();
        try {
            return Collections.enumeration(parameters.keySet());
        } finally {
            parametersLock.readLock().unlock();
        }

    }


    /**
     * @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 getProcessingTime() {
        return swValve.getProcessingTime();
    }

    public long getMaxTime() {
        return swValve.getMaxTime();
    }

    public long getMinTime() {
        return swValve.getMinTime();
    }

    /**
     * Returns the number of requests processed by the wrapper.
     *
     * @return the number of requests processed by the wrapper.
     *
     * @deprecated The return type will change to long in Tomcat 11 onwards. Callers of this method should switch to
     *                 storing the result of calls to this method in a long value rather than an int.
     */

    @Deprecated
    public int getRequestCount() {
        return swValve.getRequestCount();
    }

    /**
     * Returns the number of requests processed by the wrapper that resulted in an error.
     *
     * @return the number of requests processed by the wrapper that resulted in an error.
     *
     * @deprecated The return type will change to long in Tomcat 11 onwards. Callers of this method should switch to
     *                 storing the result of calls to this method in a long value rather than an int.
     */

    @Deprecated
    public int getErrorCount() {
        return swValve.getErrorCount();
    }

    /**
     * Increment the error count used for monitoring.
     */

    @Override
    public void incrementErrorCount() {
        swValve.incrementErrorCount();
    }

    public long getLoadTime() {
        return loadTime;
    }

    public int getClassLoadTime() {
        return classLoadTime;
    }

    @Override
    public MultipartConfigElement getMultipartConfigElement() {
        return multipartConfigElement;
    }

    @Override
    public void setMultipartConfigElement(MultipartConfigElement multipartConfigElement) {
        this.multipartConfigElement = multipartConfigElement;
    }

    @Override
    public boolean isAsyncSupported() {
        return asyncSupported;
    }

    @Override
    public void setAsyncSupported(boolean asyncSupported) {
        this.asyncSupported = asyncSupported;
    }

    @Override
    public boolean isEnabled() {
        return enabled;
    }

    @Override
    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    // -------------------------------------------------------- Package Methods


    // -------------------------------------------------------- protected Methods


    protected 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 and implement the requirements of
     * {@link org.apache.catalina.util.LifecycleBase#startInternal()}.
     *
     * @exception LifecycleException if this component detects a fatal error that prevents this component from being
     *                                   used
     */

    @Override
    protected synchronized void startInternal() throws LifecycleException {

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

        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 and implement the requirements of
     * {@link org.apache.catalina.util.LifecycleBase#stopInternal()}.
     *
     * @exception LifecycleException if this component detects a fatal error that prevents this component from being
     *                                   used
     */

    @Override
    protected synchronized void stopInternal() throws LifecycleException {

        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.stopInternal();

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

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

    }


    @Override
    protected String getObjectNameKeyProperties() {

        StringBuilder keyProperties = new StringBuilder("j2eeType=Servlet");

        keyProperties.append(getWebModuleKeyProperties());

        keyProperties.append(",name=");

        String name = getName();
        if (Util.objectNameValueNeedsQuote(name)) {
            name = ObjectName.quote(name);
        }
        keyProperties.append(name);

        keyProperties.append(getJ2EEKeyProperties());

        return keyProperties.toString();
    }


    private String getWebModuleKeyProperties() {

        StringBuilder keyProperties = new StringBuilder(",WebModule=//");
        String hostName = getParent().getParent().getName();
        if (hostName == null) {
            keyProperties.append("DEFAULT");
        } else {
            keyProperties.append(hostName);
        }

        String contextName = getParent().getName();
        if (!contextName.startsWith("/")) {
            keyProperties.append('/');
        }
        keyProperties.append(contextName);

        return keyProperties.toString();
    }

    private String getJ2EEKeyProperties() {

        StringBuilder keyProperties = new StringBuilder(",J2EEApplication=");

        StandardContext ctx = null;
        if (parent instanceof StandardContext) {
            ctx = (StandardContext) getParent();
        }

        if (ctx == null) {
            keyProperties.append("none");
        } else {
            keyProperties.append(ctx.getJ2EEApplication());
        }
        keyProperties.append(",J2EEServer=");
        if (ctx == null) {
            keyProperties.append("none");
        } else {
            keyProperties.append(ctx.getJ2EEServer());
        }

        return keyProperties.toString();
    }


    /**
     * Remove a JMX notificationListener
     *
     * @see javax.management.NotificationEmitter#removeNotificationListener(javax.management.NotificationListener,
     *          javax.management.NotificationFilter, java.lang.Object)
     */

    @Override
    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object object)
            throws ListenerNotFoundException {
        broadcaster.removeNotificationListener(listener, filter, object);
    }

    protected MBeanNotificationInfo[] notificationInfo;

    /**
     * Get JMX Broadcaster Info
     *
     * @see javax.management.NotificationBroadcaster#getNotificationInfo()
     */

    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {
        // FIXME: we not send j2ee.state.failed
        // FIXME: we not send j2ee.attribute.changed
        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)
     */

    @Override
    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)
     */

    @Override
    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
        broadcaster.removeNotificationListener(listener);
    }
}

Messung V0.5
C=93 H=93 G=92

¤ Dauer der Verarbeitung: 0.8 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.