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 + -
显示快捷键?