Index: module-main/src/main/java/org/apache/http/protocol/UriPatternMatcher.java =================================================================== --- module-main/src/main/java/org/apache/http/protocol/UriPatternMatcher.java (revision 0) +++ module-main/src/main/java/org/apache/http/protocol/UriPatternMatcher.java (revision 0) @@ -0,0 +1,127 @@ +/* + * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/branches/limewire_contrib/module-main/src/main/java/org/apache/http/protocol/HttpRequestHandlerRegistry.java $ + * $Revision: 613298 $ + * $Date: 2008-01-18 17:09:22 -0500 (Fri, 18 Jan 2008) $ + * + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.http.protocol; + +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * Maintains a map of objects keyed by a request URI pattern. + * Instances can be looked up by request URI.
+ * Patterns may have three formats: + * + * + * @author Oleg Kalnichevski + * + * @version $Revision: 613298 $ + */ +public class UriPatternMatcher { + + private final Map handlerMap; + + public UriPatternMatcher() { + super(); + this.handlerMap = new HashMap(); + } + + public void register(final String pattern, final Object handler) { + if (pattern == null) { + throw new IllegalArgumentException("URI request pattern may not be null"); + } + if (handler == null) { + throw new IllegalArgumentException("HTTP request handelr may not be null"); + } + this.handlerMap.put(pattern, handler); + } + + public void unregister(final String pattern) { + if (pattern == null) { + return; + } + this.handlerMap.remove(pattern); + } + + public void setHandlers(final Map map) { + if (map == null) { + throw new IllegalArgumentException("Map of handlers may not be null"); + } + this.handlerMap.clear(); + this.handlerMap.putAll(map); + } + + public Object lookup(String requestURI) { + if (requestURI == null) { + throw new IllegalArgumentException("Request URI may not be null"); + } + //Strip away the query part part if found + int index = requestURI.indexOf("?"); + if (index != -1) { + requestURI = requestURI.substring(0, index); + } + + // direct match? + Object handler = this.handlerMap.get(requestURI); + if (handler == null) { + // pattern match? + String bestMatch = null; + for (Iterator it = this.handlerMap.keySet().iterator(); it.hasNext();) { + String pattern = (String) it.next(); + if (matchUriRequestPattern(pattern, requestURI)) { + // we have a match. is it any better? + if (bestMatch == null + || (bestMatch.length() < pattern.length()) + || (bestMatch.length() == pattern.length() && pattern.endsWith("*"))) { + handler = this.handlerMap.get(pattern); + bestMatch = pattern; + } + } + } + } + return handler; + } + + protected boolean matchUriRequestPattern(final String pattern, final String requestUri) { + if (pattern.equals("*")) { + return true; + } else { + return + (pattern.endsWith("*") && requestUri.startsWith(pattern.substring(0, pattern.length() - 1))) || + (pattern.startsWith("*") && requestUri.endsWith(pattern.substring(1, pattern.length()))); + } + } + +} Property changes on: module-main/src/main/java/org/apache/http/protocol/UriPatternMatcher.java ___________________________________________________________________ Name: svn:executable + * Index: module-main/src/main/java/org/apache/http/protocol/HttpRequestHandlerRegistry.java =================================================================== --- module-main/src/main/java/org/apache/http/protocol/HttpRequestHandlerRegistry.java (revision 629844) +++ module-main/src/main/java/org/apache/http/protocol/HttpRequestHandlerRegistry.java (working copy) @@ -31,8 +31,6 @@ package org.apache.http.protocol; -import java.util.HashMap; -import java.util.Iterator; import java.util.Map; /** @@ -52,77 +50,33 @@ */ public class HttpRequestHandlerRegistry implements HttpRequestHandlerResolver { - private final Map handlerMap; + private final UriPatternMatcher matcher; public HttpRequestHandlerRegistry() { - super(); - this.handlerMap = new HashMap(); + matcher = new UriPatternMatcher(); } public void register(final String pattern, final HttpRequestHandler handler) { - if (pattern == null) { - throw new IllegalArgumentException("URI request pattern may not be null"); - } - if (handler == null) { - throw new IllegalArgumentException("HTTP request handelr may not be null"); - } - this.handlerMap.put(pattern, handler); + matcher.register(pattern, handler); } public void unregister(final String pattern) { - if (pattern == null) { - return; - } - this.handlerMap.remove(pattern); + matcher.unregister(pattern); } public void setHandlers(final Map map) { - if (map == null) { - throw new IllegalArgumentException("Map of handlers may not be null"); - } - this.handlerMap.clear(); - this.handlerMap.putAll(map); + matcher.setHandlers(map); } public HttpRequestHandler lookup(String requestURI) { - if (requestURI == null) { - throw new IllegalArgumentException("Request URI may not be null"); - } - //Strip away the query part part if found - int index = requestURI.indexOf("?"); - if (index != -1) { - requestURI = requestURI.substring(0, index); - } - - // direct match? - Object handler = this.handlerMap.get(requestURI); - if (handler == null) { - // pattern match? - String bestMatch = null; - for (Iterator it = this.handlerMap.keySet().iterator(); it.hasNext();) { - String pattern = (String) it.next(); - if (matchUriRequestPattern(pattern, requestURI)) { - // we have a match. is it any better? - if (bestMatch == null - || (bestMatch.length() < pattern.length()) - || (bestMatch.length() == pattern.length() && pattern.endsWith("*"))) { - handler = this.handlerMap.get(pattern); - bestMatch = pattern; - } - } - } - } - return (HttpRequestHandler) handler; + return (HttpRequestHandler)matcher.lookup(requestURI); } + // TODO: Really this method should disappear, but doing so would be API + // incompatible, since this class isn't final. + @Deprecated protected boolean matchUriRequestPattern(final String pattern, final String requestUri) { - if (pattern.equals("*")) { - return true; - } else { - return - (pattern.endsWith("*") && requestUri.startsWith(pattern.substring(0, pattern.length() - 1))) || - (pattern.startsWith("*") && requestUri.endsWith(pattern.substring(1, pattern.length()))); - } + return matcher.matchUriRequestPattern(pattern, requestUri); } } Index: module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java =================================================================== --- module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java (revision 629844) +++ module-nio/src/test/java/org/apache/http/nio/protocol/TestAsyncNHttpHandlers.java (working copy) @@ -237,13 +237,9 @@ responseData.add(new ByteSequence()); } - NHttpRequestHandler requestHandler = new NHttpRequestHandler() { + NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() { - public ConsumingNHttpEntity entityRequest( - HttpEntityEnclosingRequest request, HttpContext context) { - return null; - } - + @Override public void handle( HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { @@ -370,8 +366,9 @@ responseData.add(new ByteSequence()); } - NHttpRequestHandler requestHandler = new NHttpRequestHandler() { + NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() { + @Override public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { @@ -380,6 +377,7 @@ new HeapByteBufferAllocator()); } + @Override public void handle( HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { @@ -507,8 +505,9 @@ responseData.add(new ByteSequence()); } - NHttpRequestHandler requestHandler = new NHttpRequestHandler() { + NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() { + @Override public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { @@ -517,6 +516,7 @@ new HeapByteBufferAllocator()); } + @Override public void handle( HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { @@ -649,8 +649,9 @@ responseData.add(new ByteSequence()); } - NHttpRequestHandler requestHandler = new NHttpRequestHandler() { + NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() { + @Override public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { @@ -659,6 +660,7 @@ new HeapByteBufferAllocator()); } + @Override public void handle( HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { @@ -791,8 +793,9 @@ responseData.add(new ByteSequence()); } - NHttpRequestHandler requestHandler = new NHttpRequestHandler() { + NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() { + @Override public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { @@ -801,8 +804,9 @@ new HeapByteBufferAllocator()); } + @Override public void handle( - HttpRequest request, HttpResponse response, HttpContext context) + HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { if (request instanceof HttpEntityEnclosingRequest) { HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); @@ -926,8 +930,9 @@ final RequestCount requestCount = new RequestCount(reqNo); final ResponseSequence responses = new ResponseSequence(); - NHttpRequestHandler requestHandler = new NHttpRequestHandler() { + NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() { + @Override public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { @@ -936,6 +941,7 @@ new HeapByteBufferAllocator()); } + @Override public void handle( HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { @@ -1084,8 +1090,9 @@ final String[] method = new String[1]; - NHttpRequestHandler requestHandler = new NHttpRequestHandler() { + NHttpRequestHandler requestHandler = new SimpleNHttpRequestHandler() { + @Override public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { @@ -1094,6 +1101,7 @@ new HeapByteBufferAllocator()); } + @Override public void handle( HttpRequest request, HttpResponse response, HttpContext context) throws HttpException, IOException { Index: module-nio/src/main/java/org/apache/http/nio/protocol/NHttpResponseTrigger.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/protocol/NHttpResponseTrigger.java (revision 0) +++ module-nio/src/main/java/org/apache/http/nio/protocol/NHttpResponseTrigger.java (revision 0) @@ -0,0 +1,30 @@ +package org.apache.http.nio.protocol; + +import java.io.IOException; + +import org.apache.http.HttpException; +import org.apache.http.HttpResponse; + +/** + * A trigger to allow {@link AsyncNHttpServiceHandler} to asynchronously + * process requests, before committing to a reply. + */ +public interface NHttpResponseTrigger { + + /** + * Submits a response for sending. + */ + void submitResponse(HttpResponse response); + + /** + * Submits a protocol exception that was generated while + * processing a request. + */ + void handleException(HttpException httpEx); + + /** + * Submits an IOException that was generated while + * processing a request. + */ + void handleException(IOException ioEx); +} Property changes on: module-nio/src/main/java/org/apache/http/nio/protocol/NHttpResponseTrigger.java ___________________________________________________________________ Name: svn:executable + * Index: module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestHandler.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestHandler.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestHandler.java (working copy) @@ -40,12 +40,21 @@ import org.apache.http.nio.entity.ConsumingNHttpEntity; import org.apache.http.protocol.HttpContext; +/** + * A handler for processing asynchronous requests. + * + * Implementations must call one of + * {@link NHttpResponseTrigger NHttpResponseTrigger's} methods to indicate the + * request was processed. Failure to do so could cause a response never + * to be sent (and prevent further requests from being processed). + */ public interface NHttpRequestHandler { - ConsumingNHttpEntity entityRequest(HttpEntityEnclosingRequest request, HttpContext context) - throws HttpException, IOException; + ConsumingNHttpEntity entityRequest(HttpEntityEnclosingRequest request, + HttpContext context) throws HttpException, IOException; - void handle(HttpRequest request, HttpResponse response, HttpContext context) - throws HttpException, IOException; + void handle(HttpRequest request, HttpResponse response, + NHttpResponseTrigger trigger, HttpContext context) + throws HttpException, IOException; } Index: module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpServiceHandler.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpServiceHandler.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/protocol/AsyncNHttpServiceHandler.java (working copy) @@ -52,7 +52,6 @@ import org.apache.http.nio.NHttpServiceHandler; import org.apache.http.nio.entity.ConsumingNHttpEntity; import org.apache.http.nio.entity.ConsumingNHttpEntityTemplate; -import org.apache.http.nio.entity.ContentListener; import org.apache.http.nio.entity.NByteArrayEntity; import org.apache.http.nio.entity.ProducingNHttpEntity; import org.apache.http.nio.entity.SkipContentListener; @@ -63,39 +62,30 @@ import org.apache.http.protocol.ExecutionContext; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpProcessor; -import org.apache.http.protocol.HttpRequestHandler; import org.apache.http.util.EncodingUtils; /** * HTTP service handler implementation that works with * {@link ConsumingNHttpEntity} and {@link ProducingNHttpEntity}. The contents * of HTTP headers are stored in memory, HTTP entities are streamed directly - * from the NHttpEntity to the underlying channel (and vice versa). + * from the entities to the underlying channel (and vice versa). *

- * When using this {@link NHttpServiceHandler}, it is important to ensure that - * entities supplied for writing implement ProducingNHttpEntity. Doing - * so will allow the entity to be written out asynchronously. If entities - * supplied for writing do not implement ProducingNHttpEntity, a delegate is - * added that buffers the entire contents in memory. Additionally, the buffering - * might take place in the I/O thread, which could cause I/O to block - * temporarily. For best results, ensure that all entities set on - * {@link HttpResponse HttpResponses} from - * {@link HttpRequestHandler HttpRequestHandlers} implement + * When using this, it is important to ensure that entities supplied for writing + * implement ProducingNHttpEntity. Doing so will allow the entity to be written + * out asynchronously. If entities supplied for writing do not implement + * ProducingNHttpEntity, a delegate is added that buffers the entire contents in + * memory. Additionally, the buffering might take place in the I/O thread, which + * could cause I/O to block temporarily. For best results, ensure that all + * entities set on {@link HttpResponse HttpResponses} from + * {@link NHttpRequestHandler NHttpRequestHandlers} implement * ProducingNHttpEntity. *

- * If incoming requests have entities, HttpRequestHandlers must not call - * {@link HttpEntity#getContent()}. Doing so will throw an - * {@link UnsupportedOperationException}. Instead, handlers must expect that - * incoming entities implement ConsumingNHttpEntity and install a - * {@link ContentListener} on those entities. The ContentListener will be - * notified when new data is available for reading. After all data has been - * read, the response will automatically be sent. - *

- * To support legacy HttpRequestHandlers that do use getContent(), you can wrap - * the handler within a {@link NBlockingHttpRequestHandler}. Doing so will - * allow the handler to be processed on a new thread, in a blocking manner. - *

- * + * If incoming requests are entity requests, NHttpRequestHandlers are expected + * to return a ConsumingNHttpEntity for reading the content. After the entity is + * finished reading the data, + * {@link NHttpRequestHandler#handle(HttpRequest, HttpResponse, NHttpResponseTrigger, HttpContext)} is + * called to generate a response. + * * @author Oleg Kalnichevski * @author Sam Berlin * @author Steffen Pingel @@ -369,24 +359,17 @@ response.setParams( new DefaultedHttpParams(response.getParams(), this.params)); + NHttpResponseTrigger trigger = new ResponseTrigger(conn, request, context, this); try { - this.httpProcessor.process(request, context); - NHttpRequestHandler handler = getRequestHandler(request); if (handler != null) { - handler.handle(request, response, context); + handler.handle(request, response, trigger, context); } else { response.setStatusCode(HttpStatus.SC_NOT_IMPLEMENTED); } - sendResponse(conn, request, response); - } catch (HttpException ex) { - response = this.responseFactory.newHttpResponse(HttpVersion.HTTP_1_0, - HttpStatus.SC_INTERNAL_SERVER_ERROR, context); - response.setParams( - new DefaultedHttpParams(response.getParams(), this.params)); - handleException(ex, response); + trigger.handleException(ex); } } @@ -431,27 +414,27 @@ return handler; } - static class ServerConnState { + protected static class ServerConnState { private NHttpRequestHandler requestHandler; private ConsumingNHttpEntity consumingEntity; private ProducingNHttpEntity producingEntity; - void finishInput() { + public void finishInput() { if (this.consumingEntity != null) { this.consumingEntity.finish(); this.consumingEntity = null; } } - void finishOutput() { + public void finishOutput() { if (this.producingEntity != null) { this.producingEntity.finish(); this.producingEntity = null; } } - void reset() { + public void reset() { finishInput(); finishOutput(); this.requestHandler = null; @@ -482,5 +465,57 @@ } } + + static class ResponseTrigger implements NHttpResponseTrigger { + private final AsyncNHttpServiceHandler handler; + private final NHttpServerConnection conn; + private final HttpContext context; + private final HttpRequest request; + + public ResponseTrigger(NHttpServerConnection conn, HttpRequest request, + HttpContext context, AsyncNHttpServiceHandler handler) { + this.conn = conn; + this.request = request; + this.handler = handler; + this.context = context; + } + + @Override + public void handleException(HttpException httpEx) { + HttpResponse response = handler.responseFactory.newHttpResponse(HttpVersion.HTTP_1_0, + HttpStatus.SC_INTERNAL_SERVER_ERROR, context); + response.setParams( + new DefaultedHttpParams(response.getParams(), handler.params)); + handler.handleException(httpEx, response); + submitResponse(response); + } + + @Override + public void handleException(IOException ioEx) { + handler.shutdownConnection(conn, ioEx); + if (handler.eventListener != null) { + handler.eventListener.fatalIOException(ioEx, conn); + } + } + + @Override + public void submitResponse(HttpResponse response) { + try { + handler.sendResponse(conn, request, response); + } catch(IOException iox) { + handler.shutdownConnection(conn, iox); + if (handler.eventListener != null) { + handler.eventListener.fatalIOException(iox, conn); + } + } catch(HttpException httpX) { + handler.closeConnection(conn, httpX); + if (handler.eventListener != null) { + handler.eventListener.fatalProtocolException(httpX, conn); + } + } + } + + } + } Index: module-nio/src/main/java/org/apache/http/nio/protocol/SimpleNHttpRequestHandler.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/protocol/SimpleNHttpRequestHandler.java (revision 0) +++ module-nio/src/main/java/org/apache/http/nio/protocol/SimpleNHttpRequestHandler.java (revision 0) @@ -0,0 +1,38 @@ +package org.apache.http.nio.protocol; + +import java.io.IOException; + +import org.apache.http.HttpEntityEnclosingRequest; +import org.apache.http.HttpException; +import org.apache.http.HttpRequest; +import org.apache.http.HttpResponse; +import org.apache.http.nio.entity.ConsumingNHttpEntity; +import org.apache.http.protocol.HttpContext; + +/** + * A simple implementation of {@link NHttpRequestHandler} that abstracts away + * the need to use {@link NHttpResponseTrigger}, or to handle entities. + * Implementations need only to implement + * {@link SimpleNHttpRequestHandler#handle(HttpRequest, HttpResponse, HttpContext)}. + */ +public abstract class SimpleNHttpRequestHandler implements NHttpRequestHandler { + + @Override + public ConsumingNHttpEntity entityRequest( + HttpEntityEnclosingRequest request, HttpContext context) + throws HttpException, IOException { + return null; + } + + @Override + public final void handle(HttpRequest request, HttpResponse response, + NHttpResponseTrigger trigger, HttpContext context) + throws HttpException, IOException { + handle(request, response, context); + trigger.submitResponse(response); + } + + public abstract void handle(HttpRequest request, HttpResponse response, + HttpContext context) throws HttpException, IOException; + +} Property changes on: module-nio/src/main/java/org/apache/http/nio/protocol/SimpleNHttpRequestHandler.java ___________________________________________________________________ Name: svn:executable + * Index: module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestHandlerRegistry.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestHandlerRegistry.java (revision 0) +++ module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestHandlerRegistry.java (revision 0) @@ -0,0 +1,44 @@ +package org.apache.http.nio.protocol; + +import java.util.Map; + +import org.apache.http.protocol.UriPatternMatcher; + +/** + * Maintains a map of HTTP request handlers keyed by a request URI pattern. + * {@link NHttpRequestHandler} instances can be looked up by request URI + * using the {@link NHttpRequestHandlerResolver} interface.
+ * Patterns may have three formats: + *

+ * + * @version $Revision: 613298 $ + */ +public class NHttpRequestHandlerRegistry implements NHttpRequestHandlerResolver { + + private final UriPatternMatcher matcher; + + public NHttpRequestHandlerRegistry() { + matcher = new UriPatternMatcher(); + } + + public void register(final String pattern, final NHttpRequestHandler handler) { + matcher.register(pattern, handler); + } + + public void unregister(final String pattern) { + matcher.unregister(pattern); + } + + public void setHandlers(final Map map) { + matcher.setHandlers(map); + } + + public NHttpRequestHandler lookup(String requestURI) { + return (NHttpRequestHandler) matcher.lookup(requestURI); + } + +} Property changes on: module-nio/src/main/java/org/apache/http/nio/protocol/NHttpRequestHandlerRegistry.java ___________________________________________________________________ Name: svn:executable + * Index: module-nio/src/main/java/org/apache/http/nio/entity/ProducingNHttpEntity.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/entity/ProducingNHttpEntity.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/entity/ProducingNHttpEntity.java (working copy) @@ -1,7 +1,7 @@ /* - * $HeadURL:$ - * $Revision:$ - * $Date:$ + * $HeadURL$ + * $Revision$ + * $Date$ * * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one @@ -51,6 +51,9 @@ */ void produceContent(ContentEncoder encoder, IOControl ioctrl) throws IOException; + /** + * Notification that any resources allocated for writing can be released. + */ void finish(); } Index: module-nio/src/main/java/org/apache/http/nio/entity/SkipContentListener.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/entity/SkipContentListener.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/entity/SkipContentListener.java (working copy) @@ -38,6 +38,9 @@ import org.apache.http.nio.IOControl; import org.apache.http.nio.util.ByteBufferAllocator; +/** + * A simple {@link ContentListener} that reads and ignores all content. + */ public class SkipContentListener implements ContentListener { private final ByteBuffer buffer; Index: module-nio/src/main/java/org/apache/http/nio/entity/ConsumingNHttpEntityTemplate.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/entity/ConsumingNHttpEntityTemplate.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/entity/ConsumingNHttpEntityTemplate.java (working copy) @@ -40,6 +40,10 @@ import org.apache.http.nio.ContentDecoder; import org.apache.http.nio.IOControl; +/** + * A {@link ConsumingNHttpEntity} that forwards available content to a + * {@link ContentListener}. + */ public class ConsumingNHttpEntityTemplate extends HttpEntityWrapper implements ConsumingNHttpEntity { Index: module-nio/src/main/java/org/apache/http/nio/entity/NByteArrayEntity.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/entity/NByteArrayEntity.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/entity/NByteArrayEntity.java (working copy) @@ -44,8 +44,6 @@ /** * An entity whose content is retrieved from a byte array. - * This entity is intended for use only as an {@link NHttpEntity}. - * Blocking methods are not supported. * * @author Sam Berlin * Index: module-nio/src/main/java/org/apache/http/nio/entity/NStringEntity.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/entity/NStringEntity.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/entity/NStringEntity.java (working copy) @@ -46,8 +46,6 @@ /** * An entity whose content is retrieved from a string. - * This entity is intended for use only as an {@link NHttpEntity}. - * Blocking methods are not supported. * * @author Sam Berlin * Index: module-nio/src/main/java/org/apache/http/nio/entity/BufferingNHttpEntity.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/entity/BufferingNHttpEntity.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/entity/BufferingNHttpEntity.java (working copy) @@ -42,8 +42,14 @@ import org.apache.http.nio.util.ByteBufferAllocator; import org.apache.http.nio.util.SimpleInputBuffer; -public class BufferingNHttpEntity - extends HttpEntityWrapper implements ConsumingNHttpEntity { +/** + * A {@link ConsumingNHttpEntity} that consumes content into a buffer. The + * content can be retrieved as an InputStream via + * {@link HttpEntity#getContent()}, or written to an output stream via + * {@link HttpEntity#writeTo(OutputStream)}. + */ +public class BufferingNHttpEntity extends HttpEntityWrapper implements + ConsumingNHttpEntity { private final static int BUFFER_SIZE = 2048; Index: module-nio/src/main/java/org/apache/http/nio/entity/NFileEntity.java =================================================================== --- module-nio/src/main/java/org/apache/http/nio/entity/NFileEntity.java (revision 629844) +++ module-nio/src/main/java/org/apache/http/nio/entity/NFileEntity.java (working copy) @@ -46,8 +46,6 @@ /** * An entity whose content is retrieved from from a file. - * This entity is intended for use only as an {@link NHttpEntity}. - * Blocking methods are not supported. * * @author Sam Berlin * Index: module-nio/src/examples/org/apache/http/examples/nio/NHttpFileServer.java =================================================================== --- module-nio/src/examples/org/apache/http/examples/nio/NHttpFileServer.java (revision 629844) +++ module-nio/src/examples/org/apache/http/examples/nio/NHttpFileServer.java (working copy) @@ -61,6 +61,8 @@ import org.apache.http.nio.protocol.EventListener; import org.apache.http.nio.protocol.NHttpRequestHandler; import org.apache.http.nio.protocol.NHttpRequestHandlerResolver; +import org.apache.http.nio.protocol.NHttpResponseTrigger; +import org.apache.http.nio.protocol.SimpleNHttpRequestHandler; import org.apache.http.nio.reactor.IOEventDispatch; import org.apache.http.nio.reactor.ListeningIOReactor; import org.apache.http.params.BasicHttpParams; @@ -138,7 +140,7 @@ System.out.println("Shutdown"); } - static class HttpFileHandler implements NHttpRequestHandler { + static class HttpFileHandler extends SimpleNHttpRequestHandler { private final String docRoot; private final boolean useFileChannels; @@ -148,6 +150,7 @@ this.useFileChannels = useFileChannels; } + @Override public ConsumingNHttpEntity entityRequest( HttpEntityEnclosingRequest request, HttpContext context) throws HttpException, IOException { @@ -156,6 +159,7 @@ new FileWriteListener(useFileChannels)); } + @Override public void handle( final HttpRequest request, final HttpResponse response,