Author: ggregory Date: Mon May 14 16:23:52 2012 New Revision: 1338274 URL: http://svn.apache.org/viewvc?rev=1338274&view=rev Log: Update httpcore-nio used for testing to 4.2 from 4.1.4.
Modified: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/http/test/HttpProviderTestCase.java commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/url/test/UrlProviderHttpTestCase.java commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/NHttpServer.java Modified: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/http/test/HttpProviderTestCase.java URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/http/test/HttpProviderTestCase.java?rev=1338274&r1=1338273&r2=1338274&view=diff ============================================================================== --- commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/http/test/HttpProviderTestCase.java (original) +++ commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/http/test/HttpProviderTestCase.java Mon May 14 16:23:52 2012 @@ -16,6 +16,7 @@ */ package org.apache.commons.vfs2.provider.http.test; +import java.io.File; import java.io.IOException; import junit.framework.Test; @@ -59,7 +60,7 @@ public class HttpProviderTestCase extend private static void setUpClass() throws Exception { Server = new NHttpServer(); - if (!Server.run(SocketPort, getTestDirectory(), 5000)) + if (!Server.run(SocketPort, new File(getTestDirectory()), 5000)) { throw new IllegalStateException("The embedded HTTP server has not completed startup, increase wait time"); } Modified: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/url/test/UrlProviderHttpTestCase.java URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/url/test/UrlProviderHttpTestCase.java?rev=1338274&r1=1338273&r2=1338274&view=diff ============================================================================== --- commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/url/test/UrlProviderHttpTestCase.java (original) +++ commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/provider/url/test/UrlProviderHttpTestCase.java Mon May 14 16:23:52 2012 @@ -16,6 +16,7 @@ */ package org.apache.commons.vfs2.provider.url.test; +import java.io.File; import java.io.IOException; import junit.framework.Test; @@ -59,7 +60,7 @@ public class UrlProviderHttpTestCase ext private static void setUpClass() throws Exception { Server = new NHttpServer(); - if (!Server.run(SocketPort, getTestDirectory(), 5000)) + if (!Server.run(SocketPort, new File(getTestDirectory()), 5000)) { throw new IllegalStateException("The embedded HTTP server has not completed startup, increase wait time"); } Modified: commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/NHttpServer.java URL: http://svn.apache.org/viewvc/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/NHttpServer.java?rev=1338274&r1=1338273&r2=1338274&view=diff ============================================================================== --- commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/NHttpServer.java (original) +++ commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2/util/NHttpServer.java Mon May 14 16:23:52 2012 @@ -33,14 +33,22 @@ import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.URL; import java.net.URLDecoder; +import java.security.KeyManagementException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; import java.util.Date; import java.util.Locale; import java.util.concurrent.Executors; +import javax.net.ssl.KeyManager; +import javax.net.ssl.KeyManagerFactory; +import javax.net.ssl.SSLContext; + import org.apache.commons.httpclient.util.DateUtil; import org.apache.commons.io.IOUtils; -import org.apache.http.HttpEntity; -import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpException; import org.apache.http.HttpHeaders; import org.apache.http.HttpRequest; @@ -48,15 +56,25 @@ import org.apache.http.HttpResponse; import org.apache.http.HttpResponseInterceptor; import org.apache.http.HttpStatus; import org.apache.http.MethodNotSupportedException; +import org.apache.http.entity.ContentType; import org.apache.http.impl.DefaultConnectionReuseStrategy; -import org.apache.http.impl.DefaultHttpResponseFactory; -import org.apache.http.impl.nio.DefaultServerIOEventDispatch; +import org.apache.http.impl.nio.DefaultHttpServerIODispatch; +import org.apache.http.impl.nio.DefaultNHttpServerConnection; +import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory; +import org.apache.http.impl.nio.SSLNHttpServerConnectionFactory; import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor; import org.apache.http.nio.NHttpConnection; +import org.apache.http.nio.NHttpConnectionFactory; +import org.apache.http.nio.NHttpServerConnection; import org.apache.http.nio.entity.NFileEntity; import org.apache.http.nio.entity.NStringEntity; -import org.apache.http.nio.protocol.BufferingHttpServiceHandler; -import org.apache.http.nio.protocol.EventListener; +import org.apache.http.nio.protocol.BasicAsyncRequestConsumer; +import org.apache.http.nio.protocol.BasicAsyncResponseProducer; +import org.apache.http.nio.protocol.HttpAsyncExchange; +import org.apache.http.nio.protocol.HttpAsyncRequestConsumer; +import org.apache.http.nio.protocol.HttpAsyncRequestHandler; +import org.apache.http.nio.protocol.HttpAsyncRequestHandlerRegistry; +import org.apache.http.nio.protocol.HttpAsyncService; import org.apache.http.nio.reactor.IOEventDispatch; import org.apache.http.nio.reactor.IOReactorException; import org.apache.http.nio.reactor.ListeningIOReactor; @@ -64,26 +82,24 @@ import org.apache.http.params.CoreConnec import org.apache.http.params.CoreProtocolPNames; import org.apache.http.params.HttpParams; import org.apache.http.params.SyncBasicHttpParams; +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.protocol.HttpRequestHandlerRegistry; import org.apache.http.protocol.ImmutableHttpProcessor; import org.apache.http.protocol.ResponseConnControl; import org.apache.http.protocol.ResponseContent; import org.apache.http.protocol.ResponseDate; import org.apache.http.protocol.ResponseServer; -import org.apache.http.util.EntityUtils; /** * Adapted from org.apache.http.examples.nio.NHttpServer. * * <p> - * Basic, yet fully functional and spec compliant, HTTP/1.1 server based on the non-blocking I/O model. + * HTTP/1.1 file server based on the non-blocking I/O model and capable of direct channel (zero copy) data transfer. * </p> * <p> - * Please note the purpose of this application is demonstrate the usage of HttpCore APIs. It is NOT intended to demonstrate the most - * efficient way of building an HTTP server. + * Please note the purpose of this application is demonstrate the usage of HttpCore APIs. It is NOT intended to + * demonstrate the most efficient way of building an HTTP server. * </p> * * @version $Id$ @@ -92,96 +108,82 @@ import org.apache.http.util.EntityUtils; public class NHttpServer { - static class EventLogger implements EventListener + static class HttpFileHandler implements HttpAsyncRequestHandler<HttpRequest> { - public void connectionClosed(final NHttpConnection conn) - { - debug("Connection closed: " + conn); - } - - public void connectionOpen(final NHttpConnection conn) - { - debug("Connection open: " + conn); - } - - public void connectionTimeout(final NHttpConnection conn) - { - debug("Connection timed out: " + conn); - } - public void fatalIOException(final IOException ex, final NHttpConnection conn) - { - debug("I/O error: " + ex.getMessage()); - } + private final File docRoot; - public void fatalProtocolException(final HttpException ex, final NHttpConnection conn) + public HttpFileHandler(final File docRoot) { - debug("HTTP error: " + ex.getMessage()); + super(); + this.docRoot = docRoot; } - } - static class HttpFileHandler implements HttpRequestHandler - { - private final String docRoot; - - public HttpFileHandler(final String docRoot) + @Override + public void handle(final HttpRequest request, final HttpAsyncExchange httpexchange, final HttpContext context) + throws HttpException, IOException { - super(); - this.docRoot = docRoot; + final HttpResponse response = httpexchange.getResponse(); + this.handleInternal(request, response, context); + httpexchange.submitResponse(new BasicAsyncResponseProducer(response)); } - public void handle(final HttpRequest request, final HttpResponse response, final HttpContext context) + private void handleInternal(final HttpRequest request, final HttpResponse response, final HttpContext context) throws HttpException, IOException { - String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH); + + final String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH); if (!method.equals("GET") && !method.equals("HEAD") && !method.equals("POST")) { throw new MethodNotSupportedException(method + " method not supported"); } - if (request instanceof HttpEntityEnclosingRequest) - { - HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); - byte[] entityContent = EntityUtils.toByteArray(entity); - debug("Incoming entity content (bytes): " + entityContent.length); - } - - String target = request.getRequestLine().getUri(); + final String target = request.getRequestLine().getUri(); final File file = new File(this.docRoot, URLDecoder.decode(target, "UTF-8")); if (!file.exists()) { + response.setStatusCode(HttpStatus.SC_NOT_FOUND); - NStringEntity entity = new NStringEntity("<html><body><h1>File" + file.getPath() - + " not found</h1></body></html>", "UTF-8"); - entity.setContentType("text/html; charset=UTF-8"); + final NStringEntity entity = new NStringEntity("<html><body><h1>File" + file.getPath() + + " not found</h1></body></html>", ContentType.create("text/html", "UTF-8")); response.setEntity(entity); - debug("File " + file.getPath() + " not found"); + NHttpServer.debug("File " + file.getPath() + " not found"); } else if (!file.canRead()) { + response.setStatusCode(HttpStatus.SC_FORBIDDEN); - NStringEntity entity = new NStringEntity("<html><body><h1>Access denied</h1></body></html>", "UTF-8"); - entity.setContentType("text/html; charset=UTF-8"); + final NStringEntity entity = new NStringEntity("<html><body><h1>Access denied</h1></body></html>", + ContentType.create("text/html", "UTF-8")); response.setEntity(entity); - debug("Cannot read file " + file.getPath()); + NHttpServer.debug("Cannot read file " + file.getPath()); } else { + final NHttpConnection conn = (NHttpConnection) context.getAttribute(ExecutionContext.HTTP_CONNECTION); response.setStatusCode(HttpStatus.SC_OK); - NFileEntity body = new NFileEntity(file, "text/html"); + final NFileEntity body = new NFileEntity(file, ContentType.create("text/html")); response.setEntity(body); if (!response.containsHeader(HttpHeaders.LAST_MODIFIED)) { response.addHeader(HttpHeaders.LAST_MODIFIED, DateUtil.formatDate(new Date(file.lastModified()))); } - debug("Serving file " + file.getPath()); + NHttpServer.debug(conn + ": serving file " + file.getPath()); } } + + @Override + public HttpAsyncRequestConsumer<HttpRequest> processRequest(final HttpRequest request, final HttpContext context) + { + // Buffer request content in memory for simplicity + return new BasicAsyncRequestConsumer(); + } + } static final boolean Debug = false; - private static void debug(String s) + private static void debug(final String s) { if (Debug) { @@ -189,70 +191,138 @@ public class NHttpServer } } - public static void main(String[] args) throws Exception + public static void main(final String[] args) throws Exception { - new NHttpServer().run(0, null, 0); + new NHttpServer().run(Integer.valueOf(args[0]), new File(args[1]), 0); } - public volatile ListeningIOReactor ioReactor; + volatile ListeningIOReactor ioReactor; - public boolean run(final int port, final String docRoot, long waitMillis) throws IOReactorException, + public boolean run(final int port, final File docRoot, final long waitMillis) throws IOReactorException, InterruptedException { Executors.newSingleThreadExecutor().execute(new Runnable() { + @Override public void run() { try { - runBlock(port, docRoot); - } catch (IOReactorException e) + NHttpServer.this.runBlock(port, docRoot); + } catch (final IOReactorException e) + { + throw new IllegalStateException(e); + } catch (final UnrecoverableKeyException e) + { + throw new IllegalStateException(e); + } catch (final KeyStoreException e) + { + throw new IllegalStateException(e); + } catch (final NoSuchAlgorithmException e) + { + throw new IllegalStateException(e); + } catch (final CertificateException e) + { + throw new IllegalStateException(e); + } catch (final IOException e) + { + throw new IllegalStateException(e); + } catch (final KeyManagementException e) { throw new IllegalStateException(e); } } }); - return waitForServerStartup(port, waitMillis); + return this.waitForServerStartup(port, waitMillis); } - private void runBlock(final int port, final String docRoot) throws IOReactorException + public void runBlock(final int port, final File docRoot) throws KeyStoreException, NoSuchAlgorithmException, + CertificateException, IOException, UnrecoverableKeyException, KeyManagementException { - HttpParams params = new SyncBasicHttpParams(); + if (docRoot == null) + { + throw new IllegalArgumentException("No doc root specified."); + } + // HTTP parameters for the server + final HttpParams params = new SyncBasicHttpParams(); params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000) .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024) - .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false) .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true) - .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpComponents/1.1"); - - HttpProcessor httpproc = new ImmutableHttpProcessor(new HttpResponseInterceptor[] - { new ResponseDate(), new ResponseServer(), new ResponseContent(), new ResponseConnControl() }); - - BufferingHttpServiceHandler handler = new BufferingHttpServiceHandler(httpproc, - new DefaultHttpResponseFactory(), new DefaultConnectionReuseStrategy(), params); - - // Set up request handlers - HttpRequestHandlerRegistry reqistry = new HttpRequestHandlerRegistry(); + .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "HttpTest/1.1"); + // Create HTTP protocol processing chain + final HttpProcessor httpproc = new ImmutableHttpProcessor(new HttpResponseInterceptor[] + { + // Use standard server-side protocol interceptors + new ResponseDate(), + new ResponseServer(), + new ResponseContent(), + new ResponseConnControl() }); + // Create request handler registry + final HttpAsyncRequestHandlerRegistry reqistry = new HttpAsyncRequestHandlerRegistry(); + // Register the default handler for all URIs reqistry.register("*", new HttpFileHandler(docRoot)); + // Create server-side HTTP protocol handler + final HttpAsyncService protocolHandler = new HttpAsyncService(httpproc, new DefaultConnectionReuseStrategy(), + reqistry, params) + { - handler.setHandlerResolver(reqistry); + @Override + public void closed(final NHttpServerConnection conn) + { + NHttpServer.debug(conn + ": connection closed"); + super.closed(conn); + } - // Provide an event logger - handler.setEventListener(new EventLogger()); + @Override + public void connected(final NHttpServerConnection conn) + { + NHttpServer.debug(conn + ": connection open"); + super.connected(conn); + } - IOEventDispatch ioEventDispatch = new DefaultServerIOEventDispatch(handler, params); - ioReactor = new DefaultListeningIOReactor(2, params); + }; + // Create HTTP connection factory + NHttpConnectionFactory<DefaultNHttpServerConnection> connFactory; + if (port == 8443) + { + // Initialize SSL context + final ClassLoader cl = NHttpServer.class.getClassLoader(); + final URL url = cl.getResource("my.keystore"); + if (url == null) + { + NHttpServer.debug("Keystore not found"); + System.exit(1); + } + final KeyStore keystore = KeyStore.getInstance("jks"); + keystore.load(url.openStream(), "secret".toCharArray()); + final KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); + kmfactory.init(keystore, "secret".toCharArray()); + final KeyManager[] keymanagers = kmfactory.getKeyManagers(); + final SSLContext sslcontext = SSLContext.getInstance("TLS"); + sslcontext.init(keymanagers, null, null); + connFactory = new SSLNHttpServerConnectionFactory(sslcontext, null, params); + } else + { + connFactory = new DefaultNHttpServerConnectionFactory(params); + } + // Create server-side I/O event dispatch + final IOEventDispatch ioEventDispatch = new DefaultHttpServerIODispatch(protocolHandler, connFactory); + // Create server-side I/O reactor + this.ioReactor = new DefaultListeningIOReactor(); try { - ioReactor.listen(new InetSocketAddress(port)); - ioReactor.execute(ioEventDispatch); - } catch (InterruptedIOException ex) + // Listen of the given port + this.ioReactor.listen(new InetSocketAddress(port)); + // Ready to go! + this.ioReactor.execute(ioEventDispatch); + } catch (final InterruptedIOException ex) { - debug("Interrupted"); - } catch (IOException e) + System.err.println("Interrupted"); + } catch (final IOException e) { - debug("I/O error: " + e.getMessage()); + System.err.println("I/O error: " + e.getMessage()); } - debug("Shutdown"); + NHttpServer.debug("Shutdown"); } public void stop() throws IOException @@ -261,26 +331,15 @@ public class NHttpServer { this.ioReactor.shutdown(2000); } - } - /** - * Waits {@code waitMillis} for the server to start on the given {@code port} - * - * @param port - * The port the server is running on - * @param waitMillis - * How long to wail in milliseconds. - * @throws InterruptedException - * If waiting is interrupted - */ - private boolean waitForServerStartup(final int port, long waitMillis) throws InterruptedException + private boolean waitForServerStartup(final int port, final long waitMillis) throws InterruptedException { final long endWait = System.currentTimeMillis() + waitMillis; final String urlSpec = "http://localhost:" + port; try { - URL url = new URL(urlSpec); + final URL url = new URL(urlSpec); InputStream inputStream = null; while (System.currentTimeMillis() < endWait && inputStream == null) { @@ -292,18 +351,19 @@ public class NHttpServer IOUtils.closeQuietly(inputStream); return true; } - } catch (IOException e) + } catch (final IOException e) { // ignore - // System.out.println("While waiting: " + e); + // debug("While waiting: " + e); // e.printStackTrace(); } Thread.sleep(100); } - } catch (MalformedURLException e) + } catch (final MalformedURLException e) { throw new IllegalStateException("Error in test code for URL " + urlSpec); } return false; } + }