servletwrapper.java

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

JAVA
990
字号
		throw new ServletException("Incorrect servlet release"+					   " occurred.");	    }        }                /**         * method for referencing a servlet instance of the pool         * This method was added for backward compatibility in order to 	 * support the deprecated getServlet() method,         * which is structurally not applicable to the pool mechanism, i.e. 	 * it always returns null in         * case of the SingleThreadModel (in accordance with the current 	 * servlet spec)         * @return a servlet reference or null         */        protected synchronized Servlet getRepresentative() {            if ((!inited)||(capacity < 1)||(loadedClass == null)) {		return null;	    } else {		if (singleThreaded) {		    // FIXME, here we could also return pool[0],		    // which is defined but probably taken.		    // However, using pool[0] in a normal manner might 		    // cause strange behavior 		    // due to its single threaded design aspect.		    return null;		} else {		    return pool[0];		}            }        }    }            private class ServletRunner implements Runnable {	Servlet srServlet = null;	JigsawHttpServletRequest srReq = null;	JigsawHttpServletResponse srResp = null;	public void run() {	    // name modified in order to keep track of who is running	    // which instance, tk, 21.10.2001	    Thread t = Thread.currentThread();	    String ts = t.getName();	    t.setName("ServletRunner<" + ts +":"+ srServlet.hashCode() + ">");	    // synchronization object	    Object o = null;	    try {		Reply reply = srResp.getReply();		if (reply != null) {		    o = reply.getState(JigsawHttpServletResponse.MONITOR);		}		srServlet.service(srReq , srResp);                try {		    servletPool.releaseServlet(srServlet);		} finally {		    srServlet = null;                }		srResp.flushStream(true);	    } catch (UnavailableException uex) {		String message = null;		srResp.setStatus(HTTP.SERVICE_UNAVAILABLE);		if (uex.isPermanent()) {		    message = "<h2>The servlet is permanently "+			"unavailable :</h2>"+			"Details: <b>"+uex.getMessage()+"</b>";		    try {			srResp.sendError(HTTP.SERVICE_UNAVAILABLE, message);		    } catch (IOException ioex) {			// not much to do now...		    }		} else {		    int delay = uex.getUnavailableSeconds();		    if (delay > 0) {			message = "<h2>The servlet is temporarily "+			    "unavailable :</h2>"+			    "Delay : "+delay+			    " seconds<br><br>Details: <b>"+			    uex.getMessage()+"</b>";			srResp.getReply().setRetryAfter(delay);			try {			    srResp.sendError(HTTP.SERVICE_UNAVAILABLE,message);			} catch (IOException ioex) {			    // not much to do now...			}		    } else {			message = "<h2>The servlet is temporarily "+			    "unavailable :</h2>"+			    "Details: <b>"+uex.getMessage()+			    "</b>";			try {					    srResp.sendError(HTTP.SERVICE_UNAVAILABLE,message);			} catch (IOException ioex) {			    // not much to do now...			}		    }		}	    } catch (Exception ex) {		if (debug) {		    ex.printStackTrace();		}		if (srResp.isStreamObtained()) {		    try {			srResp.flushStream(false);			OutputStream os = srResp.getRawOutputStream();			if (os != null) {			    synchronized (os) {				PrintWriter pw = new PrintWriter(os);				ex.printStackTrace(pw);				pw.flush();			    }			}			srResp.flushStream(true);		    } catch (IOException ioex) {}		} else {		    try {			srResp.sendError(HTTP.INTERNAL_SERVER_ERROR,					 "Servlet has thrown exception:" + 					 ex.toString());		    } catch (IOException ioex) {			// no stream to write on, fail silently		    }		}	    } finally {                if (srServlet != null) {		    try {			servletPool.releaseServlet(srServlet);		    }		    catch (ServletException ex) {			// ignore		    }                }		// release the monitor waiting for the end of the reply setup		if (o != null) {		    synchronized (o) {			o.notifyAll();		    }		}		// revert name to original value		t.setName(ts);		srServlet = null;		srReq = null;		// adds the END state		Reply r = srResp.getReply();		if (r != null) {		    r.setState(ENDED, new Object());		}		srResp = null;	    }	}	ServletRunner(Servlet servlet,		      JigsawHttpServletRequest request,		      JigsawHttpServletResponse response) {	    srServlet = servlet;	    srReq = request;	    srResp = response; 	}    }    protected void service(Request request, Reply reply)	throws ServletException, IOException	{	    JigsawHttpServletResponse jRes = null;	    JigsawHttpServletRequest jReq = null;	    /* modified due to servlet pooling, tk, 20.10.2001	       if (servlet instanceof SingleThreadModel) {	       synchronized (this) {	       jRes = new JigsawHttpServletResponse(request, reply);	       jReq = new JigsawHttpServletRequest(servlet, 	       request, 	       jRes,	       getSessionContext());	       jRes.setServletRequest(jReq);	       try {	       connections++;	       // FIXME we should reuse a thread rather than	       // reallocating one for every hit	       ServletRunner runner = new ServletRunner(servlet, jReq, jRes);	       reply.setState(RUNNER, runner);	       runner.start();	       } finally {	       connections--;	       }	       }	       } else {	    */	    jRes = new JigsawHttpServletResponse(request, reply);            Servlet servlet = servletPool.takeServlet();             // accessing a fresh or sharable instance, tk, 21.10.2001	    // jReq = new JigsawHttpServletRequest(servlet,	    JigsawServletContext jco = 		                    (JigsawServletContext) getServletContext();	    jReq = new JigsawHttpServletRequest(servlet, 						jco,						request, 						jRes,						getSessionContext());	    jRes.setServletRequest(jReq);	    // try {  	    //       connections++;	    // FIXME we should reuse a thread rather than	    // reallocating one for every hit	    // reallocating one for every hit	    ServletRunner runner = new ServletRunner(servlet, jReq, jRes);	    reply.setState(RUNNER, runner);	    threadCache.getThread(runner, true);//	    runner.start();	    // } finally {	    //     connections--;	    // }	    /* } */	    timeoutManager.restart();	}    /**     * Get the class name of the wrapped servlet.     * @return The class name for the servlet if attribute is defined.      * Otherwise the class name is deduced from the resource identifier.     */    public String getServletClass()	{	    String sclass =  getString(ATTR_SERVLET_CLASS, null);	    if (sclass == null) {		String ident = getIdentifier();		if (ident.endsWith(".class")) {		    sclass = ident;		}	    }	    return sclass;	}    /**     * Get the init parameters for our wrapped servlet.     * @return An ArrayDictionary instance if the attribute is defined,      * <strong>false</strong> otherwise.     */    public ArrayDictionary getServletParameters() {	return (ArrayDictionary) getValue(ATTR_PARAMETERS, null);    }    protected void setValueOfSuperClass(int idx, Object value) {	super.setValue(idx, value);    }    /**     * Catch assignements to the servlet class name attribute.     * <p>When a change to that attribute is detected, the servlet is     * automatically reinitialized.     */    public void setValue(int idx, Object value) {	super.setValue(idx, value);	if (((idx == ATTR_SERVLET_CLASS) && (value != null)) ||	    (idx == ATTR_PARAMETERS)) {	    try {                synchronized(servletPool) {                     // synchronization added, tk, 20.10.2001    		    inited = launchServlet();                }	    } catch (Exception ex) {		String msg = ("unable to set servlet class \""+			      getServletClass()+			      "\" : "+			      ex.getMessage());		getServer().errlog(msg);	    }	} if (idx == ATTR_SERVLET_TIMEOUT) {	    timeoutManager.restart();	}    }    /**     * Destroy the servlet we are wrapping.     */    protected void destroyServlet() {	// if ((servlet != null) && (connections < 1)) {	synchronized(servletPool) {	    Servlet servlet = servletPool.remove();	    while (servlet != null) {		servlet.destroy();		// servlet = null;		servlet = servletPool.remove();	    }	    inited = (servletPool.getLoadedClass() != null);	}	// }    }    /**     * Get the servlet we are wrapping.     * @return A servlet instance, if the servlet is alredy running,      * <strong>null</strong> otherwise.     */    public Servlet getServlet() {	try {	    checkServlet();	} catch (Exception ex) {	    if (debug)		ex.printStackTrace();	}	return servletPool.getRepresentative();    }        /**     * Initialize our servlet from the given (loaded) class.     * @param cls The servlet loaded main class.     * @return A boolean, <strong>true</strong> if servlet was successfully     * initialised, <strong>false</strong> otherwise.     * @exception ServletException if servlet can't be initialized.     */    protected boolean launchServlet(Class cls) 	throws ServletException	{	    if (debug) {		System.out.println("launching Servlet: "+getServletName());	    }	    Servlet servlet = null;	    try {		servlet = (Servlet) cls.newInstance();		servlet.init((ServletConfig) this);		timeoutManager.restart();	    } catch (IllegalAccessException ex) {		String msg = ("Illegal access during servlet instantiation, "+			      ex.getClass().getName()+": "+			      ex.getMessage());		if ( debug ) {		    ex.printStackTrace();		}		getServer().errlog(this, msg);		return false;	    } catch (InstantiationException iex) {		String msg = ("unable to instantiate servlet, "+			      iex.getClass().getName()+": "+			      iex.getMessage());		if ( debug ) {		    iex.printStackTrace();		}		getServer().errlog(this, msg);		return false;	    } catch (Exception oex) {		String msg = ("Error while loading servlet");		getServer().errlog(this, msg);		if ( debug ) {		    oex.printStackTrace();		}	    }	    // modified for servlet pool and executed in a context 	    // synchronized on the servlet pool, tk, 20.10.2001	    if (servlet != null) {		servletPool.add(servlet);		return true;	    } else {		return false;	    }	}    /**     * Check if the Servletclass wrapped is a Servlet class without     * initializing it. (not the same than checkServlet).     * used by the ServletIndexer.     * @see org.w3c.jigsaw.servlet.ServletIndexer     * @return A boolean.     */    protected boolean isWrappingAServlet() {	String clsname = getServletClass();	if ( clsname == null ) {	    return false;	}	Class c = null;	try {	    c = getLocalServletLoader().loadClass(clsname, true);	    Object o = c.newInstance();	    return (o instanceof Servlet);	} catch (Exception ex) {	    return false;	}    }    /**     * Launch the servlet we are wrapping.     * <p>This method either succeed, or the wrapper resource itself will fail     * to initialize, acting as transparently as possible (in some sense).     * @return A boolean, <strong>true</strong> if servlet launched.     * @exception ClassNotFoundException if servlet class can't be found.     * @exception ServletException if servlet can't be initialized.     */    protected boolean launchServlet() 	throws ClassNotFoundException, ServletException	{	    // Get and check the servlet class:	    // if ( servlet != null )	    destroyServlet();	    if (inited) { 		String msg = "relaunching servlet failed due to incomplete \""		    + getServletClass() + "\" cleanup.";		getServer().errlog(this, msg); 		return false;	    } else {		// Load appropriate servlet class:		String clsname = getServletClass();		if ( clsname == null ) {		    getServer().errlog(this, "no servlet class attribute"+				       " defined.");		    return false;		} else {		    Class c = null;		    try {			if (getLocalServletLoader().classChanged(clsname)) {			    createNewLocalServletLoader(true);			    invalidateAllSession();			}			c = getLocalServletLoader().loadClass(clsname, true);		    } catch (ClassNotFoundException ex) {			String msg = ("unable to find servlet class \""+				      getServletClass()+"\"");			getServer().errlog(msg);			// re throw the exception			throw ex;		    }		    return (c != null) ? launchServlet(c) : false;		}	    }	}        public boolean acceptUnload() {	// return (servlet == null);        return (!inited);    }        public void notifyUnload() {	if (timeoutManager != null) {	    timeoutManager.stop();	}	destroyServlet();    }    /**      * Get or create a suitable LocalServletLoader instance to load      * that servlet.     * @return A LocalServletLoader instance.     */    // singleton synchronized already performed at the servlet context.    // protected synchronized AutoReloadServletLoader getLocalServletLoader() {    protected AutoReloadServletLoader getLocalServletLoader() {	JigsawServletContext ctxt = (JigsawServletContext) getServletContext();	return ctxt.getLocalServletLoader();    }    protected AutoReloadServletLoader createNewLocalServletLoader(boolean 								  keepold)     {	JigsawServletContext ctxt = (JigsawServletContext) 		                                      getServletContext();	return ctxt.createNewLocalServletLoader(keepold);    }    /**     * Returns the name of this servlet instance.     * The name may be provided via server administration, assigned in the      * web application deployment descriptor, or for an unregistered (and thus     * unnamed) servlet instance it will be the servlet's class name.     * @return the name of the servlet instance     */    public String getServletName() {	return getIdentifier();    }    /**     * Initialize this servlet wrapper resource.     * After the wrapper itself is inited, it performs the servlet      * initialzation.     * @param values The default attribute values.     */    public void initialize(Object values[]) {	super.initialize(values);	// connections = 0;		if (getServletContext() != null) {	    timeoutManager = new TimeoutManager((httpd)getServer());	    timeoutManager.start();	}	try {	    registerFrameIfNone("org.w3c.jigsaw.servlet.ServletWrapperFrame",				"servlet-wrapper-frame");	} catch (Exception ex) {	    ex.printStackTrace();	}    }}

⌨️ 快捷键说明

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