001: package com.quadcap.http.server22;
002:
003: /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.BufferedInputStream;
042: import java.io.BufferedOutputStream;
043: import java.io.ByteArrayOutputStream;
044: import java.io.FileOutputStream;
045: import java.io.InputStream;
046: import java.io.IOException;
047: import java.io.OutputStream;
048: import java.io.OutputStreamWriter;
049: import java.io.PrintStream;
050: import java.io.PrintWriter;
051:
052: import java.net.InetAddress;
053: import java.net.Socket;
054: import java.net.SocketException;
055:
056: import java.util.Enumeration;
057: import java.util.Hashtable;
058: import java.util.Vector;
059:
060: import javax.servlet.RequestDispatcher;
061: import javax.servlet.Servlet;
062: import javax.servlet.ServletException;
063: import javax.servlet.SingleThreadModel;
064:
065: import javax.servlet.http.HttpServlet;
066: import javax.servlet.http.HttpServletResponse;
067:
068: import com.quadcap.io.LogInputStream;
069: import com.quadcap.io.LogOutputStream;
070: import com.quadcap.io.IO;
071:
072: import com.quadcap.util.Config;
073: import com.quadcap.util.Debug;
074:
075: import com.quadcap.net.server.Server;
076: import com.quadcap.net.server.Worker;
077:
078: /**
079: * A Worker is a thread spawned by the server to handle a single client
080: * connection.
081: *
082: * @author Stan Bailes
083: */
084: public class WebWorker extends Worker {
085: WebServer s;
086:
087: HttpInputStream is = new HttpInputStream();
088: HttpOutputStream os = new HttpOutputStream();
089: HttpRequest req = new HttpRequest(this );
090: HttpResponse res = new HttpResponse(this );
091:
092: /** Construct a Worker attached to the specified socket. */
093: public void init(Server server, Object context) {
094: super .init(server, context);
095: this .s = (WebServer) context;
096: res.setFixedHeader("Server", s.getServerInfo());
097: req.setResponse(res);
098: }
099:
100: /**
101: * Handle the client session.
102: */
103: public void doSession() {
104: checkPermission();
105: boolean close = true;
106: //Jni j1 = new Jni("WebWorker");
107: int cnt = 0;
108: do {
109: String uri = "";
110: String proto = HttpRequest.proto_10;
111: try {
112: //j1.reset();
113: //Debug.println("[" + this + "].doSession(" + cnt + ")");
114: cnt++;
115: is.reset(getInputStream());
116: //j1.dump("is.reset");
117: os.reset(getOutputStream());
118: //j1.dump("os.reset");
119: try {
120: req.reset(is);
121: } catch (SocketException e) {
122: try {
123: os.reallyClose();
124: } catch (Throwable t) {
125: }
126: return;
127: }
128: //j1.dump("req.reset");
129: if (req.badRequest()) {
130: try {
131: os.reallyClose();
132: } catch (Throwable t) {
133: }
134: return;
135: }
136: res.reset(os);
137: //j1.dump("res.reset");
138: req.setResponse(res);
139: //j1.dump("req.setResponse");
140:
141: uri = req.getRequestURI();
142: //j1.dump("getRequestURI");
143: WebApplication app = s.getContext(uri);
144: //j1.dump("getContext(uri)");
145: //j1.dump("getHeader(Connection)");
146: proto = req.getProtocol();
147: //j1.dump("getProtocol");
148: if (proto == HttpRequest.proto_11) {
149: String conn = req.getHeader("Connection");
150: close = false;
151: if (conn != null) {
152: //Debug.println("conn = " + conn);
153: close = conn.equalsIgnoreCase("Close");
154: }
155: }
156: //j1.dump("proto check");
157:
158: // XXX but res.reset will trash this!!!!
159: res.setProtocol(proto);
160: res.setKeepAlive(!close);
161: //j1.dump("set Connection Header");
162: if (app != null) {
163: String subPath = uri.substring(app.getContextPath()
164: .length());
165: HttpDispatcher rd = (HttpDispatcher) app
166: .getRequestDispatcher(subPath);
167: if (rd != null) {
168: try {
169: rd.service(req, res);
170: } catch (Throwable th) {
171: Debug.print(th);
172: showException(th, req, res);
173: } finally {
174: if (res.getContentLength() < 0)
175: close = true;
176: if (Trace.level() > 0) {
177: Debug.println("[" + req.getMethod()
178: + " " + req.getRequestURI()
179: + "] " + res.sc + " " + res.sm);
180: }
181: //j1.dump("rd.service()");
182: res.flush();
183: //j1.dump("res.flush()");
184: }
185: } else {
186: res.sendError(HttpServletResponse.SC_NOT_FOUND,
187: "Not Found (request dispatcher)");
188: }
189: } else {
190: res.sendError(HttpServletResponse.SC_NOT_FOUND,
191: "Not Found (webapp)");
192: }
193: } catch (SocketException e) {
194: close = true;
195: } catch (Throwable e) {
196: Debug.println(1, e.toString());
197: e.printStackTrace(Debug.debugStream);
198: close = true;
199: } finally {
200: String qs = req.getQueryString();
201: if (qs == null) {
202: qs = "";
203: } else {
204: qs = "?" + qs;
205: }
206: s.requestLog(getRemoteHost() + " " + getRemoteAddr()
207: + " " + req.getMethod() + " " + uri + qs + " "
208: + res.sc);
209: }
210:
211: } while (!close);
212:
213: //j1.dump("loop done");
214: if (os != null) {
215: try {
216: os.close();
217: } catch (Exception e1) {
218: }
219: }
220: //j1.dump("os.close()");
221: }
222:
223: final void showException(Throwable t, HttpRequest req,
224: HttpResponse res) {
225: try {
226: res.reset();
227: res.setContentType("text/html");
228: PrintWriter pw = null;
229: if (res.getOutputStreamCalled) {
230: OutputStream os1 = res.getOutputStream();
231: OutputStreamWriter w = new OutputStreamWriter(os1);
232: pw = new PrintWriter(w);
233: } else {
234: pw = res.getWriter();
235: }
236: pw.println("<h3>Servlet Exception Report</h3>");
237: pw.println("<pre>");
238: ByteArrayOutputStream bos = new ByteArrayOutputStream();
239: PrintStream p = new PrintStream(bos);
240: t.printStackTrace(p);
241: if (t instanceof ServletException) {
242: Throwable t1 = ((ServletException) t).getRootCause();
243: if (t1 != null) {
244: p.println("");
245: p.println("<b>Root Cause</b>:");
246: t1.printStackTrace(p);
247: }
248: }
249:
250: p.flush();
251: pw.println(bos.toString());
252: bos = null;
253: p = null;
254: pw.println("contextPath = " + req.getContextPath());
255: pw.println("servletPath = " + req.getServletPath());
256: pw.println("pathInfo = " + req.getPathInfo());
257: pw.println("Headers:");
258: Enumeration e1 = req.getHeaderNames();
259: while (e1.hasMoreElements()) {
260: String name = e1.nextElement().toString();
261: Enumeration e2 = req.getHeaders(name);
262: while (e2.hasMoreElements()) {
263: String val = e2.nextElement().toString();
264: pw.println(name + ": " + val);
265: }
266: }
267: pw.println("</pre>");
268: } catch (Throwable th) {
269: Debug.print(th);
270: }
271: }
272:
273: /**
274: * Get the output stream.
275: */
276: public HttpOutputStream getHttpOutputStream() {
277: return os;
278: }
279:
280: /**
281: * Get the input stream.
282: */
283: public HttpInputStream getHttpInputStream() {
284: return is;
285: }
286:
287: /**
288: * Who is my http server?
289: */
290: public WebServer getHttpServer() {
291: return s;
292: }
293:
294: void checkPermission() {
295: if (String.valueOf(System.getProperty("public")).equals("true")) {
296: return;
297: }
298: if (String.valueOf(Config.getProperty("public")).equals("true")) {
299: return;
300: }
301: InetAddress ia = socket.getInetAddress();
302: if (ia.toString().equals("/127.0.0.1"))
303: return;
304: try {
305: if (ia.equals(InetAddress.getLocalHost())) {
306: return;
307: }
308: } catch (Throwable t) {
309: }
310: throw new RuntimeException("No permission: " + ia);
311: }
312: }
|