servletwrapper.java

来自「很棒的web服务器源代码」· Java 代码 · 共 990 行 · 第 1/2 页

JAVA
990
字号
// ServletWrapper.java// $Id: ServletWrapper.java,v 1.72 2003/02/18 16:17:53 ylafon Exp $// (c) COPYRIGHT MIT and INRIA, 1996.// Please first read the full copyright statement in file COPYRIGHT.htmlpackage org.w3c.jigsaw.servlet;import java.io.File;import java.io.IOException;import java.io.OutputStream;import java.io.PrintStream;import java.io.PrintWriter;import java.util.Enumeration;import java.util.LinkedList;import java.util.NoSuchElementException;import javax.servlet.Servlet;import javax.servlet.ServletConfig;import javax.servlet.ServletContext;import javax.servlet.ServletException;import javax.servlet.SingleThreadModel;import javax.servlet.UnavailableException;import org.w3c.tools.timers.EventHandler;import org.w3c.tools.timers.EventManager;import org.w3c.util.ArrayDictionary;import org.w3c.util.EmptyEnumeration;import org.w3c.util.ThreadCache;import org.w3c.jigsaw.http.Reply;import org.w3c.jigsaw.http.Request;import org.w3c.jigsaw.http.httpd;import org.w3c.tools.resources.Attribute;import org.w3c.tools.resources.AttributeHolder;import org.w3c.tools.resources.AttributeRegistry;import org.w3c.tools.resources.FramedResource;import org.w3c.tools.resources.InvalidResourceException;import org.w3c.tools.resources.IntegerAttribute;import org.w3c.tools.resources.LongAttribute;import org.w3c.tools.resources.ObjectAttribute;import org.w3c.tools.resources.PropertiesAttribute;import org.w3c.tools.resources.Resource;import org.w3c.tools.resources.ResourceReference;import org.w3c.tools.resources.ServerInterface;import org.w3c.tools.resources.StringAttribute;import org.w3c.www.http.HTTP;/** * @author Alexandre Rafalovitch <alex@access.com.au> * @author Anselm Baird-Smith <abaird@w3.org> * @author Benoit Mahe <bmahe@w3.org> */public class ServletWrapper extends FramedResource     implements ServletConfig{    static ThreadCache threadCache = null;    static {	threadCache = new ThreadCache("servlet-runner");	threadCache.setCachesize(5);	threadCache.setGrowAsNeeded(true);	threadCache.setIdleTimeout(86400000);	threadCache.initialize();    }    protected class TimeoutManager implements EventHandler {	private Object timer     = null;	private httpd  server    = null;	/**	 * Handle timer events. 	 * @param data The timer closure.	 * @param time The absolute time at which the event was triggered.	 * @see org.w3c.tools.timers.EventManager	 * @see org.w3c.tools.timers.EventHandler	 */	public void handleTimerEvent(Object data, long time) {	    synchronized (this) {		timer = null;	    }            // FIXME, each servlet instance available should have its 	    // individual timeout manager.            // Thus, resources could be released as required. This mechanism	    // would opt for a more fine grained servlet instance management.	    destroyServlet();	}	private synchronized void setTimer(long ms) {	    if ( timer != null ) {		server.timer.recallTimer(timer) ;		timer = null ;	    }	    timer = server.timer.registerTimer(ms, this, null);	}	protected void restart() {	    start();	}	protected void start() {	    long timeout = getServletTimeout();	    if (timeout != -1)		setTimer(timeout);	}	protected synchronized void stop() {	    if ( timer != null ) {		server.timer.recallTimer(timer);		timer = null;	    }	}		TimeoutManager(httpd server) {	    this.server = server;	}    }    // used to pass the runner as a state    public static final String RUNNER = "org.w3c.jigsaw.servlet.runner";    // used to signal the end of the servlet in the Reply    public static final String ENDED = "org.w3c.jigsaw.servlet.ended";    protected TimeoutManager timeoutManager = null;    // protected int connections = 0;    protected final static boolean debug = false;    /**     * Attributes index - The servlet class name.     */    protected static int ATTR_SERVLET_CLASS = -1 ;    /**     * Attributes index - The servlet timeout     */    protected static int ATTR_SERVLET_TIMEOUT = -1 ;    /**     * Attributes index - The servlet maxinstances for single thread model     * servlet instance pool size limitation, tk, 20.10.2001     */    protected static int ATTR_SERVLET_INSTANCEMAX = -1 ;    /**     * Attribute index - The init parameters for that servlet.     */    protected static int ATTR_PARAMETERS = 1;    /**     * Attribute index - Our parent-inherited servlet context.     */    protected static int ATTR_SERVLET_CONTEXT = -1;    /**     * Attribute index - Our parent-inherited session context.     */    protected static int ATTR_SESSION_CONTEXT = -1;    static {	Attribute a   = null ;	Class     cls = null ;	try {	    cls = Class.forName("org.w3c.jigsaw.servlet.ServletWrapper") ;	} catch (Exception ex) {	    ex.printStackTrace();	    System.exit(0);	}	// The servlet class attribute.	a = new StringAttribute("servlet-class"				, null				, Attribute.EDITABLE | Attribute.MANDATORY) ;	ATTR_SERVLET_CLASS = AttributeRegistry.registerAttribute(cls, a) ;	// This servlet init parameters	a = new PropertiesAttribute("servlet-parameters"				    , null				    , Attribute.EDITABLE);	ATTR_PARAMETERS = AttributeRegistry.registerAttribute(cls, a);	// Our servlet context:	a = new ObjectAttribute("servlet-context",				"org.w3c.jigsaw.servlet.JigsawServletContext",				null,				Attribute.DONTSAVE);	ATTR_SERVLET_CONTEXT = AttributeRegistry.registerAttribute(cls, a);	// Our session context:	a = new ObjectAttribute("session-context",			     "org.w3c.jigsaw.servlet.JigsawHttpSessionContext",				null,				Attribute.DONTSAVE);	ATTR_SESSION_CONTEXT = AttributeRegistry.registerAttribute(cls, a);	// The servlet timeout:	a = new LongAttribute("servlet-timeout",			      null,			      Attribute.EDITABLE);	ATTR_SERVLET_TIMEOUT = AttributeRegistry.registerAttribute(cls, a);	// The servlet maxinstances:	a = new IntegerAttribute("servlet-instancemax",				 null,				 Attribute.EDITABLE);	ATTR_SERVLET_INSTANCEMAX = AttributeRegistry.registerAttribute(cls, a);    }    /**      * Using a limited pool of servlet instances instead of a single      * instance, tk, 22.10.2001     * protected Servlet servlet = null;     */    protected ServletPool servletPool = new ServletPool();         /**     * Is our servler initialized ?     */    protected boolean inited = false;    /**     * The Path where we can find the servlet class file.     */    public File getServletDirectory() {	ResourceReference rr = getParent();	if (rr != null) {	    try {		Resource parent = rr.lock();		if (parent.definesAttribute("directory"))		    return (File) parent.getValue("directory", null);	    } catch(InvalidResourceException ex) {		ex.printStackTrace();	    } finally {		rr.unlock();	    }	}	return null;    }    /**     * Servlet stub implementation - Get an init parameter value.     */    public synchronized String getInitParameter(String string) {	ArrayDictionary d = getServletParameters();	String          v = (d != null) ? (String) d.get(string) : null;	return v;    }    /**     * Servlet stub implementation - Get all init parameters.     */    public synchronized Enumeration getInitParameterNames() {	// Convert init parameters to hashtable:	ArrayDictionary d = getServletParameters();	return (d != null) ? d.keys() : new EmptyEnumeration();    }    /**     * Servlet stub implementation - Get that servlet context.     */    public ServletContext getServletContext() { 	ServletContext ctxt = 	    (ServletContext) getValue(ATTR_SERVLET_CONTEXT, null);	return ctxt;    }    public JigsawHttpSessionContext getSessionContext() {	return (JigsawHttpSessionContext) getValue(ATTR_SESSION_CONTEXT, null);    }    protected long getServletTimeout() {	long timeout = getLong(ATTR_SERVLET_TIMEOUT, 0);	if (timeout == 0) {	    JigsawServletContext ctxt = 		(JigsawServletContext) getServletContext();	    timeout = ctxt.getServletTimeout();	}	return timeout;    }    protected int getInstanceMax() {         // added for single thread model 	// servlet instance pool size limitation, tk, 20.10.2001	int instancemax = getInt(ATTR_SERVLET_INSTANCEMAX, 1);	if (instancemax < 1) {	    JigsawServletContext ctxt = 		(JigsawServletContext) getServletContext();	    instancemax = ctxt.getServletInstanceMax();	}        if (instancemax < 1) {	    return 1;        } else {	    return instancemax;	}    }    protected void invalidateAllSession() {	if (debug) {	    System.out.println("Invalidate All Session...");	}	JigsawHttpSessionContext ctxt = getSessionContext();	Enumeration enum = ctxt.getIds();	while (enum.hasMoreElements()) {	    ctxt.getSession((String)enum.nextElement()).invalidate();	}    }    /**     * Check the servlet class, ans try to initialize it.     * @exception ClassNotFoundException if servlet class can't be found.     * @exception ServletException if servlet can't be initialized.     */    protected void checkServlet() 	throws ClassNotFoundException, ServletException	{	    synchronized(servletPool) {                 // tk, 20.10.2001, synchronized loading is necessary at 		// least for the non-SingleThreadModel		boolean classmodified = 		    getLocalServletLoader().classChanged(getServletClass());		if ((!inited) ||		    classmodified ||		    // (servlet.getClass() != 		    //    getLocalServletLoader().loadClass(getServletClass()))		    (servletPool.getLoadedClass() != 		        getLocalServletLoader().loadClass(getServletClass()))		    ) {		    inited = launchServlet();		}	    }	}    protected boolean isInited() {	return inited;    }    /**     * Check and eventually load the servlet we are wrapping.     * This method was added for replacing getServlet() during access checks     * in order to do perform checks without accessing a servlet instance.     * @return true if and only if the sevlet has successfully been loaded     */    public boolean isServletLoaded() {	try {	    checkServlet();	} catch (Exception ex) {	    if (debug) {		ex.printStackTrace();	    }	}	return inited;    }        /**     * Helper class for managing a limited pool of servlet instances,      * tk, 20.10.2001     * For the SingleThreadModel instance are created as required and      * retained up to a specified limit.     * For the non-SingleThreadModel one instance only is created      * (in accordance with the servlet spec).     * The first instance initializes the pool with its pars-pro-toto     * class attributes.     */    private class ServletPool {                // maximum pool size        private int maximum = 1;                // current pool capacity        private int capacity = 0;                // current pool usage level        private int usage = 0;                // list of servlet instances        private Servlet[] pool = null;        // indicator for SingleThreadModel        private boolean singleThreaded = false;                // common class of the servlet pool        private Class loadedClass = null;                /**         * method for exporting the class common to all loaded servlet 	 * instances         * @return common loaded servlet class         */        protected Class getLoadedClass() {            return loadedClass;        }                /**         * method for adding a fresh servlet instance to the pool 	 * (using external synchronization)         * @param servlet the instance to be added to the pool         */        protected void add(Servlet servlet) {            if ((pool == null)||(loadedClass == null)) {		singleThreaded = (servlet instanceof SingleThreadModel);		if (singleThreaded) maximum = getInstanceMax(); 		else maximum = 1;		loadedClass = servlet.getClass();		pool = new Servlet[maximum];            }            if (capacity < maximum) {		pool[capacity++] = servlet;            }        }                /**         * non-blocking method for removing a servlet instance from the	 * pool (using external synchronization)         * @return a removed servlet instance or null if the pool is empty         */        protected Servlet remove() {	    if (capacity > usage) {                Servlet servlet = pool[--capacity];                if (capacity < 1) {		    pool = null;		    loadedClass = null;		    singleThreaded = false;		    maximum = 1;                }                return servlet;	    }	    else return null;        }                /**         * blocking method for accessing a servlet instance from the pool         * @exception ServletException thrown if the pool is not properly	 * initialized         */        protected synchronized Servlet takeServlet() throws ServletException {            if ((!inited)||(capacity < 1)||		(pool == null)||(loadedClass == null)) {		throw new ServletException("Accessing servlet without"+					   " initialization.");            }            if (singleThreaded) {		try {		    while (true) {			if (usage < capacity) {			    return pool[usage++];			} else {			    if (capacity < maximum) {				if (launchServlet(loadedClass)) {				    notifyAll();				    Thread.currentThread().yield();                                     // give previous waiters a chance				} else {				    wait();				}			    } else {				wait();			    }			}		    }		}		catch (InterruptedException ex) {		    throw new ServletException("Waiting for a free servlet"+					       " instance interrupted.");		}            } else {		// One instance only is used in non single thread case 		// (cf. servlet api for details)		usage++;		return pool[0];            }        }                /**         * method for releasing a servlet instance into the pool after work         * @param servlet the instance to be returned to the pool         * @exception ServletException thrown if pool is not properly 	 * initialized         */        protected synchronized void releaseServlet(Servlet servlet) 	    throws ServletException 	{            if ((!inited)||(capacity < 1)||(pool == null)||		   (loadedClass == null)) {		throw new ServletException("Releasing servlet without"+					   " initialization.");            }            if (usage > 0) {		if (singleThreaded) {		    pool[--usage] = servlet;		    notifyAll();		} else {		    // In this case the servlet instance is shared, i.e. 		    // we have a counting semaphore only.		    usage--;		}            } else {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?