Package winstone

Source Code of winstone.ServletConfiguration

/*
* Copyright 2003-2006 Rick Knowles <winstone-devel at lists sourceforge net>
* Distributed under the terms of either:
* - the common development and distribution license (CDDL), v1.0; or
* - the GNU Lesser General Public License, v2.1 or later
*/
package winstone;

import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Map;

import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServletResponse;

import org.w3c.dom.Node;

/**
* This is the one that keeps a specific servlet instance's config, as well as
* holding the instance itself.
*
* @author <a href="mailto:rick_knowles@hotmail.com">Rick Knowles</a>
* @version $Id: ServletConfiguration.java,v 1.16 2007/04/23 02:55:35 rickknowles Exp $
*/
public class ServletConfiguration implements javax.servlet.ServletConfig,
        Comparable {
   
    static final String ELEM_NAME = "servlet-name";
    static final String ELEM_DISPLAY_NAME = "display-name";
    static final String ELEM_CLASS = "servlet-class";
    static final String ELEM_JSP_FILE = "jsp-file";
    static final String ELEM_DESCRIPTION = "description";
    static final String ELEM_INIT_PARAM = "init-param";
    static final String ELEM_INIT_PARAM_NAME = "param-name";
    static final String ELEM_INIT_PARAM_VALUE = "param-value";
    static final String ELEM_LOAD_ON_STARTUP = "load-on-startup";
    static final String ELEM_RUN_AS = "run-as";
    static final String ELEM_SECURITY_ROLE_REF = "security-role-ref";
    static final String ELEM_ROLE_NAME = "role-name";
    static final String ELEM_ROLE_LINK = "role-link";
   
    final String JSP_FILE = "org.apache.catalina.jsp_file";

    private String servletName;
    private String classFile;
    private Servlet instance;
    private Map initParameters;
    private WebAppConfiguration webAppConfig;
    private int loadOnStartup;
    private String jspFile;
//    private String runAsRole;
    private Map securityRoleRefs;
    private Object servletSemaphore = new Boolean(true);
    private boolean isSingleThreadModel = false;
    private boolean unavailable = false;
    private Throwable unavailableException = null;
   
    protected ServletConfiguration(WebAppConfiguration webAppConfig) {
        this.webAppConfig = webAppConfig;
        this.initParameters = new Hashtable();
        this.loadOnStartup = -1;
        this.securityRoleRefs = new Hashtable();
    }

    public ServletConfiguration(WebAppConfiguration webAppConfig, String servletName,
            String className, Map initParams, int loadOnStartup) {
        this(webAppConfig);
        if (initParams != null)
            this.initParameters.putAll(initParams);
        this.servletName = servletName;
        this.classFile = className;
        this.jspFile = null;
        this.loadOnStartup = loadOnStartup;
    }

    public ServletConfiguration(WebAppConfiguration webAppConfig, Node elm) {
        this(webAppConfig);

        // Parse the web.xml file entry
        for (int n = 0; n < elm.getChildNodes().getLength(); n++) {
            Node child = elm.getChildNodes().item(n);
            if (child.getNodeType() != Node.ELEMENT_NODE)
                continue;
            String nodeName = child.getNodeName();

            // Construct the servlet instances
            if (nodeName.equals(ELEM_NAME))
                this.servletName = WebAppConfiguration.getTextFromNode(child);
            else if (nodeName.equals(ELEM_CLASS))
                this.classFile = WebAppConfiguration.getTextFromNode(child);
            else if (nodeName.equals(ELEM_JSP_FILE))
                this.jspFile = WebAppConfiguration.getTextFromNode(child);
            else if (nodeName.equals(ELEM_LOAD_ON_STARTUP)) {
                String index = child.getFirstChild() == null ? "-1" :
                    WebAppConfiguration.getTextFromNode(child);
                this.loadOnStartup = Integer.parseInt(index);
            } else if (nodeName.equals(ELEM_INIT_PARAM)) {
                String paramName = "";
                String paramValue = "";
                for (int k = 0; k < child.getChildNodes().getLength(); k++) {
                    Node paramNode = child.getChildNodes().item(k);
                    if (paramNode.getNodeType() != Node.ELEMENT_NODE)
                        continue;
                    else if (paramNode.getNodeName().equals(ELEM_INIT_PARAM_NAME))
                        paramName = WebAppConfiguration.getTextFromNode(paramNode);
                    else if (paramNode.getNodeName().equals(ELEM_INIT_PARAM_VALUE))
                        paramValue = WebAppConfiguration.getTextFromNode(paramNode);
                }
                if (!paramName.equals("")) {
                    this.initParameters.put(paramName, paramValue);
                }
            } else if (nodeName.equals(ELEM_RUN_AS)) {
                for (int m = 0; m < child.getChildNodes().getLength(); m++) {
                    Node roleElm = child.getChildNodes().item(m);
                    if ((roleElm.getNodeType() == Node.ELEMENT_NODE)
                            && (roleElm.getNodeName().equals(ELEM_ROLE_NAME))) {
//                        this.runAsRole = WebAppConfiguration.getTextFromNode(roleElm); // not used
                    }
                }
            } else if (nodeName.equals(ELEM_SECURITY_ROLE_REF)) {
                String name = "";
                String link = "";
                for (int k = 0; k < child.getChildNodes().getLength(); k++) {
                    Node roleRefNode = child.getChildNodes().item(k);
                    if (roleRefNode.getNodeType() != Node.ELEMENT_NODE)
                        continue;
                    else if (roleRefNode.getNodeName().equals(ELEM_ROLE_NAME))
                        name = WebAppConfiguration.getTextFromNode(roleRefNode);
                    else if (roleRefNode.getNodeName().equals(ELEM_ROLE_LINK))
                        link = WebAppConfiguration.getTextFromNode(roleRefNode);
                }
                if (!name.equals("") && !link.equals(""))
                    this.initParameters.put(name, link);
            }
        }

        if ((this.jspFile != null) && (this.classFile == null)) {
            this.classFile = WebAppConfiguration.JSP_SERVLET_CLASS;
            WebAppConfiguration.addJspServletParams(this.initParameters);
        }
        Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES,
                "ServletConfiguration.DeployedInstance", new String[] {
                        this.servletName, this.classFile });
    }
   
    public void ensureInitialization() {
       
        if (this.instance != null) {
            return; // already init'd
        }
       
        synchronized (this.servletSemaphore) {

            if (this.instance != null) {
                return; // already init'd
            }
           
            // Check if we were decommissioned while blocking
            if (this.unavailableException != null) {
                return;
            }
           
            // If no instance, class load, then call init()
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
           
            Servlet newInstance = null;
            Throwable otherError = null;
            try {
                Class servletClass = Class.forName(classFile, true, this.webAppConfig.getLoader());
                newInstance = (Servlet) servletClass.newInstance();
                this.isSingleThreadModel = Class.forName("javax.servlet.SingleThreadModel").isInstance(newInstance);
               
                // Initialise with the correct classloader
                Logger.log(Logger.DEBUG, Launcher.RESOURCES, "ServletConfiguration.init", this.servletName);
                newInstance.init(this);
                this.instance = newInstance;
            } catch (ClassNotFoundException err) {
                Logger.log(Logger.WARNING, Launcher.RESOURCES,
                        "ServletConfiguration.ClassLoadError", this.classFile, err);
                setUnavailable(newInstance);
                this.unavailableException = err;
            } catch (IllegalAccessException err) {
                Logger.log(Logger.WARNING, Launcher.RESOURCES,
                        "ServletConfiguration.ClassLoadError", this.classFile, err);
                setUnavailable(newInstance);
                this.unavailableException = err;
            } catch (InstantiationException err) {
                Logger.log(Logger.WARNING, Launcher.RESOURCES,
                        "ServletConfiguration.ClassLoadError", this.classFile, err);
                setUnavailable(newInstance);
                this.unavailableException = err;
            } catch (ServletException err) {
                Logger.log(Logger.WARNING, Launcher.RESOURCES,
                        "ServletConfiguration.InitError", this.servletName, err);
                this.instance = null; // so that we don't call the destroy method
                setUnavailable(newInstance);
                this.unavailableException = err;
            } catch (RuntimeException err) {
                otherError = err;
                throw err;
            } catch (Error err) {
                otherError = err;
                throw err;
            } finally {
                Thread.currentThread().setContextClassLoader(cl);
                if ((otherError == null) && (this.unavailableException == null)) {
                    this.instance = newInstance;
                }
            }
        }
        return;
    }

    public void execute(ServletRequest request, ServletResponse response, String requestURI)
            throws ServletException, IOException {
       
        ensureInitialization();
       
        // If init failed, return 500 error
        if (this.unavailable) {
//            ((HttpServletResponse) response).sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
//                    resources.getString("StaticResourceServlet.PathNotFound", requestURI));
            RequestDispatcher rd = this.webAppConfig.getErrorDispatcherByClass(
                    this.unavailableException);
            rd.forward(request, response);
            return;
        }
       
        if (this.jspFile != null)
            request.setAttribute(JSP_FILE, this.jspFile);

        ClassLoader cl = Thread.currentThread().getContextClassLoader();
        Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());

        try {
            if (this.isSingleThreadModel) {
                synchronized (this) {
                    this.instance.service(request, response);
                }
            } else
                this.instance.service(request, response);
        } catch (UnavailableException err) {
            // catch locally and rethrow as a new ServletException, so
            // we only invalidate the throwing servlet
            setUnavailable(this.instance);
            ((HttpServletResponse) response).sendError(HttpServletResponse.SC_NOT_FOUND,
                    Launcher.RESOURCES.getString("StaticResourceServlet.PathNotFound", requestURI));
//            throw new ServletException(resources.getString(
//                    "RequestDispatcher.ForwardError"), err);
        } finally {
            Thread.currentThread().setContextClassLoader(cl);
        }
    }
   
    public int getLoadOnStartup() {
        return this.loadOnStartup;
    }

    public String getInitParameter(String name) {
        return (String) this.initParameters.get(name);
    }

    public Enumeration getInitParameterNames() {
        return Collections.enumeration(this.initParameters.keySet());
    }

    public ServletContext getServletContext() {
        return this.webAppConfig;
    }

    public String getServletName() {
        return this.servletName;
    }

    public Map getSecurityRoleRefs() {
        return this.securityRoleRefs;
    }

    /**
     * This was included so that the servlet instances could be sorted on their
     * loadOnStartup values. Otherwise used.
     */
    public int compareTo(Object objTwo) {
        Integer one = new Integer(this.loadOnStartup);
        Integer two = new Integer(((ServletConfiguration) objTwo).loadOnStartup);
        return one.compareTo(two);
    }

    /**
     * Called when it's time for the container to shut this servlet down.
     */
    public void destroy() {
        synchronized (this.servletSemaphore) {
            setUnavailable(this.instance);
        }
    }

    protected void setUnavailable(Servlet unavailableServlet) {
       
        this.unavailable = true;
        if (unavailableServlet != null) {
            Logger.log(Logger.DEBUG, Launcher.RESOURCES,
                    "ServletConfiguration.destroy", this.servletName);
            ClassLoader cl = Thread.currentThread().getContextClassLoader();
            Thread.currentThread().setContextClassLoader(this.webAppConfig.getLoader());
            try {
                unavailableServlet.destroy();
            } finally {
                Thread.currentThread().setContextClassLoader(cl);
                this.instance = null;
            }
        }
       
        // remove from webapp
        this.webAppConfig.removeServletConfigurationAndMappings(this);
    }
}
TOP

Related Classes of winstone.ServletConfiguration

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.