001: /* ====================================================================
002: The Jicarilla Software License
003:
004: Copyright (c) 2003 Leo Simons.
005: All rights reserved.
006:
007: Permission is hereby granted, free of charge, to any person obtaining
008: a copy of this software and associated documentation files (the
009: "Software"), to deal in the Software without restriction, including
010: without limitation the rights to use, copy, modify, merge, publish,
011: distribute, sublicense, and/or sell copies of the Software, and to
012: permit persons to whom the Software is furnished to do so, subject to
013: the following conditions:
014:
015: The above copyright notice and this permission notice shall be
016: included in all copies or substantial portions of the Software.
017:
018: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
019: EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
020: MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
021: IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
022: CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
023: TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
024: SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
025: ==================================================================== */
026: package org.jicarilla.webserver.plumbing;
027:
028: import EDU.oswego.cs.dl.util.concurrent.Channel;
029: import org.apache.commons.pool.impl.SoftReferenceObjectPool;
030: import org.jicarilla.http.HTTPEncoding;
031: import org.jicarilla.http.HTTPException;
032: import org.jicarilla.http.HTTPMessage;
033: import org.jicarilla.http.HTTPMessageGenerator;
034: import org.jicarilla.http.HTTPParser;
035: import org.jicarilla.http.HTTPParserImpl;
036: import org.jicarilla.http.MessageFactory;
037: import org.jicarilla.http.MessageReceivedListener;
038: import org.jicarilla.lang.ExceptionListener;
039: import org.jicarilla.plumbing.Sink;
040:
041: import java.io.IOException;
042: import java.io.PrintWriter;
043: import java.io.StringWriter;
044: import java.nio.ByteBuffer;
045: import java.nio.channels.SocketChannel;
046:
047: /**
048: * Wraps HTTPParserImpl as a stage in the pipeline. Not
049: * threadsafe.
050: *
051: * @author <a href="lsimons at jicarilla dot org">Leo Simons</a>
052: * @version $Id: ParsingStage.java,v 1.1 2004/03/31 12:11:00 lsimons Exp $
053: */
054: public class ParsingStage extends AbstractStage {
055: public final static int BUFFER_SIZE = 8096;
056:
057: protected HTTPParserImpl m_parser;
058: protected HTTPMessageGenerator m_generator;
059: protected Listener m_listener;
060:
061: public ParsingStage(final Channel queue, final Sink errorHandler) {
062: super (queue, errorHandler);
063:
064: // todo: remove hard-wiring
065: setListener(new Listener());
066: setGenerator(new HTTPMessageGenerator(getListener(),
067: getListener(), new SoftReferenceObjectPool(
068: new MessageFactory())));
069: setParser(new HTTPParserImpl(getGenerator(), getGenerator()));
070: }
071:
072: protected Listener getListener() {
073: return m_listener;
074: }
075:
076: protected void setListener(final Listener listener) {
077: m_listener = listener;
078: }
079:
080: protected HTTPMessageGenerator getGenerator() {
081: return m_generator;
082: }
083:
084: protected void setGenerator(final HTTPMessageGenerator generator) {
085: m_generator = generator;
086: }
087:
088: protected HTTPParser getParser() {
089: return m_parser;
090: }
091:
092: protected void setParser(final HTTPParserImpl parser) {
093: m_parser = parser;
094: }
095:
096: protected void process(final HTTPEvent e) throws HTTPException,
097: IOException {
098: try {
099: // todo: robustness
100: final SocketChannel c = e.getChannel();
101: HTTPException ex = null;
102: while (true) {
103: if (getListener().message != null)
104: break;
105:
106: final ByteBuffer buf = ByteBuffer.allocate(BUFFER_SIZE);
107: final int read = c.read(buf);
108:
109: if (read < 0)
110: break;
111: if (read == 0) {
112: Thread.yield();
113: continue;
114: }
115:
116: buf.rewind();
117:
118: try {
119: getParser().parse(buf, read);
120: } catch (HTTPException he) {
121: ex = he;
122: break;
123: }
124: }
125: if (getListener().message == null) {
126: // note the listener will have heard of the exception
127: // if the message is not null :D
128: m_listener.exceptionOccurred(ex);
129: } else {
130: e.setRequest(getListener().message);
131: }
132: } finally {
133: getParser().reset();
134: getGenerator().newMessage();
135: getListener().message = null;
136: }
137: }
138:
139: protected static class Listener implements MessageReceivedListener,
140: ExceptionListener {
141: public HTTPMessage message = null;
142:
143: public void messageReceived(final HTTPMessage m) {
144: message = m;
145: }
146:
147: public void exceptionOccurred(final Throwable t) {
148: // todo improve
149: final HTTPMessage exMessage = new HTTPMessage();
150: exMessage.setMessageType(HTTPMessage.TYPE_RESPONSE);
151: exMessage.setField1(HTTPEncoding.VERSION_10);
152: exMessage
153: .setStatusCode(HTTPEncoding.STATUS_500_Internal_Server_Error);
154: exMessage.setField3("Internal Server Error");
155:
156: final StringWriter sw = new StringWriter();
157: final PrintWriter pw = new PrintWriter(sw);
158:
159: t.printStackTrace(pw);
160: exMessage.addHeader("Content-Type", "text/html");
161: exMessage
162: .addBodyPart("<html><head><title>Internal Server Error</title></head><body><h1>An unexpected exception occurred:</h1><pre>");
163: exMessage.addBodyPart(sw.toString());
164: exMessage.addBodyPart("</pre></body><html>");
165:
166: message = exMessage;
167: }
168: }
169: }
|