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