You are viewing a plain text version of this content. The canonical link for it is here.
Posted to droids-commits@incubator.apache.org by ol...@apache.org on 2008/11/03 16:23:02 UTC
svn commit: r710092 - in /incubator/droids/trunk: ./
src/java/org/apache/droids/api/ src/java/org/apache/droids/impl/
src/java/org/apache/droids/protocol/ src/test/java/org/apache/droids/impl/
src/test/java/org/apache/droids/localserver/ src/test/java/...
Author: olegk
Date: Mon Nov 3 08:23:01 2008
New Revision: 710092
URL: http://svn.apache.org/viewvc?rev=710092&view=rev
Log:
Added an end to end test case based on an embedded HTTP server
Added:
incubator/droids/trunk/src/test/java/org/apache/droids/impl/TestSimpleDroid.java
incubator/droids/trunk/src/test/java/org/apache/droids/localserver/
incubator/droids/trunk/src/test/java/org/apache/droids/localserver/LocalHttpServer.java
incubator/droids/trunk/src/test/java/org/apache/droids/localserver/ResourceHandler.java
incubator/droids/trunk/src/test/java/resources/
incubator/droids/trunk/src/test/java/resources/page1_html
incubator/droids/trunk/src/test/java/resources/page2_html
incubator/droids/trunk/src/test/java/resources/page3_html
incubator/droids/trunk/src/test/java/resources/page4_html
incubator/droids/trunk/src/test/java/resources/start_html
Modified:
incubator/droids/trunk/pom.xml
incubator/droids/trunk/src/java/org/apache/droids/api/TaskMaster.java
incubator/droids/trunk/src/java/org/apache/droids/impl/MultiThreadedTaskMaster.java
incubator/droids/trunk/src/java/org/apache/droids/protocol/HttpBase.java
Modified: incubator/droids/trunk/pom.xml
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/pom.xml?rev=710092&r1=710091&r2=710092&view=diff
==============================================================================
--- incubator/droids/trunk/pom.xml (original)
+++ incubator/droids/trunk/pom.xml Mon Nov 3 08:23:01 2008
@@ -137,6 +137,15 @@
</includes>
</resource>
</resources>
+ <testResources>
+ <testResource>
+ <directory>src/test/java</directory>
+ <filtering>false</filtering>
+ <includes>
+ <include>**/resources/**</include>
+ </includes>
+ </testResource>
+ </testResources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
Modified: incubator/droids/trunk/src/java/org/apache/droids/api/TaskMaster.java
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/java/org/apache/droids/api/TaskMaster.java?rev=710092&r1=710091&r2=710092&view=diff
==============================================================================
--- incubator/droids/trunk/src/java/org/apache/droids/api/TaskMaster.java (original)
+++ incubator/droids/trunk/src/java/org/apache/droids/api/TaskMaster.java Mon Nov 3 08:23:01 2008
@@ -17,6 +17,7 @@
package org.apache.droids.api;
import java.util.Date;
+import java.util.concurrent.TimeUnit;
@@ -24,6 +25,7 @@
* Responsible for running all the tasks
*/
public interface TaskMaster<T extends Task> {
+
void processAllTasks( final TaskQueue<T> queue, final Droid<T> droid );
Date getStartTime();
@@ -33,4 +35,7 @@
int getCompletedTasks();
T getLastCompletedTask();
+
+ void awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
+
}
Modified: incubator/droids/trunk/src/java/org/apache/droids/impl/MultiThreadedTaskMaster.java
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/java/org/apache/droids/impl/MultiThreadedTaskMaster.java?rev=710092&r1=710091&r2=710092&view=diff
==============================================================================
--- incubator/droids/trunk/src/java/org/apache/droids/impl/MultiThreadedTaskMaster.java (original)
+++ incubator/droids/trunk/src/java/org/apache/droids/impl/MultiThreadedTaskMaster.java Mon Nov 3 08:23:01 2008
@@ -46,7 +46,6 @@
*/
public void processAllTasks(final TaskQueue<T> queue, final Droid<T> droid)
{
- // TODO Auto-generated method stub
this.queue = queue;
this.droid = droid;
this.startedWorking = new Date();
@@ -219,4 +218,9 @@
public Date getStartTime() {
return startedWorking;
}
+
+ public void awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+ pool.awaitTermination(timeout, unit);
+ }
+
}
Modified: incubator/droids/trunk/src/java/org/apache/droids/protocol/HttpBase.java
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/java/org/apache/droids/protocol/HttpBase.java?rev=710092&r1=710091&r2=710092&view=diff
==============================================================================
--- incubator/droids/trunk/src/java/org/apache/droids/protocol/HttpBase.java (original)
+++ incubator/droids/trunk/src/java/org/apache/droids/protocol/HttpBase.java Mon Nov 3 08:23:01 2008
@@ -148,9 +148,15 @@
protected HttpURLConnection prepareConnection(URL source) throws IOException {
HttpURLConnection urlc = null;
urlc = (HttpURLConnection) source.openConnection();
- urlc.setRequestProperty("User-Agent", userAgent);
- urlc.addRequestProperty("From", from);
- urlc.setRequestProperty("Referer", refer);
+ if (userAgent != null) {
+ urlc.setRequestProperty("User-Agent", userAgent);
+ }
+ if (from != null) {
+ urlc.addRequestProperty("From", from);
+ }
+ if (refer != null) {
+ urlc.setRequestProperty("Referer", refer);
+ }
urlc.setConnectTimeout(timeout);
return urlc;
}
Added: incubator/droids/trunk/src/test/java/org/apache/droids/impl/TestSimpleDroid.java
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/test/java/org/apache/droids/impl/TestSimpleDroid.java?rev=710092&view=auto
==============================================================================
--- incubator/droids/trunk/src/test/java/org/apache/droids/impl/TestSimpleDroid.java (added)
+++ incubator/droids/trunk/src/test/java/org/apache/droids/impl/TestSimpleDroid.java Mon Nov 3 08:23:01 2008
@@ -0,0 +1,147 @@
+/*
+ * 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.
+ */
+package org.apache.droids.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+
+import junit.framework.Assert;
+
+import org.apache.droids.api.Link;
+import org.apache.droids.api.Parse;
+import org.apache.droids.api.Handler;
+import org.apache.droids.delay.SimpleDelayTimer;
+import org.apache.droids.helper.factories.DroidFactory;
+import org.apache.droids.helper.factories.HandlerFactory;
+import org.apache.droids.helper.factories.ParserFactory;
+import org.apache.droids.helper.factories.ProtocolFactory;
+import org.apache.droids.helper.factories.URLFiltersFactory;
+import org.apache.droids.localserver.LocalHttpServer;
+import org.apache.droids.localserver.ResourceHandler;
+import org.apache.droids.net.RegexURLFilter;
+import org.apache.droids.parse.html.HtmlParser;
+import org.apache.droids.protocol.http.Http;
+import org.apache.droids.robot.crawler.CrawlingDroid;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TestSimpleDroid
+{
+
+ protected LocalHttpServer testserver;
+
+ @Before
+ public void initializeLocalTestServer() {
+ this.testserver = new LocalHttpServer();
+ }
+
+ @After
+ public void shutdownLocalTestServer() throws IOException {
+ this.testserver.stop();
+ }
+
+ @Test
+ public void testBasicCrawling() throws Exception
+ {
+ this.testserver.register("*", new ResourceHandler());
+ this.testserver.start();
+
+ String baseURI = "http:/" + this.testserver.getServiceAddress();
+ String targetURI = baseURI + "/start_html";
+
+ final Set<URL> visitedLinks = new HashSet<URL>();
+
+ ParserFactory parserFactory = new ParserFactory();
+ HtmlParser htmlParser = new HtmlParser();
+ htmlParser.setElements(new HashMap<String, String>());
+ htmlParser.getElements().put("a", "href");
+ htmlParser.getElements().put("link", "href");
+ htmlParser.getElements().put("img", "src");
+ htmlParser.getElements().put("script", "src");
+ parserFactory.setMap(new HashMap<String, Object>());
+ parserFactory.getMap().put("text/html", htmlParser);
+
+ ProtocolFactory protocolFactory = new ProtocolFactory();
+ Http httpProtocol = new Http();
+ httpProtocol.setForceAllow(true);
+ httpProtocol.setUserAgent("Droids/1.1");
+
+ protocolFactory.setMap(new HashMap<String, Object>());
+ protocolFactory.getMap().put("http", httpProtocol);
+
+ URLFiltersFactory filtersFactory = new URLFiltersFactory();
+ RegexURLFilter defaultURLFilter = new RegexURLFilter();
+ defaultURLFilter.setFile("classpath:/regex-urlfilter.txt");
+ filtersFactory.setMap(new HashMap<String, Object>());
+ filtersFactory.getMap().put("default", defaultURLFilter);
+
+ HandlerFactory handlerFactory = new HandlerFactory();
+ Handler defaultHandler = new Handler() {
+
+ public void handle(InputStream openStream, URL url, Parse parse) throws Exception {
+ visitedLinks.add(url);
+ }
+
+ };
+ handlerFactory.setMap(new HashMap<String, Object>());
+ handlerFactory.getMap().put("default", defaultHandler);
+
+ DroidFactory<Link> droidFactory = new DroidFactory<Link>();
+ droidFactory.setMap(new HashMap<String, Object>());
+
+ SimpleDelayTimer simpleDelayTimer = new SimpleDelayTimer();
+ simpleDelayTimer.setDelayMillis(100);
+
+ SimpleTaskQueue<Link> simpleQueue = new SimpleTaskQueue<Link>();
+
+ MultiThreadedTaskMaster<Link> taskMaster = new MultiThreadedTaskMaster<Link>();
+ taskMaster.setMaxThreads( 1 );
+ taskMaster.setDelayTimer( simpleDelayTimer );
+
+ CrawlingDroid helloCrawler = new CrawlingDroid( simpleQueue, taskMaster );
+ helloCrawler.setFiltersFactory(filtersFactory);
+ helloCrawler.setParserFactory(parserFactory);
+ helloCrawler.setProtocolFactory(protocolFactory);
+ helloCrawler.setHandlerFactory(handlerFactory);
+
+ Collection<String> initialLocations = new ArrayList<String>();
+ initialLocations.add( targetURI );
+ helloCrawler.setInitialLocations(initialLocations);
+
+ helloCrawler.init();
+ helloCrawler.start();
+
+ helloCrawler.getTaskMaster().awaitTermination(30, TimeUnit.SECONDS);
+
+ Assert.assertFalse(visitedLinks.isEmpty());
+ Assert.assertEquals(5, visitedLinks.size());
+ Assert.assertTrue(visitedLinks.contains(new URL(baseURI + "/start_html")));
+ Assert.assertTrue(visitedLinks.contains(new URL(baseURI + "/page1_html")));
+ Assert.assertTrue(visitedLinks.contains(new URL(baseURI + "/page2_html")));
+ Assert.assertTrue(visitedLinks.contains(new URL(baseURI + "/page3_html")));
+ Assert.assertTrue(visitedLinks.contains(new URL(baseURI + "/page4_html")));
+ }
+
+}
Added: incubator/droids/trunk/src/test/java/org/apache/droids/localserver/LocalHttpServer.java
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/test/java/org/apache/droids/localserver/LocalHttpServer.java?rev=710092&view=auto
==============================================================================
--- incubator/droids/trunk/src/test/java/org/apache/droids/localserver/LocalHttpServer.java (added)
+++ incubator/droids/trunk/src/test/java/org/apache/droids/localserver/LocalHttpServer.java Mon Nov 3 08:23:01 2008
@@ -0,0 +1,328 @@
+/*
+ * 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.
+ */
+package org.apache.droids.localserver;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.http.ConnectionReuseStrategy;
+import org.apache.http.HttpException;
+import org.apache.http.HttpServerConnection;
+import org.apache.http.impl.DefaultConnectionReuseStrategy;
+import org.apache.http.impl.DefaultHttpResponseFactory;
+import org.apache.http.impl.DefaultHttpServerConnection;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.HttpParams;
+import org.apache.http.params.CoreProtocolPNames;
+import org.apache.http.protocol.BasicHttpProcessor;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.BasicHttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.apache.http.protocol.HttpRequestHandlerRegistry;
+import org.apache.http.protocol.HttpService;
+import org.apache.http.protocol.ResponseConnControl;
+import org.apache.http.protocol.ResponseContent;
+import org.apache.http.protocol.ResponseDate;
+import org.apache.http.protocol.ResponseServer;
+
+/**
+ * Local HTTP server for tests that require one.
+ */
+public class LocalHttpServer
+{
+
+ /**
+ * The local address to bind to. The host is an IP number rather than
+ * "localhost" to avoid surprises on hosts that map "localhost" to an IPv6
+ * address or something else. The port is 0 to let the system pick one.
+ */
+ public final static InetSocketAddress TEST_SERVER_ADDR = new InetSocketAddress("127.0.0.1", 0);
+
+ /** The request handler registry. */
+ private final HttpRequestHandlerRegistry handlerRegistry;
+
+ /** The server-side connection re-use strategy. */
+ private final ConnectionReuseStrategy reuseStrategy;
+
+ /**
+ * The HTTP processor. If the interceptors are thread safe and the list is not
+ * modified during operation, the processor is thread safe.
+ */
+ private final BasicHttpProcessor httpProcessor;
+
+ /** The server parameters. */
+ private final HttpParams params;
+
+ /** The server socket, while being served. */
+ private volatile ServerSocket servicedSocket;
+
+ /** The request listening thread, while listening. */
+ private volatile Thread listenerThread;
+
+ /** The number of connections this accepted. */
+ private final AtomicInteger acceptedConnections = new AtomicInteger(0);
+
+ /**
+ * Creates a new test server.
+ */
+ public LocalHttpServer() {
+ this.handlerRegistry = new HttpRequestHandlerRegistry();
+ this.reuseStrategy = new DefaultConnectionReuseStrategy();
+ this.httpProcessor = new BasicHttpProcessor();
+ this.httpProcessor.addInterceptor(new ResponseDate());
+ this.httpProcessor.addInterceptor(new ResponseServer());
+ this.httpProcessor.addInterceptor(new ResponseContent());
+ this.httpProcessor.addInterceptor(new ResponseConnControl());
+ this.params = new BasicHttpParams();
+ this.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, "LocalTestServer/1.1");
+ }
+
+ /**
+ * Returns the number of connections this test server has accepted.
+ */
+ public int getAcceptedConnectionCount() {
+ return this.acceptedConnections.get();
+ }
+
+ /**
+ * Registers a handler with the local registry.
+ *
+ * @param pattern
+ * the URL pattern to match
+ * @param handler
+ * the handler to apply
+ */
+ public void register(String pattern, HttpRequestHandler handler) {
+ this.handlerRegistry.register(pattern, handler);
+ }
+
+ /**
+ * Unregisters a handler from the local registry.
+ *
+ * @param pattern
+ * the URL pattern
+ */
+ public void unregister(String pattern) {
+ this.handlerRegistry.unregister(pattern);
+ }
+
+ /**
+ * Starts this test server. Use {@link #getServicePort getServicePort} to
+ * obtain the port number afterwards.
+ */
+ public void start() throws IOException {
+ if (servicedSocket != null) {
+ return; // Already running
+ }
+
+ ServerSocket ssock = new ServerSocket();
+ ssock.setReuseAddress(true); // probably pointless for port '0'
+ ssock.bind(TEST_SERVER_ADDR);
+ this.servicedSocket = ssock;
+
+ this.listenerThread = new Thread(new RequestListener());
+ this.listenerThread.setDaemon(false);
+ this.listenerThread.start();
+ }
+
+ /**
+ * Stops this test server.
+ */
+ public void stop() throws IOException {
+ if (this.servicedSocket == null) {
+ return; // not running
+ }
+
+ try {
+ this.servicedSocket.close();
+ }
+ catch (IOException iox) {
+ System.out.println("error stopping " + this);
+ iox.printStackTrace(System.out);
+ }
+ finally {
+ this.servicedSocket = null;
+ }
+
+ if (this.listenerThread != null) {
+ this.listenerThread.interrupt();
+ this.listenerThread = null;
+ }
+ }
+
+ @Override
+ public String toString() {
+ ServerSocket ssock = servicedSocket; // avoid synchronization
+ StringBuffer sb = new StringBuffer(80);
+ sb.append("LocalTestServer/");
+ if (ssock == null) {
+ sb.append("stopped");
+ } else {
+ sb.append(ssock.getLocalSocketAddress());
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Obtains the port this server is servicing.
+ *
+ * @return the service port
+ */
+ public int getServicePort() {
+ ServerSocket ssock = this.servicedSocket; // avoid synchronization
+ if (ssock == null) {
+ throw new IllegalStateException("not running");
+ }
+ return ssock.getLocalPort();
+ }
+
+ /**
+ * Obtains the local address the server is listening on
+ *
+ * @return the service address
+ */
+ public SocketAddress getServiceAddress() {
+ ServerSocket ssock = this.servicedSocket; // avoid synchronization
+ if (ssock == null) {
+ throw new IllegalStateException("not running");
+ }
+ return ssock.getLocalSocketAddress();
+ }
+
+ /**
+ * The request listener. Accepts incoming connections and launches a service
+ * thread.
+ */
+ public class RequestListener implements Runnable
+ {
+
+ /** The workers launched from here. */
+ private final Set<Thread> workerThreads;
+
+ public RequestListener() {
+ super();
+ this.workerThreads = Collections.synchronizedSet(new HashSet<Thread>());
+ }
+
+ public void run() {
+ try {
+ while ((servicedSocket != null) && (listenerThread == Thread.currentThread())
+ && !Thread.interrupted()) {
+ try {
+ accept();
+ }
+ catch (Exception e) {
+ ServerSocket ssock = servicedSocket;
+ if ((ssock != null) && !ssock.isClosed()) {
+ System.out.println(LocalHttpServer.this.toString() + " could not accept");
+ e.printStackTrace(System.out);
+ }
+ // otherwise ignore the exception silently
+ break;
+ }
+ }
+ }
+ finally {
+ cleanup();
+ }
+ }
+
+ protected void accept() throws IOException {
+ // Set up HTTP connection
+ Socket socket = servicedSocket.accept();
+ acceptedConnections.incrementAndGet();
+ DefaultHttpServerConnection conn = new DefaultHttpServerConnection();
+ conn.bind(socket, params);
+
+ // Set up the HTTP service
+ HttpService httpService = new HttpService(httpProcessor,
+ new DefaultConnectionReuseStrategy(), new DefaultHttpResponseFactory());
+ httpService.setParams(params);
+ httpService.setHandlerResolver(handlerRegistry);
+
+ // Start worker thread
+ Thread t = new Thread(new Worker(httpService, conn));
+ workerThreads.add(t);
+ t.setDaemon(true);
+ t.start();
+
+ }
+
+ protected void cleanup() {
+ Thread[] threads = workerThreads.toArray(new Thread[0]);
+ for (int i = 0; i < threads.length; i++) {
+ if (threads[i] != null)
+ threads[i].interrupt();
+ }
+ }
+
+ /**
+ * A worker for serving incoming requests.
+ */
+ public class Worker implements Runnable
+ {
+
+ private final HttpService httpservice;
+
+ private final HttpServerConnection conn;
+
+ public Worker(final HttpService httpservice, final HttpServerConnection conn) {
+
+ this.httpservice = httpservice;
+ this.conn = conn;
+ }
+
+ public void run() {
+ HttpContext context = new BasicHttpContext(null);
+ try {
+ while ((servicedSocket != null) && this.conn.isOpen() && !Thread.interrupted()) {
+ this.httpservice.handleRequest(this.conn, context);
+ }
+ }
+ catch (IOException ex) {
+ // ignore silently
+ }
+ catch (HttpException ex) {
+ // ignore silently
+ }
+ finally {
+ workerThreads.remove(Thread.currentThread());
+ try {
+ this.conn.shutdown();
+ }
+ catch (IOException ignore) {
+ }
+ }
+ }
+
+ }
+
+ }
+
+}
Added: incubator/droids/trunk/src/test/java/org/apache/droids/localserver/ResourceHandler.java
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/test/java/org/apache/droids/localserver/ResourceHandler.java?rev=710092&view=auto
==============================================================================
--- incubator/droids/trunk/src/test/java/org/apache/droids/localserver/ResourceHandler.java (added)
+++ incubator/droids/trunk/src/test/java/org/apache/droids/localserver/ResourceHandler.java Mon Nov 3 08:23:01 2008
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+package org.apache.droids.localserver;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Locale;
+
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.HttpStatus;
+import org.apache.http.MethodNotSupportedException;
+import org.apache.http.entity.InputStreamEntity;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+
+/**
+ * A handler that serves out a resource
+ */
+public class ResourceHandler implements HttpRequestHandler
+{
+
+ public void handle(final HttpRequest request, final HttpResponse response,
+ final HttpContext context) throws HttpException, IOException {
+
+ String method = request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
+ if (!"GET".equals(method) && !"HEAD".equals(method)) {
+ throw new MethodNotSupportedException(method + " not supported by " + getClass().getName());
+ }
+ String requestURI = request.getRequestLine().getUri();
+ String s = requestURI;
+ if (!s.startsWith("/")) {
+ s = "/" + s;
+ }
+ s = "resources" + s;
+
+ ClassLoader cl = ResourceHandler.class.getClassLoader();
+ URL resource = cl.getResource(s);
+
+ if (resource != null) {
+ InputStream instream = resource.openStream();
+ InputStreamEntity entity = new InputStreamEntity(instream, -1);
+ if (requestURI.endsWith("_html")) {
+ entity.setContentType("text/html");
+ }
+ response.setEntity(entity);
+ } else {
+ response.setStatusCode(HttpStatus.SC_NOT_FOUND);
+ StringEntity entity = new StringEntity(requestURI + " not found", "US-ASCII");
+ entity.setContentType("text/html");
+ response.setEntity(entity);
+ }
+ }
+
+}
Added: incubator/droids/trunk/src/test/java/resources/page1_html
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/test/java/resources/page1_html?rev=710092&view=auto
==============================================================================
--- incubator/droids/trunk/src/test/java/resources/page1_html (added)
+++ incubator/droids/trunk/src/test/java/resources/page1_html Mon Nov 3 08:23:01 2008
@@ -0,0 +1,6 @@
+<html>
+ <head>Page 1</head>
+ <body>
+ <a href="/page3_html">Page1</a>
+ </body>
+</html>
\ No newline at end of file
Added: incubator/droids/trunk/src/test/java/resources/page2_html
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/test/java/resources/page2_html?rev=710092&view=auto
==============================================================================
--- incubator/droids/trunk/src/test/java/resources/page2_html (added)
+++ incubator/droids/trunk/src/test/java/resources/page2_html Mon Nov 3 08:23:01 2008
@@ -0,0 +1,6 @@
+<html>
+ <head>Page 2</head>
+ <body>
+ <a href="/page4_html">Page1</a>
+ </body>
+</html>
\ No newline at end of file
Added: incubator/droids/trunk/src/test/java/resources/page3_html
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/test/java/resources/page3_html?rev=710092&view=auto
==============================================================================
--- incubator/droids/trunk/src/test/java/resources/page3_html (added)
+++ incubator/droids/trunk/src/test/java/resources/page3_html Mon Nov 3 08:23:01 2008
@@ -0,0 +1,6 @@
+<html>
+ <head>Page 4</head>
+ <body>
+ <p>Yada yada</p>
+ </body>
+</html>
\ No newline at end of file
Added: incubator/droids/trunk/src/test/java/resources/page4_html
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/test/java/resources/page4_html?rev=710092&view=auto
==============================================================================
--- incubator/droids/trunk/src/test/java/resources/page4_html (added)
+++ incubator/droids/trunk/src/test/java/resources/page4_html Mon Nov 3 08:23:01 2008
@@ -0,0 +1,6 @@
+<html>
+ <head>Page 4</head>
+ <body>
+ <p>Blah blah blah</p>
+ </body>
+</html>
\ No newline at end of file
Added: incubator/droids/trunk/src/test/java/resources/start_html
URL: http://svn.apache.org/viewvc/incubator/droids/trunk/src/test/java/resources/start_html?rev=710092&view=auto
==============================================================================
--- incubator/droids/trunk/src/test/java/resources/start_html (added)
+++ incubator/droids/trunk/src/test/java/resources/start_html Mon Nov 3 08:23:01 2008
@@ -0,0 +1,7 @@
+<html>
+ <head>Start page</head>
+ <body>
+ <a href="/page1_html">Page1</a>
+ <a href="/page2_html">Page1</a>
+ </body>
+</html>
\ No newline at end of file