Quadcap Embeddable Server

com/quadcap/http/server22/WebWorker.java

Go to the documentation of this file.
00001 package com.quadcap.http.server22; 00002 00003 /* Copyright 1997 - 2003 Quadcap Software. All rights reserved. 00004 * 00005 * This software is distributed under the Quadcap Free Software License. 00006 * This software may be used or modified for any purpose, personal or 00007 * commercial. Open Source redistributions are permitted. Commercial 00008 * redistribution of larger works derived from, or works which bundle 00009 * this software requires a "Commercial Redistribution License"; see 00010 * http://www.quadcap.com/purchase. 00011 * 00012 * Redistributions qualify as "Open Source" under one of the following terms: 00013 * 00014 * Redistributions are made at no charge beyond the reasonable cost of 00015 * materials and delivery. 00016 * 00017 * Redistributions are accompanied by a copy of the Source Code or by an 00018 * irrevocable offer to provide a copy of the Source Code for up to three 00019 * years at the cost of materials and delivery. Such redistributions 00020 * must allow further use, modification, and redistribution of the Source 00021 * Code under substantially the same terms as this license. 00022 * 00023 * Redistributions of source code must retain the copyright notices as they 00024 * appear in each source code file, these license terms, and the 00025 * disclaimer/limitation of liability set forth as paragraph 6 below. 00026 * 00027 * Redistributions in binary form must reproduce this Copyright Notice, 00028 * these license terms, and the disclaimer/limitation of liability set 00029 * forth as paragraph 6 below, in the documentation and/or other materials 00030 * provided with the distribution. 00031 * 00032 * The Software is provided on an "AS IS" basis. No warranty is 00033 * provided that the Software is free of defects, or fit for a 00034 * particular purpose. 00035 * 00036 * Limitation of Liability. Quadcap Software shall not be liable 00037 * for any damages suffered by the Licensee or any third party resulting 00038 * from use of the Software. 00039 */ 00040 00041 import java.io.BufferedInputStream; 00042 import java.io.BufferedOutputStream; 00043 import java.io.ByteArrayOutputStream; 00044 import java.io.FileOutputStream; 00045 import java.io.InputStream; 00046 import java.io.IOException; 00047 import java.io.OutputStream; 00048 import java.io.OutputStreamWriter; 00049 import java.io.PrintStream; 00050 import java.io.PrintWriter; 00051 00052 import java.net.InetAddress; 00053 import java.net.Socket; 00054 import java.net.SocketException; 00055 00056 import java.util.Enumeration; 00057 import java.util.Hashtable; 00058 import java.util.Vector; 00059 00060 import javax.servlet.RequestDispatcher; 00061 import javax.servlet.Servlet; 00062 import javax.servlet.ServletException; 00063 import javax.servlet.SingleThreadModel; 00064 00065 import javax.servlet.http.HttpServlet; 00066 import javax.servlet.http.HttpServletResponse; 00067 00068 import com.quadcap.io.LogInputStream; 00069 import com.quadcap.io.LogOutputStream; 00070 import com.quadcap.io.IO; 00071 00072 import com.quadcap.util.Config; 00073 import com.quadcap.util.Debug; 00074 00075 import com.quadcap.net.server.Server; 00076 import com.quadcap.net.server.Worker; 00077 00078 /** 00079 * A Worker is a thread spawned by the server to handle a single client 00080 * connection. 00081 * 00082 * @author Stan Bailes 00083 */ 00084 public class WebWorker extends Worker { 00085 WebServer s; 00086 00087 HttpInputStream is = new HttpInputStream(); 00088 HttpOutputStream os = new HttpOutputStream(); 00089 HttpRequest req = new HttpRequest(this); 00090 HttpResponse res = new HttpResponse(this); 00091 00092 /** Construct a Worker attached to the specified socket. */ 00093 public void init(Server server, Object context) { 00094 super.init(server, context); 00095 this.s = (WebServer)context; 00096 res.setFixedHeader("Server", s.getServerInfo()); 00097 req.setResponse(res); 00098 } 00099 00100 /** 00101 * Handle the client session. 00102 */ 00103 public void doSession() { 00104 checkPermission(); 00105 boolean close = true; 00106 //Jni j1 = new Jni("WebWorker"); 00107 int cnt = 0; 00108 do { 00109 String uri = ""; 00110 String proto = HttpRequest.proto_10; 00111 try { 00112 //j1.reset(); 00113 //Debug.println("[" + this + "].doSession(" + cnt + ")"); 00114 cnt++; 00115 is.reset(getInputStream()); 00116 //j1.dump("is.reset"); 00117 os.reset(getOutputStream()); 00118 //j1.dump("os.reset"); 00119 try { 00120 req.reset(is); 00121 } catch (SocketException e) { 00122 try { 00123 os.reallyClose(); 00124 } catch (Throwable t) {} 00125 return; 00126 } 00127 //j1.dump("req.reset"); 00128 if (req.badRequest()) { 00129 try { 00130 os.reallyClose(); 00131 } catch (Throwable t) {} 00132 return; 00133 } 00134 res.reset(os); 00135 //j1.dump("res.reset"); 00136 req.setResponse(res); 00137 //j1.dump("req.setResponse"); 00138 00139 uri = req.getRequestURI(); 00140 //j1.dump("getRequestURI"); 00141 WebApplication app = s.getContext(uri); 00142 //j1.dump("getContext(uri)"); 00143 //j1.dump("getHeader(Connection)"); 00144 proto = req.getProtocol(); 00145 //j1.dump("getProtocol"); 00146 if (proto == HttpRequest.proto_11) { 00147 String conn = req.getHeader("Connection"); 00148 close = false; 00149 if (conn != null) { 00150 //Debug.println("conn = " + conn); 00151 close = conn.equalsIgnoreCase("Close"); 00152 } 00153 } 00154 //j1.dump("proto check"); 00155 00156 // XXX but res.reset will trash this!!!! 00157 res.setProtocol(proto); 00158 res.setKeepAlive(!close); 00159 //j1.dump("set Connection Header"); 00160 if (app != null) { 00161 String subPath = uri.substring(app.getContextPath().length()); 00162 HttpDispatcher rd = (HttpDispatcher)app.getRequestDispatcher(subPath); 00163 if (rd != null) { 00164 try { 00165 rd.service(req, res); 00166 } catch (Throwable th) { 00167 Debug.print(th); 00168 showException(th, req, res); 00169 } finally { 00170 if (res.getContentLength() < 0) close = true; 00171 if (Trace.level() > 0) { 00172 Debug.println("[" + req.getMethod() + " " + 00173 req.getRequestURI() + "] " + 00174 res.sc + " " + res.sm); 00175 } 00176 //j1.dump("rd.service()"); 00177 res.flush(); 00178 //j1.dump("res.flush()"); 00179 } 00180 } else { 00181 res.sendError(HttpServletResponse.SC_NOT_FOUND, 00182 "Not Found (request dispatcher)"); 00183 } 00184 } else { 00185 res.sendError(HttpServletResponse.SC_NOT_FOUND, 00186 "Not Found (webapp)"); 00187 } 00188 } catch (SocketException e) { 00189 close = true; 00190 } catch (Throwable e) { 00191 Debug.println(1, e.toString()); 00192 e.printStackTrace(Debug.debugStream); 00193 close = true; 00194 } finally { 00195 String qs = req.getQueryString(); 00196 if (qs == null) { 00197 qs = ""; 00198 } else { 00199 qs = "?" + qs; 00200 } 00201 s.requestLog(getRemoteHost() + " " + getRemoteAddr() + " " + 00202 req.getMethod() + " " + uri + qs + " " + res.sc); 00203 } 00204 00205 } while (!close); 00206 00207 //j1.dump("loop done"); 00208 if (os != null) { 00209 try { 00210 os.close(); 00211 } catch (Exception e1) {} 00212 } 00213 //j1.dump("os.close()"); 00214 } 00215 00216 final void showException(Throwable t, HttpRequest req, HttpResponse res) { 00217 try { 00218 res.reset(); 00219 res.setContentType("text/html"); 00220 PrintWriter pw = null; 00221 if (res.getOutputStreamCalled) { 00222 OutputStream os1 = res.getOutputStream(); 00223 OutputStreamWriter w = new OutputStreamWriter(os1); 00224 pw = new PrintWriter(w); 00225 } else { 00226 pw = res.getWriter(); 00227 } 00228 pw.println("<h3>Servlet Exception Report</h3>"); 00229 pw.println("<pre>"); 00230 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 00231 PrintStream p = new PrintStream(bos); 00232 t.printStackTrace(p); 00233 if (t instanceof ServletException) { 00234 Throwable t1 = ((ServletException)t).getRootCause(); 00235 if (t1 != null) { 00236 p.println(""); 00237 p.println("<b>Root Cause</b>:"); 00238 t1.printStackTrace(p); 00239 } 00240 } 00241 00242 p.flush(); 00243 pw.println(bos.toString()); 00244 bos = null; 00245 p = null; 00246 pw.println("contextPath = " + req.getContextPath()); 00247 pw.println("servletPath = " + req.getServletPath()); 00248 pw.println("pathInfo = " + req.getPathInfo()); 00249 pw.println("Headers:"); 00250 Enumeration e1 = req.getHeaderNames(); 00251 while (e1.hasMoreElements()) { 00252 String name = e1.nextElement().toString(); 00253 Enumeration e2 = req.getHeaders(name); 00254 while (e2.hasMoreElements()) { 00255 String val = e2.nextElement().toString(); 00256 pw.println(name + ": " + val); 00257 } 00258 } 00259 pw.println("</pre>"); 00260 } catch (Throwable th) { 00261 Debug.print(th); 00262 } 00263 } 00264 00265 /** 00266 * Get the output stream. 00267 */ 00268 public HttpOutputStream getHttpOutputStream() { return os; } 00269 00270 /** 00271 * Get the input stream. 00272 */ 00273 public HttpInputStream getHttpInputStream() { return is; } 00274 00275 /** 00276 * Who is my http server? 00277 */ 00278 public WebServer getHttpServer() { return s; } 00279 00280 void checkPermission() { 00281 if (String.valueOf(System.getProperty("public")).equals("true")) { 00282 return; 00283 } 00284 if (String.valueOf(Config.getProperty("public")).equals("true")) { 00285 return; 00286 } 00287 InetAddress ia = socket.getInetAddress(); 00288 if (ia.toString().equals("/127.0.0.1")) return; 00289 try { 00290 if (ia.equals(InetAddress.getLocalHost())) { 00291 return; 00292 } 00293 } catch (Throwable t) {} 00294 throw new RuntimeException("No permission: " + ia); 00295 } 00296 }