You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2012/05/14 18:23:52 UTC
svn commit: r1338274 - in
/commons/proper/vfs/trunk/core/src/test/java/org/apache/commons/vfs2:
provider/http/test/HttpProviderTestCase.java
provider/url/test/UrlProviderHttpTestCase.java util/NHttpServer.java
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;
}
+
}