1 7 package winstone; 8 9 import java.io.IOException ; 10 import java.io.InputStream ; 11 import java.io.InterruptedIOException ; 12 import java.io.OutputStream ; 13 import java.net.Socket ; 14 import java.net.SocketException ; 15 16 import javax.servlet.ServletException ; 17 import javax.servlet.ServletRequestEvent ; 18 import javax.servlet.ServletRequestListener ; 19 20 26 public class RequestHandlerThread implements Runnable { 27 private Thread thread; 28 private ObjectPool objectPool; 29 private WinstoneInputStream inData; 30 private WinstoneOutputStream outData; 31 private WinstoneRequest req; 32 private WinstoneResponse rsp; 33 private Listener listener; 34 private Socket socket; 35 private String threadName; 36 private long requestStartTime; 37 private boolean simulateModUniqueId; 38 private boolean saveSessions; 39 41 45 public RequestHandlerThread(ObjectPool objectPool, int threadIndex, 46 boolean simulateModUniqueId, boolean saveSessions) { 47 this.objectPool = objectPool; 48 this.simulateModUniqueId = simulateModUniqueId; 49 this.saveSessions = saveSessions; 50 this.threadName = Launcher.RESOURCES.getString( 51 "RequestHandlerThread.ThreadName", "" + threadIndex); 52 53 this.thread = new Thread (this, threadName); 55 this.thread.setDaemon(true); 56 } 57 58 61 public void run() { 62 63 boolean interrupted = false; 64 while (!interrupted) { 65 InputStream inSocket = null; 67 OutputStream outSocket = null; 68 boolean iAmFirst = true; 69 try { 70 inSocket = socket.getInputStream(); 72 outSocket = socket.getOutputStream(); 73 74 boolean continueFlag = true; 76 while (continueFlag && !interrupted) { 77 try { 78 long requestId = System.currentTimeMillis(); 79 this.listener.allocateRequestResponse(socket, inSocket, 80 outSocket, this, iAmFirst); 81 if (this.req == null) { 82 this.listener.deallocateRequestResponse(this, req, 84 rsp, inData, outData); 85 continue; 86 } 87 String servletURI = this.listener.parseURI(this, 88 this.req, this.rsp, this.inData, this.socket, 89 iAmFirst); 90 if (servletURI == null) { 91 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 92 "RequestHandlerThread.KeepAliveTimedOut", this.threadName); 93 94 this.listener.deallocateRequestResponse(this, req, 96 rsp, inData, outData); 97 continueFlag = false; 98 continue; 99 } 100 101 if (this.simulateModUniqueId) { 102 req.setAttribute("UNIQUE_ID", "" + requestId); 103 } 104 long headerParseTime = getRequestProcessTime(); 105 iAmFirst = false; 106 107 HostConfiguration hostConfig = req.getHostGroup().getHostByName(req.getServerName()); 108 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 109 "RequestHandlerThread.StartRequest", 110 new String [] {"" + requestId, hostConfig.getHostname()}); 111 112 WebAppConfiguration webAppConfig = hostConfig.getWebAppByURI(servletURI); 115 if (webAppConfig == null) { 116 webAppConfig = hostConfig.getWebAppByURI("/"); 117 } 118 if (webAppConfig == null) { 119 Logger.log(Logger.WARNING, Launcher.RESOURCES, 120 "RequestHandlerThread.UnknownWebapp", 121 new String [] { servletURI }); 122 rsp.sendError(WinstoneResponse.SC_NOT_FOUND, 123 Launcher.RESOURCES.getString("RequestHandlerThread.UnknownWebappPage", servletURI)); 124 rsp.flushBuffer(); 125 req.discardRequestBody(); 126 writeToAccessLog(servletURI, req, rsp, null); 127 128 continueFlag = this.listener.processKeepAlive(req, rsp, inSocket); 130 this.listener.deallocateRequestResponse(this, req, rsp, inData, outData); 131 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "RequestHandlerThread.FinishRequest", 132 "" + requestId); 133 Logger.log(Logger.SPEED, Launcher.RESOURCES, "RequestHandlerThread.RequestTime", 134 new String [] { servletURI, "" + headerParseTime, "" + getRequestProcessTime() }); 135 continue; 136 } 137 req.setWebAppConfig(webAppConfig); 138 139 ServletRequestListener reqLsnrs[] = webAppConfig.getRequestListeners(); 142 for (int n = 0; n < reqLsnrs.length; n++) { 143 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 144 Thread.currentThread().setContextClassLoader(webAppConfig.getLoader()); 145 reqLsnrs[n].requestInitialized(new ServletRequestEvent (webAppConfig, req)); 146 Thread.currentThread().setContextClassLoader(cl); 147 } 148 149 processRequest(webAppConfig, req, rsp, 151 webAppConfig.getServletURIFromRequestURI(servletURI)); 152 writeToAccessLog(servletURI, req, rsp, webAppConfig); 153 154 this.outData.finishResponse(); 155 this.inData.finishRequest(); 156 157 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 158 "RequestHandlerThread.FinishRequest", 159 "" + requestId); 160 161 continueFlag = this.listener.processKeepAlive(req, rsp, inSocket); 163 164 req.markSessionsAsRequestFinished(this.requestStartTime, this.saveSessions); 167 168 for (int n = 0; n < reqLsnrs.length; n++) { 170 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 171 Thread.currentThread().setContextClassLoader(webAppConfig.getLoader()); 172 reqLsnrs[n].requestDestroyed(new ServletRequestEvent (webAppConfig, req)); 173 Thread.currentThread().setContextClassLoader(cl); 174 } 175 176 req.setWebAppConfig(null); 177 rsp.setWebAppConfig(null); 178 req.setRequestAttributeListeners(null); 179 180 this.listener.deallocateRequestResponse(this, req, rsp, inData, outData); 181 Logger.log(Logger.SPEED, Launcher.RESOURCES, "RequestHandlerThread.RequestTime", 182 new String [] { servletURI, "" + headerParseTime, 183 "" + getRequestProcessTime() }); 184 } catch (InterruptedIOException errIO) { 185 continueFlag = false; 186 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 187 "RequestHandlerThread.SocketTimeout", errIO); 188 } catch (SocketException errIO) { 189 continueFlag = false; 190 } 191 } 192 this.listener.deallocateRequestResponse(this, req, rsp, inData, outData); 193 this.listener.releaseSocket(this.socket, inSocket, outSocket); } catch (Throwable err) { 195 try { 196 this.listener.deallocateRequestResponse(this, req, rsp, inData, outData); 197 } catch (Throwable errClose) { 198 } 199 try { 200 this.listener.releaseSocket(this.socket, inSocket, 201 outSocket); } catch (Throwable errClose) { 203 } 204 Logger.log(Logger.ERROR, Launcher.RESOURCES, 205 "RequestHandlerThread.RequestError", err); 206 } 207 208 this.objectPool.releaseRequestHandler(this); 209 210 if (!interrupted) { 211 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 213 "RequestHandlerThread.EnterWaitState"); 214 try { 215 synchronized (this) { 216 this.wait(); 217 } 218 } catch (InterruptedException err) { 219 interrupted = true; 220 } 221 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 222 "RequestHandlerThread.WakingUp"); 223 } 224 } 225 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, "RequestHandlerThread.ThreadExit"); 226 } 227 228 233 private void processRequest(WebAppConfiguration webAppConfig, WinstoneRequest req, 234 WinstoneResponse rsp, String path) throws IOException , ServletException { 235 RequestDispatcher rd = null; 236 javax.servlet.RequestDispatcher rdError = null; 237 try { 238 rd = webAppConfig.getInitialDispatcher(path, req, rsp); 239 240 if (rd != null) { 242 Logger.log(Logger.FULL_DEBUG, Launcher.RESOURCES, 243 "RequestHandlerThread.HandlingRD", rd.getName()); 244 rd.forward(req, rsp); 245 } 246 } catch (Throwable err) { 248 Logger.log(Logger.WARNING, Launcher.RESOURCES, 249 "RequestHandlerThread.UntrappedError", err); 250 rdError = webAppConfig.getErrorDispatcherByClass(err); 251 } 252 253 if (rdError != null) { 255 try { 256 if (rsp.isCommitted()) { 257 rdError.include(req, rsp); 258 } else { 259 rsp.resetBuffer(); 260 rdError.forward(req, rsp); 261 } 262 } catch (Throwable err) { 263 Logger.log(Logger.ERROR, Launcher.RESOURCES, "RequestHandlerThread.ErrorInErrorServlet", err); 264 } 265 } 267 rsp.flushBuffer(); 268 req.discardRequestBody(); 269 } 270 271 274 public void commenceRequestHandling(Socket socket, Listener listener) { 275 this.listener = listener; 276 this.socket = socket; 277 if (this.thread.isAlive()) 278 synchronized (this) { 279 this.notifyAll(); 280 } 281 else 282 this.thread.start(); 283 } 284 285 public void setRequest(WinstoneRequest request) { 286 this.req = request; 287 } 288 289 public void setResponse(WinstoneResponse response) { 290 this.rsp = response; 291 } 292 293 public void setInStream(WinstoneInputStream inStream) { 294 this.inData = inStream; 295 } 296 297 public void setOutStream(WinstoneOutputStream outStream) { 298 this.outData = outStream; 299 } 300 301 public void setRequestStartTime() { 302 this.requestStartTime = System.currentTimeMillis(); 303 } 304 305 public long getRequestProcessTime() { 306 return System.currentTimeMillis() - this.requestStartTime; 307 } 308 309 312 public void destroy() { 313 if (this.thread.isAlive()) { 314 this.thread.interrupt(); 315 } 316 } 317 318 protected void writeToAccessLog(String originalURL, WinstoneRequest request, WinstoneResponse response, 319 WebAppConfiguration webAppConfig) { 320 if (webAppConfig != null) { 321 AccessLogger logger = webAppConfig.getAccessLogger(); 323 if (logger != null) { 324 logger.log(originalURL, request, response); 325 } 326 } 327 } 328 } 329 | Popular Tags |