You are viewing a plain text version of this content. The canonical link for it is here.
Posted to xmlrpc-dev@ws.apache.org by jo...@apache.org on 2005/10/26 23:13:47 UTC

svn commit: r328736 [2/2] - in /webservices/xmlrpc/branches/b20050512_streaming: ./ .settings/ src/java/org/apache/xmlrpc/serializer/ src/java/org/apache/xmlrpc/util/ src/java/org/apache/xmlrpc/webserver/

Added: webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java
URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java?rev=328736&view=auto
==============================================================================
--- webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java (added)
+++ webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/HttpServletResponseImpl.java Wed Oct 26 14:13:21 2005
@@ -0,0 +1,465 @@
+/*
+ * Copyright 1999,2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xmlrpc.webserver;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+
+
+/** Stub implementation of a {@link javax.servlet.http.HttpServletResponse}
+ * with lots of unimplemented methods. I implemented only those, which
+ * are required for testing the {@link org.apache.xmlrpc.webserver.XmlRpcServlet}.
+ * Perhaps someone else is adding more at a later time?
+ */
+public class HttpServletResponseImpl implements HttpServletResponse {
+	static final int BUFFER_SIZE = 8192;
+	private final Socket socket;
+	private final OutputStream ostream;
+	private final Map headers = new HashMap();
+	private int status = HttpServletResponse.SC_OK;
+	private String message = getStatusMessage(status);
+	private Locale locale;
+	private String charEncoding;
+	private PrintWriter writer;
+	private ServletOutputStreamImpl soStream;
+
+	/** Creates a new instance.
+	 * @param pSocket The clients socket.
+	 * @throws IOException Accessing the sockets output stream failed.
+	 */
+	public HttpServletResponseImpl(Socket pSocket) throws IOException {
+		socket = pSocket;
+		ostream = socket.getOutputStream();
+	}
+
+	public void addCookie(Cookie pCookie) { throw new IllegalStateException("Not implemented"); }
+
+	public void addDateHeader(String pHeader, long pDate) { throw new IllegalStateException("Not implemented"); }
+
+	public void addHeader(String pHeader, String pValue) {
+		String key = pHeader.toLowerCase();
+		Object o = headers.get(key);
+		if (o == null) {
+			headers.put(key, pValue);
+		} else {
+			List list;
+			if (o instanceof String) {
+				list = new ArrayList();
+				headers.put(key, list);
+				list.add(o);
+			} else {
+				list = (List) o;
+			}
+			list.add(pValue);
+		}
+	}
+
+	private String getHeader(String pHeader) {
+		String key = pHeader.toLowerCase();
+		Object o = headers.get(key);
+		if (o == null) {
+			return null;
+		} else if (o instanceof String) {
+			return (String) o;
+		} else {
+			List list = (List) o;
+			if (list.size() == 0) {
+				return null;
+			} else {
+				return (String) list.get(0);
+			}
+		}
+	}
+
+	public void addIntHeader(String pHeader, int pValue) {
+		addHeader(pHeader, Integer.toString(pValue));
+	}
+
+	public boolean containsHeader(String pHeader) {
+		return headers.containsKey(pHeader.toLowerCase());
+	}
+
+	public String encodeRedirectURL(String pURL) { throw new IllegalStateException("Not implemented"); }
+
+	public String encodeRedirectUrl(String pURL) { return encodeRedirectURL(pURL); }
+
+	public String encodeURL(String pURL) { throw new IllegalStateException("Not implemented"); }
+
+	public String encodeUrl(String pURL) { return encodeUrl(pURL); }
+
+	public void sendError(int pStatusCode) throws IOException {
+		sendError(pStatusCode, getStatusMessage(pStatusCode));
+	}
+
+	public void sendError(int pStatusCode, String pMessage) throws IOException {
+		sendError(pStatusCode, pMessage, null);
+	}
+
+    protected void sendError(int pStatusCode, String pMessage, String pDescription)
+    		throws IOException {
+		if (isCommitted()) {
+			throw new IllegalStateException("Can't send an error message, if the response has already been committed.");
+		}
+		headers.clear();
+		setContentType("text/html");
+		setStatus(pStatusCode, pMessage);
+		if (soStream == null) {
+			soStream = new ServletOutputStreamImpl(ostream, this);
+		} else {
+			soStream.reset();
+		}
+		OutputStreamWriter osw = new OutputStreamWriter(soStream, getCharacterEncoding());
+		osw.write("<html><head><title>" + pStatusCode + " " + pMessage + "</title></head>\r\n");
+		osw.write("<body><h1>" + pStatusCode + " " + pMessage + "</h1>\r\n");
+		if (pDescription != null) {
+			osw.write("<p>" + pDescription + "</p>\r\n");
+		}
+		osw.write("</body></html>\r\n");
+		osw.close();
+	}
+
+	public void sendRedirect(String arg0) throws IOException { throw new IllegalStateException("Not implemented"); }
+
+	public void setDateHeader(String arg0, long arg1) { throw new IllegalStateException("Not implemented"); }
+
+	public void setHeader(String pHeader, String pValue) {
+		headers.remove(pHeader.toLowerCase());
+		addHeader(pHeader, pValue);
+	}
+
+	public void setIntHeader(String pHeader, int pValue) {
+		setHeader(pHeader, Integer.toString(pValue));
+	}
+
+	public void setStatus(int pStatusCode) {
+		setStatus(pStatusCode, getStatusMessage(pStatusCode));
+	}
+
+	public void setStatus(int pStatusCode, String pMessage) {
+		status = pStatusCode;
+		message = pMessage;
+	}
+
+	public void flushBuffer() throws IOException {
+		ostream.flush();
+	}
+
+	public int getBufferSize() { return BUFFER_SIZE; }
+
+	/** <p>Sets the character encoding (MIME charset) of the response being sent
+	 * to the client, for example, to UTF-8. If the character encoding has
+	 * already been set by setContentType(java.lang.String) or
+	 * setLocale(java.util.Locale), this method overrides it.
+	 * Calling setContentType(java.lang.String) with the String
+	 * of text/html and calling this method with the String of UTF-8
+	 * is equivalent with calling setContentType with the String of
+	 * text/html; charset=UTF-8.</p>
+	 * <p>This method can be called repeatedly to change the character
+	 * encoding. This method has no effect if it is called after getWriter
+	 * has been called or after the response has been committed.</p>
+	 * <p>Containers must communicate the character encoding used for
+	 * the servlet response's writer to the client if the protocol
+	 * provides a way for doing so. In the case of HTTP, the character
+	 * encoding is communicated as part of the Content-Type header for
+	 * text media types. Note that the character encoding cannot be
+	 * communicated via HTTP headers if the servlet does not specify
+	 * a content type; however, it is still used to encode text written
+	 * via the servlet response's writer.</p>
+	 * @param pCharset A String specifying only the character set defined
+	 * by IANA Character Sets (http://www.iana.org/assignments/character-sets)
+	 * @since Servlet API 2.4
+	 * @see #setLocale(Locale)
+	 */
+	public void setCharacterEncoding(String pCharset) {
+		charEncoding = pCharset;
+	}
+
+	public String getCharacterEncoding() {
+		if (charEncoding == null) {
+			return "ISO-8859-1";
+		} else {
+			return charEncoding;
+		}
+	}
+
+	public Locale getLocale() { return locale; }
+
+	public ServletOutputStream getOutputStream() throws IOException {
+		if (writer != null) {
+			throw new IllegalStateException("You may call either getWriter() or getOutputStream(), but not both.");
+		} else {
+			if (soStream == null) {
+				soStream = new ServletOutputStreamImpl(ostream, this);
+			}
+			return soStream;
+		}
+	}
+
+	public PrintWriter getWriter() throws IOException {
+		if (writer != null) {
+			return writer;
+		} else if (soStream != null) {
+			throw new IllegalStateException("You may call either getWriter() or getOutputStream(), but not both.");
+		} else {
+			writer = new PrintWriter(new OutputStreamWriter(getOutputStream(), getCharacterEncoding()));
+			return writer;
+		}
+	}
+
+	public boolean isCommitted() {
+		return soStream != null  &&  soStream.isCommitted();
+	}
+
+	public void reset() {
+		resetBuffer();
+		setStatus(HttpServletResponse.SC_OK);
+		headers.clear();
+		charEncoding = null;
+		locale = null;
+	}
+
+	public void resetBuffer() {
+		if (isCommitted()) {
+			throw new IllegalStateException("The ServletOutputStream is already committed. A reset is no longer possible.");
+		}
+		if (soStream != null) {
+			soStream.reset();
+		}
+	}
+
+	public void setBufferSize(int pBufferSize) { throw new IllegalStateException("Not implemented"); }
+
+	public void setContentLength(int pContentLength) {
+		if (pContentLength == -1) {
+			headers.remove("content-length");
+		} else {
+			setIntHeader("content-length", pContentLength);
+		}
+	}
+
+	/** <p>Returns the content type used for the MIME body sent in this
+	 * response. The content type proper must have been specified
+	 * using setContentType(java.lang.String) before the response is
+	 * committed. If no content type has been specified, this method
+	 * returns null. If a content type has been specified and a
+	 * character encoding has been explicitly or implicitly specified
+	 * as described in getCharacterEncoding(), the charset parameter
+	 * is included in the string returned. If no character encoding
+	 * has been specified, the charset parameter is omitted.</p>
+	 * @return A String specifying the content type, for example,
+	 * text/html; charset=UTF-8, or null
+	 * @since Servlet API 2.4
+	 * @see #setContentType(String)
+	 */
+	public String getContentType() {
+		String s = getHeader("content-type");
+		if (s != null  &&  s.toLowerCase().startsWith("text/")) {
+			String enc = getCharacterEncoding();
+			if (enc != null) {
+				s += "; charset=" + enc;
+			}
+		}
+		return s;
+	}
+
+
+	public void setContentType(String pType) {
+		if (pType != null) {
+			boolean charSetFound = false;
+			StringBuffer sb = new StringBuffer();
+			for (StringTokenizer st = new StringTokenizer(pType, ";");  st.hasMoreTokens();  ) {
+				String t = st.nextToken();
+				if (t.toLowerCase().startsWith("charset=")) {
+					charSetFound = true;
+					setCharacterEncoding(t.substring("charset=".length()).trim());
+				} else {
+					if (sb.length() > 0) {
+						sb.append("; ");
+					}
+					sb.append(t);
+				}
+			}
+			if (charSetFound) {
+				pType = sb.toString();
+			}
+		}
+		setHeader("content-type", pType);
+	}
+
+	public void setLocale(Locale pLocale) { locale = pLocale; }
+
+	/** Returns a default message for a given HTTP status code.
+	 * @param pStatusCode The status code being queried.
+	 * @return The default message.
+	 */
+	public static String getStatusMessage(int pStatusCode) {
+		switch (pStatusCode) {
+			case HttpServletResponse.SC_OK:
+				return ("OK");
+			case HttpServletResponse.SC_ACCEPTED:
+				return ("Accepted");
+			case HttpServletResponse.SC_BAD_GATEWAY:
+				return ("Bad Gateway");
+			case HttpServletResponse.SC_BAD_REQUEST:
+				return ("Bad Request");
+			case HttpServletResponse.SC_CONFLICT:
+				return ("Conflict");
+			case HttpServletResponse.SC_CONTINUE:
+				return ("Continue");
+			case HttpServletResponse.SC_CREATED:
+				return ("Created");
+			case HttpServletResponse.SC_EXPECTATION_FAILED:
+				return ("Expectation Failed");
+			case HttpServletResponse.SC_FORBIDDEN:
+				return ("Forbidden");
+			case HttpServletResponse.SC_GATEWAY_TIMEOUT:
+				return ("Gateway Timeout");
+			case HttpServletResponse.SC_GONE:
+				return ("Gone");
+			case HttpServletResponse.SC_HTTP_VERSION_NOT_SUPPORTED:
+				return ("HTTP Version Not Supported");
+			case HttpServletResponse.SC_INTERNAL_SERVER_ERROR:
+				return ("Internal Server Error");
+			case HttpServletResponse.SC_LENGTH_REQUIRED:
+				return ("Length Required");
+			case HttpServletResponse.SC_METHOD_NOT_ALLOWED:
+				return ("Method Not Allowed");
+			case HttpServletResponse.SC_MOVED_PERMANENTLY:
+				return ("Moved Permanently");
+			case HttpServletResponse.SC_MOVED_TEMPORARILY:
+				return ("Moved Temporarily");
+			case HttpServletResponse.SC_MULTIPLE_CHOICES:
+				return ("Multiple Choices");
+			case HttpServletResponse.SC_NO_CONTENT:
+				return ("No Content");
+			case HttpServletResponse.SC_NON_AUTHORITATIVE_INFORMATION:
+				return ("Non-Authoritative Information");
+			case HttpServletResponse.SC_NOT_ACCEPTABLE:
+				return ("Not Acceptable");
+			case HttpServletResponse.SC_NOT_FOUND:
+				return ("Not Found");
+			case HttpServletResponse.SC_NOT_IMPLEMENTED:
+				return ("Not Implemented");
+			case HttpServletResponse.SC_NOT_MODIFIED:
+				return ("Not Modified");
+			case HttpServletResponse.SC_PARTIAL_CONTENT:
+				return ("Partial Content");
+			case HttpServletResponse.SC_PAYMENT_REQUIRED:
+				return ("Payment Required");
+			case HttpServletResponse.SC_PRECONDITION_FAILED:
+				return ("Precondition Failed");
+			case HttpServletResponse.SC_PROXY_AUTHENTICATION_REQUIRED:
+				return ("Proxy Authentication Required");
+			case HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE:
+				return ("Request Entity Too Large");
+			case HttpServletResponse.SC_REQUEST_TIMEOUT:
+				return ("Request Timeout");
+			case HttpServletResponse.SC_REQUEST_URI_TOO_LONG:
+				return ("Request URI Too Long");
+			case HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE:
+				return ("Requested Range Not Satisfiable");
+			case HttpServletResponse.SC_RESET_CONTENT:
+				return ("Reset Content");
+			case HttpServletResponse.SC_SEE_OTHER:
+				return ("See Other");
+			case HttpServletResponse.SC_SERVICE_UNAVAILABLE:
+				return ("Service Unavailable");
+			case HttpServletResponse.SC_SWITCHING_PROTOCOLS:
+				return ("Switching Protocols");
+			case HttpServletResponse.SC_UNAUTHORIZED:
+				return ("Unauthorized");
+			case HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE:
+				return ("Unsupported Media Type");
+			case HttpServletResponse.SC_USE_PROXY:
+				return ("Use Proxy");
+			case 207:       // WebDAV
+				return ("Multi-Status");
+			case 422:       // WebDAV
+				return ("Unprocessable Entity");
+			case 423:       // WebDAV
+				return ("Locked");
+			case 507:       // WebDAV
+				return ("Insufficient Storage");
+			default:
+				return ("HTTP Response Status " + pStatusCode);
+		}
+	}
+
+	String getHttpHeaders(Integer pContentLength) throws IOException {
+		StringBuffer sb = new StringBuffer();
+		sb.append("HTTP/1.0 ");
+		sb.append(status);
+		sb.append(' ');
+		sb.append(message);
+		sb.append("\r\n");
+		String contentType = getContentType();
+		if (contentType != null) {
+			sb.append("Content-Type: ");
+			sb.append(contentType);
+			sb.append("\r\n");
+		}
+		boolean contentLengthSeen = false;
+		for (Iterator iter = headers.entrySet().iterator();  iter.hasNext();  ) {
+			Map.Entry entry = (Map.Entry) iter.next();
+			String header = (String) entry.getKey();
+			if ("content-type".equalsIgnoreCase(header)) {
+				continue;
+			}
+			Object o = entry.getValue();
+			if (o == null) {
+				continue;
+			}
+			if ("content-length".equalsIgnoreCase(header)) {
+				contentLengthSeen = true;
+			}
+			if (o instanceof String) {
+				sb.append(header);
+				sb.append(": ");
+				sb.append(o);
+				sb.append("\r\n");
+			} else {
+				List list = (List) o;
+				for (int i = 0;  i < list.size();  i++) {
+					sb.append(header);
+					sb.append(": ");
+					sb.append(list.get(i));
+					sb.append("\r\n");
+				}
+			}
+		}
+		if (pContentLength != null  &&  !contentLengthSeen) {
+			sb.append("Content-Length: ");
+			sb.append(pContentLength);
+			sb.append("\r\n");
+		}
+		sb.append("\r\n");
+		return sb.toString();
+	}
+}

Added: webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletConnection.java
URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletConnection.java?rev=328736&view=auto
==============================================================================
--- webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletConnection.java (added)
+++ webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletConnection.java Wed Oct 26 14:13:21 2005
@@ -0,0 +1,54 @@
+/*
+ * Copyright 1999,2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xmlrpc.webserver;
+
+import java.io.IOException;
+import java.net.Socket;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.xmlrpc.server.XmlRpcStreamServer;
+import org.apache.xmlrpc.util.ThreadPool.Task;
+
+
+/** {@link org.apache.xmlrpc.webserver.ServletWebServer ServletWebServer's}
+ * {@link org.apache.xmlrpc.util.ThreadPool.Task} for handling a single
+ * servlet connection.
+ */
+public class ServletConnection implements Task {
+	private final WebServer webServer;
+	private final XmlRpcStreamServer xmlRpcServer;
+	private final Socket socket;
+	private final HttpServletRequest request;
+	private final HttpServletResponse response;
+
+	public ServletConnection(WebServer pWebServer,
+							 XmlRpcStreamServer pXmlRpcServer,
+							 Socket pSocket) throws IOException {
+		webServer = pWebServer;
+		xmlRpcServer = pXmlRpcServer;
+		socket = pSocket;
+		request = new HttpServletRequestImpl(socket);
+		response = new HttpServletResponseImpl(socket);
+	}
+
+	public void run() throws Throwable {
+		// TODO Auto-generated method stub
+
+	}
+
+}

Added: webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletOutputStreamImpl.java
URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletOutputStreamImpl.java?rev=328736&view=auto
==============================================================================
--- webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletOutputStreamImpl.java (added)
+++ webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletOutputStreamImpl.java Wed Oct 26 14:13:21 2005
@@ -0,0 +1,83 @@
+package org.apache.xmlrpc.webserver;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import javax.servlet.ServletOutputStream;
+
+
+/** Default implementation of a servlet output stream.
+ * Handles output of HTTP headers.
+ */
+class ServletOutputStreamImpl extends ServletOutputStream {
+	private final OutputStream target;
+	private final HttpServletResponseImpl res;
+	private final byte[] buffer = new byte[HttpServletResponseImpl.BUFFER_SIZE];
+	private int bufferOffset;
+	private boolean closed;
+	private boolean committed;
+
+	ServletOutputStreamImpl(OutputStream pTarget, HttpServletResponseImpl pResponse) {
+		target = pTarget;
+		res = pResponse;
+	}
+
+	public void write(int b) throws IOException {
+		if (closed) {
+			throw new IOException("This output stream is already closed.");
+		}
+		if (bufferOffset == buffer.length) {
+			flush();
+		}
+		buffer[bufferOffset++] = (byte) b;
+	}
+
+	public void write(byte[] pChars, int pOffset, int pLen) throws IOException {
+		if (closed) {
+			throw new IOException("This output stream is already closed.");
+		}
+		while (pLen-- > 0) {
+			if (bufferOffset == buffer.length) {
+				flush();
+			}
+			buffer[bufferOffset++] = pChars[pOffset++];
+		}
+	}
+
+	private void flush(boolean pClosing) throws IOException {
+		if (!committed) {
+			committed = true;
+			String headers = res.getHttpHeaders(pClosing ? new Integer(bufferOffset) : null);
+			target.write(headers.getBytes("US-ASCII"));
+		}
+		if (bufferOffset > 0) {
+			target.write(buffer, 0, bufferOffset);
+		}
+	}
+
+	public void close() throws IOException {
+		if (!closed) {
+			flush(true);
+			closed = true;
+			target.close();
+		}
+	}
+
+	public void flush() throws IOException {
+		if (closed) {
+			throw new IOException("This output stream is already closed.");
+		}
+		flush(false);
+		target.flush();
+	}
+
+	void reset() {
+		if (committed) {
+			throw new IllegalStateException("The response is already committed. A reset cannot be performed.");
+		}
+	}
+
+	boolean isCommitted() {
+		return committed;
+	}
+}

Added: webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletWebServer.java
URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletWebServer.java?rev=328736&view=auto
==============================================================================
--- webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletWebServer.java (added)
+++ webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/ServletWebServer.java Wed Oct 26 14:13:21 2005
@@ -0,0 +1,90 @@
+/*
+ * Copyright 1999,2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.xmlrpc.webserver;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.Socket;
+
+import javax.servlet.ServletException;
+
+import org.apache.xmlrpc.server.XmlRpcStreamServer;
+import org.apache.xmlrpc.util.ThreadPool;
+
+
+/** A subclass of {@link WebServer}, which emulates a servlet
+ * container. Mainly useful for debugging.
+ */
+public class ServletWebServer extends WebServer {
+	/** This exception is thrown by the request handling classes,
+	 * advising the server, that it should return an error response.
+	 */
+	public static class Exception extends IOException {
+		private static final long serialVersionUID = 49879832748972394L;
+		private final int statusCode;
+		private final String description;
+
+		/** Creates a new instance.
+		 * @param pStatusCode The HTTP status code being sent to the client.
+		 * @param pMessage The HTTP status message being sent to the client.
+		 * @param pDescription The error description being sent to the client
+		 * in the response body.
+		 */
+		public Exception(int pStatusCode, String pMessage, String pDescription) {
+			super(pMessage);
+			statusCode = pStatusCode;
+			description = pDescription;
+		}
+
+		public String getMessage() { return statusCode + " " + super.getMessage(); }
+
+		/** Returns the error description. The server will send the description
+		 * as plain text in the response body.
+		 * @return The error description.
+		 */
+		public String getDescription() { return description; }
+
+		/** Returns the HTTP status code.
+		 * @return The status code.
+		 */
+		public int getStatusCode() { return statusCode; }
+	}
+
+	/** Creates a new instance, which is listening on all
+	 * local IP addresses and the given port.
+	 * @param pPort The servers port number; 0 for a random
+	 * port being choosen.
+	 */
+	public ServletWebServer(int pPort) {
+		super(pPort);
+	}
+
+	/** Creates a new instance, which is listening on the
+	 * given IP address and the given port.
+	 * @param pPort The servers port number; 0 for a random
+	 * port being choosen.
+	 * @param pAddr The servers IP address.
+	 */
+	public ServletWebServer(int pPort, InetAddress pAddr) {
+		super(pPort, pAddr);
+	}
+
+	protected ThreadPool.Task newTask(WebServer pWebServer,
+									  XmlRpcStreamServer pXmlRpcServer,
+									  Socket pSocket) throws IOException {
+		return new ServletConnection(pWebServer, pXmlRpcServer, pSocket);
+	}
+}

Modified: webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/WebServer.java
URL: http://svn.apache.org/viewcvs/webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/WebServer.java?rev=328736&r1=328735&r2=328736&view=diff
==============================================================================
--- webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/WebServer.java (original)
+++ webservices/xmlrpc/branches/b20050512_streaming/src/java/org/apache/xmlrpc/webserver/WebServer.java Wed Oct 26 14:13:21 2005
@@ -248,7 +248,12 @@
 		}
 		return false;
 	}
-	
+
+	protected ThreadPool.Task newTask(WebServer pServer, XmlRpcStreamServer pXmlRpcServer,
+						   			  Socket pSocket) throws IOException {
+		return new Connection(pServer, pXmlRpcServer, pSocket);
+	}
+
 	/**
 	 * Listens for client requests until stopped.  Call {@link
 	 * #start()} to invoke this method, and {@link #shutdown()} to
@@ -275,8 +280,8 @@
 					
 					try {
 						if (allowConnection(socket)) {
-							final Connection con = new Connection(this, server, socket);
-							if (pool.startTask(con)) {
+							final ThreadPool.Task task = newTask(this, server, socket);
+							if (pool.startTask(task)) {
 								socket = null;
 							} else {
 								log("Maximum load of " + pool.getMaxThreads()