You are viewing a plain text version of this content. The canonical link for it is here.
Posted to awf-commits@incubator.apache.org by jm...@apache.org on 2011/08/02 17:59:28 UTC

svn commit: r1153226 [1/3] - in /incubator/deft/sandbox: ./ src/main/java/org/deftserver/annotation/ src/main/java/org/deftserver/configuration/ src/main/java/org/deftserver/example/ src/main/java/org/deftserver/example/client/ src/main/java/org/deftse...

Author: jmeehan
Date: Tue Aug  2 17:59:22 2011
New Revision: 1153226

URL: http://svn.apache.org/viewvc?rev=1153226&view=rev
Log:
DEFT-100, DEFT-175 - Configure request handlers with annotations; add demonstration code.

Added:
    incubator/deft/sandbox/src/main/java/org/deftserver/annotation/
    incubator/deft/sandbox/src/main/java/org/deftserver/annotation/Path.java   (with props)
    incubator/deft/sandbox/src/main/java/org/deftserver/configuration/
    incubator/deft/sandbox/src/main/java/org/deftserver/configuration/AnnotationsScanner.java   (with props)
    incubator/deft/sandbox/src/main/java/org/deftserver/configuration/Configuration.java   (with props)
    incubator/deft/sandbox/src/main/java/org/deftserver/example/client/
    incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientGetExample.java
    incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientPostExample.java
    incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/
    incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/BasicHandlerExample.java   (with props)
    incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/CookieHandlerExample.java   (with props)
    incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/PatternHandlerExample.java   (with props)
    incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/
      - copied from r1152652, incubator/deft/sandbox/src/main/java/org/deftserver/example/kv/
    incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreHandler.java   (with props)
    incubator/deft/sandbox/src/main/java/org/deftserver/util/ReflectionTools.java   (with props)
    incubator/deft/sandbox/src/test/java/org/deftserver/configuration/
    incubator/deft/sandbox/src/test/java/org/deftserver/configuration/AnnotationsScannerTest.java   (with props)
    incubator/deft/sandbox/src/test/java/org/deftserver/configuration/ConfigurationTest.java   (with props)
    incubator/deft/sandbox/src/test/java/org/deftserver/util/ReflectionToolsTest.java   (with props)
Removed:
    incubator/deft/sandbox/src/main/java/org/deftserver/example/AsynchronousHttpClientGetExample.java
    incubator/deft/sandbox/src/main/java/org/deftserver/example/AsynchronousHttpClientPostExample.java
    incubator/deft/sandbox/src/main/java/org/deftserver/example/DeftCookieExample.java
    incubator/deft/sandbox/src/main/java/org/deftserver/example/kv/
Modified:
    incubator/deft/sandbox/NEWS.txt
    incubator/deft/sandbox/src/main/java/org/deftserver/example/DeftServerExample.java
    incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStore.java
    incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreClient.java
    incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreExample.java
    incubator/deft/sandbox/src/main/java/org/deftserver/web/HttpServer.java
    incubator/deft/sandbox/src/test/java/org/deftserver/web/DeftSystemTest.java
    incubator/deft/sandbox/src/test/java/org/deftserver/web/HttpServerTest.java

Modified: incubator/deft/sandbox/NEWS.txt
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/NEWS.txt?rev=1153226&r1=1153225&r2=1153226&view=diff
==============================================================================
--- incubator/deft/sandbox/NEWS.txt (original)
+++ incubator/deft/sandbox/NEWS.txt Tue Aug  2 17:59:22 2011
@@ -15,6 +15,7 @@ Features / Improvements
     - Bug fix. NPE when using AsynchronousSocket.write (DEFT-155)
     - Asynchronous HTTP client supports POST and PUT (DEFT-117)
     - Support for HTTP Cookies (DEFT-52)
+    - Request handlers now configured through annotations (DEFT-100)
     
 Configuration
 -------------

Added: incubator/deft/sandbox/src/main/java/org/deftserver/annotation/Path.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/annotation/Path.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/annotation/Path.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/annotation/Path.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,52 @@
+/*
+ *  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.deftserver.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.util.regex.Pattern;
+
+/**
+ * Defines the request path for which the annotated <code>RequestHandler</code>
+ * method is applicable. The path is defined from root, and so for example to
+ * associate a <code>RequestHandler</code> with the top-level directory
+ * "images":
+ * <p>
+ * <code>&#64;Path(&quot;/images/&quot;)</code>
+ * </p>
+ * <p>
+ * Values are a combination of paths and regular expressions as understood by
+ * {@link Pattern}. For example:
+ * </p>
+ * <ul>
+ * <li><code>&#64;Path("/path/([\\w]+)")</code> matches any word character after
+ * the path such as "/path/123", "/path/abc" or "/path/12ab".
+ * <li><code>&#64;Path("/matchThis")</code> matches on the path itself, that is
+ * "http://host/matchThis".
+ * </ul>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+public @interface Path {
+
+    String value();
+}

Propchange: incubator/deft/sandbox/src/main/java/org/deftserver/annotation/Path.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/deft/sandbox/src/main/java/org/deftserver/configuration/AnnotationsScanner.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/configuration/AnnotationsScanner.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/configuration/AnnotationsScanner.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/configuration/AnnotationsScanner.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,144 @@
+/*
+ *  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.deftserver.configuration;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.deftserver.annotation.Path;
+import org.deftserver.util.ReflectionTools;
+import org.deftserver.web.handler.RequestHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Provides functionality to retrieve known <code>Annotation</code> types and
+ * associated values.
+ */
+public class AnnotationsScanner {
+
+    private final static Logger logger = LoggerFactory.getLogger(AnnotationsScanner.class);
+
+    /**
+     * A <code>Map</code> of <code>RequestHandler</code>s associated with
+     * {@link Path}s.
+     */
+    private Map<String, RequestHandler> pathHandlers = new HashMap<String, RequestHandler>();
+
+    /**
+     * Recursively iterate the given package, and attempt to resolve all
+     * annotated references for <code>RequestHandler</code> implementations.
+     * 
+     * @param handlerPackage the base package to scan, for example
+     *            "org.apache.deft".
+     * @return a <code>Map&lt;String, RequestHandler&gt;</code> of handlers,
+     *         which may be empty but not <code>null</code>.
+     */
+    public Map<String, RequestHandler> findHandlers(String handlerPackage) {
+
+        List<Class<?>> classes = findClasses(handlerPackage);
+        for (Class<?> clazz : classes) {
+            if (clazz.isAnnotationPresent(Path.class)) {
+
+                RequestHandler handler = (RequestHandler) ReflectionTools.createInstance(clazz.getCanonicalName());
+                Path path = clazz.getAnnotation(Path.class);
+                pathHandlers.put(path.value(), handler);
+
+                logger.info("Added RequestHandler [" + clazz.getCanonicalName() + "] for Path [" + path.value() + "]");
+            }
+        }
+
+        return pathHandlers;
+    }
+
+    /**
+     * Recursively finds all classes available to the context
+     * <code>ClassLoader</code> from the given package.
+     * 
+     * @param packageName the package from which to commence the scan.
+     * @return A <code>List</code> of <code>Class</code> references.
+     */
+    private List<Class<?>> findClasses(String packageName) {
+
+        List<Class<?>> classes = new ArrayList<Class<?>>();
+
+        ClassLoader loader = Thread.currentThread().getContextClassLoader();
+        if (loader == null) {
+            logger.error("Context ClassLoader was not available");
+            return classes;
+        }
+
+        String path = packageName.replace('.', '/');
+        try {
+            List<File> directories = new ArrayList<File>();
+
+            Enumeration<URL> resources = loader.getResources(path);
+            while (resources.hasMoreElements()) {
+                URL resource = resources.nextElement();
+                directories.add(new File(resource.getFile()));
+            }
+
+            for (File directory : directories) {
+                classes.addAll(findClasses(directory, packageName));
+            }
+        } catch (IOException e) {
+            logger.error("Exception accessing resources for [" + path + "]", e);
+        }
+
+        return classes;
+    }
+
+    /**
+     * Recursively finds all class files available for the given package from
+     * the passed directory.
+     * 
+     * @param packageName the package from which to commence the scan.
+     * @return A <code>List</code> of <code>Class</code> references.
+     */
+    private List<Class<?>> findClasses(File directory, String packageName) {
+
+        List<Class<?>> classes = new ArrayList<Class<?>>();
+        if (directory == null || !directory.exists()) {
+            logger.error("Directory is null value or non-existent, [" + directory + "]");
+            return classes;
+        }
+
+        for (File file : directory.listFiles()) {
+            try {
+                if (file.isDirectory()) {
+                    classes.addAll(findClasses(file, packageName + "." + file.getName()));
+                } else if (file.getName().endsWith(".class")) {
+                    classes.add(Class.forName(packageName + '.'
+                            + file.getName().substring(0, file.getName().length() - 6)));
+                }
+            } catch (ClassNotFoundException e) {
+                logger.error("ClassNotFoundException", e);
+            }
+        }
+
+        return classes;
+    }
+}

Propchange: incubator/deft/sandbox/src/main/java/org/deftserver/configuration/AnnotationsScanner.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/deft/sandbox/src/main/java/org/deftserver/configuration/Configuration.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/configuration/Configuration.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/configuration/Configuration.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/configuration/Configuration.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,87 @@
+/*
+ *  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.deftserver.configuration;
+
+import org.deftserver.web.HttpServer;
+
+import com.google.common.base.Strings;
+
+/**
+ * Simple type to hold configuration options, to be passed to {@link HttpServer}
+ * .
+ */
+public class Configuration {
+
+    /**
+     * The default directory for static content.
+     */
+    static final String DEFAULT_STATIC_DIRECTORY = "static";
+
+    /**
+     * The package under which <code>RequestHandler</code> implementations are
+     * to be found, for example "org.apache.deft".
+     */
+    private String handlerPacakge;
+
+    /**
+     * The directory from which static content should be retrieved.
+     */
+    private String staticDirectory;
+
+    /**
+     * Retrieve the package under which <code>RequestHandler</code>
+     * implementations are to be found, for example "org.apache.deft".
+     * 
+     * @return the current package name.
+     */
+    public String getHandlerPackage() {
+        return handlerPacakge;
+    }
+
+    /**
+     * Set package under which <code>RequestHandler</code> implementations are
+     * to be found, for example "org.apache.deft".
+     * 
+     * @param handlerPackage the name of the package.
+     */
+    public void setHandlerPackage(String handlerPackage) {
+        handlerPacakge = handlerPackage;
+    }
+
+    /**
+     * Retrieve directory from which static content should be retrieved.
+     * Defaults to the value of {@link #DEFAULT_STATIC_DIRECTORY} where empty or
+     * <code>null</code>.
+     * 
+     * @return the current name of the static directory.
+     */
+    public String getStaticDirectory() {
+        return Strings.nullToEmpty(staticDirectory).trim().length() == 0 ? "static" : staticDirectory;
+    }
+
+    /**
+     * Set the directory from which static content should be retrieved.
+     * 
+     * @param staticDirectory the directory name for use.
+     */
+    public void setStaticDirectory(String staticDirectory) {
+        this.staticDirectory = staticDirectory;
+    }
+}

Propchange: incubator/deft/sandbox/src/main/java/org/deftserver/configuration/Configuration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/deft/sandbox/src/main/java/org/deftserver/example/DeftServerExample.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/DeftServerExample.java?rev=1153226&r1=1153225&r2=1153226&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/DeftServerExample.java (original)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/DeftServerExample.java Tue Aug  2 17:59:22 2011
@@ -19,57 +19,31 @@
  */
 package org.deftserver.example;
 
-import java.util.Map;
-
+import org.deftserver.configuration.Configuration;
 import org.deftserver.io.IOLoop;
-import org.deftserver.web.Application;
 import org.deftserver.web.HttpServer;
-import org.deftserver.web.handler.RequestHandler;
-import org.deftserver.web.http.HttpRequest;
-import org.deftserver.web.http.HttpResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.collect.Maps;
-
-
 
+/**
+ * A simple example of how to configure and instantiate a server.
+ */
 public class DeftServerExample {
-	
-	private final static Logger logger = LoggerFactory.getLogger(DeftServerExample.class);
-	private final static int PORT = 8080;
-	
-	private static class ExampleRequestHandler extends RequestHandler {
-
-		@Override
-		public void get(HttpRequest request, HttpResponse response) {
-			response.write("hello world");
-		}
-		
-		@Override
-		public void post(HttpRequest request, HttpResponse response) {
-			response.write("hello post world\nbody: " + request.getBody());
-		}
-
-	}
 
-	public static void main(String[] args) {
-		Map<String, RequestHandler> handlers = Maps.newHashMap();
-		handlers.put("/", new ExampleRequestHandler());
-		
-		Application application = new Application(handlers);
-		application.setStaticContentDir("static");
-		
-//		HttpServerDescriptor.KEEP_ALIVE_TIMEOUT = 30 * 1000;	// 30s  
-//		HttpServerDescriptor.READ_BUFFER_SIZE = 1500;			// 1500 bytes 
-//		HttpServerDescriptor.WRITE_BUFFER_SIZE = 1500;			// 1500 bytes 
-		
+    public static void main(String[] args) {
 
-		logger.debug("Starting up server on port: " + PORT);
-		HttpServer server = new HttpServer(application);
-		server.listen(PORT);
-		//server.bind(PORT);
-		//server.start(Runtime.getRuntime().availableProcessors());
-		IOLoop.INSTANCE.start();
-	}
+        /*
+         * The only required configuration option is the base package, under
+         * which handlers are found. See the sub-package "handler" for examples
+         * and how to view them as part of this example application.
+         */
+        Configuration configuration = new Configuration();
+        configuration.setHandlerPackage("org.deftserver.example.handler");
+
+        /*
+         * Create an instance of HttpServer with the given Configuration, bind
+         * to a single port and start.
+         */
+        HttpServer server = new HttpServer(configuration);
+        server.listen(8080);
+        IOLoop.INSTANCE.start();
+    }
 }

Added: incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientGetExample.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientGetExample.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientGetExample.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientGetExample.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,61 @@
+package org.deftserver.example.client;
+ 
+import org.deftserver.io.IOLoop;
+import org.deftserver.io.timeout.Timeout;
+import org.deftserver.web.AsyncCallback;
+import org.deftserver.web.AsyncResult;
+import org.deftserver.web.http.client.AsynchronousHttpClient;
+import org.deftserver.web.http.client.Response;
+ 
+/**
+ * Example class to demonstrate usage of <code>AsynchronousHttpClient</code>.
+ */
+public class AsynchronousHttpClientGetExample {
+    /**
+     * A simple example of how to use the <code>AsynchronousHttpClient</code>,
+     * taking the following steps:
+     * <ol>
+     * <li>Create an instance of <code>AsyncResult&lt;Response&gt;</code> and
+     * define the methods <code>onSuccess</code> and <code>onFailure</code>.
+     * This type will become the callback for our operation, and the actions
+     * defined in the method will be executed when that operation succeeds or
+     * fails respectively. In this case, we will detail the exception on failure
+     * and show the response body on success.
+     * <li>Create an instance of <code>AsynchronousHttpClient</code> and perform
+     * a GET action passing the URL to hit and our previously defined callback
+     * type.
+     * <li>Add time-out value to the current <code>IOLoop</code> of one second,
+     * and in the definition of the <code>onCallback</code> method tell the
+     * instance to stop listening when this time limit has been reached.
+     * <li>Start the instance.
+     * </ol>
+     * 
+     * @param args
+     *            the arguments to pass; unused.
+     */
+    public static void main(final String[] args) {
+ 
+        final AsyncResult<Response> callback = new AsyncResult<Response>() {
+ 
+            @Override
+            public void onSuccess(final Response response) { System.out.println("RESPONSE: " + response); }
+
+            @Override
+            public void onFailure(final Throwable caught) { System.out.println("EXCEPTION: " + caught); }
+        };
+
+        final AsynchronousHttpClient client = new AsynchronousHttpClient();
+        client.get("http://incubator.apache.org/deft/", callback);
+
+        IOLoop.INSTANCE.addTimeout(new Timeout(System.currentTimeMillis() + 1000, new AsyncCallback() {
+            @Override
+            public void onCallback() {
+                System.out.println("INSTANCE.stop()");
+                IOLoop.INSTANCE.stop();
+            }
+        }));
+
+        System.out.println("INSTANCE.start()");
+        IOLoop.INSTANCE.start();
+    }
+ }
\ No newline at end of file

Added: incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientPostExample.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientPostExample.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientPostExample.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/client/AsynchronousHttpClientPostExample.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,89 @@
+/*
+ *  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.deftserver.example.client;
+
+import org.deftserver.io.IOLoop;
+import org.deftserver.io.timeout.Timeout;
+import org.deftserver.web.AsyncCallback;
+import org.deftserver.web.AsyncResult;
+import org.deftserver.web.HttpVerb;
+import org.deftserver.web.http.ContentType;
+import org.deftserver.web.http.client.AsynchronousHttpClient;
+import org.deftserver.web.http.client.Request;
+import org.deftserver.web.http.client.Response;
+
+/**
+ * Example class to demonstrate usage of <code>AsynchronousHttpClient</code>.
+ */
+public class AsynchronousHttpClientPostExample {
+
+    /**
+     * A simple example of how to use the <code>AsynchronousHttpClient</code>,
+     * taking the following steps:
+     * <ol>
+     * <li>Create an instance of <code>AsyncResult&lt;Response&gt;</code> and
+     * define the methods <code>onSuccess</code> and <code>onFailure</code>.
+     * This type will become the callback for our operation, and the actions
+     * defined in the method will be executed when that operation succeeds or
+     * fails respectively. In this case, we will detail the exception on failure
+     * and show the response body on success.
+     * <li>Create a <code>Request</code>, providing target URL and HTTP method
+     * as well as body and content type information.
+     * <li>Create an instance of <code>AsynchronousHttpClient</code> and pass
+     * this <code>Request</code> with our previously defined callback.
+     * <li>Add time-out value to the current <code>IOLoop</code> of one second,
+     * and in the definition of the <code>onCallback</code> method tell the
+     * instance to stop listening when this time limit has been reached.
+     * <li>Start the instance.
+     * </ol>
+     * 
+     * @param args
+     *            the arguments to pass; unused.
+     */
+    public static void main(final String[] args) {
+
+        final AsyncResult<Response> callback = new AsyncResult<Response>() {
+
+            @Override
+            public void onSuccess(final Response response) { System.out.println("RESPONSE: " + response); }
+
+            @Override
+            public void onFailure(final Throwable caught) { System.out.println("EXCEPTION: " + caught); }
+        };
+
+        Request request = new Request("http://incubator.apache.org/deft/", HttpVerb.POST);
+        request.setBody("paramName=paramValue");
+        request.setContentType(ContentType.APPLICATION_FORM_URLENCODED);
+
+        final AsynchronousHttpClient client = new AsynchronousHttpClient();
+        client.fetch(request, callback);
+
+        IOLoop.INSTANCE.addTimeout(new Timeout(System.currentTimeMillis() + 1000, new AsyncCallback() {
+            @Override
+            public void onCallback() {
+                System.out.println("INSTANCE.stop()");
+                IOLoop.INSTANCE.stop();
+            }
+        }));
+
+        System.out.println("INSTANCE.start()");
+        IOLoop.INSTANCE.start();
+    }
+}

Added: incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/BasicHandlerExample.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/BasicHandlerExample.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/BasicHandlerExample.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/BasicHandlerExample.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,51 @@
+/*
+ *  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.deftserver.example.handler;
+
+import org.deftserver.annotation.Path;
+import org.deftserver.example.DeftServerExample;
+import org.deftserver.web.handler.RequestHandler;
+import org.deftserver.web.http.HttpRequest;
+import org.deftserver.web.http.HttpResponse;
+
+/**
+ * This is a basic handler, which does nothing more than write output and
+ * associate itself with a path. The {@link Path} annotation below defines the
+ * path on which this handler is invoked. When executed as part of the server
+ * example:
+ * <p>
+ * <code>http://localhost:8080/</code>
+ * </p>
+ * <p>
+ * The handler will send a simple message to the caller, and nothing more.
+ * </p>
+ * 
+ * @see Path
+ * @see DeftServerExample
+ */
+@Path("/")
+public class BasicHandlerExample extends RequestHandler {
+
+    @Override
+    public void get(HttpRequest request, HttpResponse response) {
+
+        response.write("It works!");
+    }
+}

Propchange: incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/BasicHandlerExample.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/CookieHandlerExample.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/CookieHandlerExample.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/CookieHandlerExample.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/CookieHandlerExample.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,62 @@
+/*
+ *  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.deftserver.example.handler;
+
+import java.util.UUID;
+
+import org.deftserver.annotation.Path;
+import org.deftserver.example.DeftServerExample;
+import org.deftserver.web.handler.RequestHandler;
+import org.deftserver.web.http.HttpRequest;
+import org.deftserver.web.http.HttpResponse;
+
+/**
+ * This handler demonstrates usage of cookie-related functionality. The
+ * {@link Path} annotation below defines the path on which this handler is
+ * invoked. When executed as part of the server example:
+ * <p>
+ * <code>http://localhost:8080/cookie</code>
+ * </p>
+ * <p>
+ * This handler will set a cookie when a page is first viewed, with a limited
+ * lifetime and unique identifier. Upon refresh, this cookie will be cleared.
+ * </p>
+ * 
+ * @see Path
+ * @see DeftServerExample
+ */
+@Path("/cookie")
+public class CookieHandlerExample extends RequestHandler {
+
+    @Override
+    public void get(HttpRequest request, HttpResponse response) {
+
+        String sessCookie = request.getCookie("deftssid");
+
+        if (sessCookie != null) {
+            response.write("Cookie deftssid: " + sessCookie);
+            response.clearCookie("deftssid");
+        } else {
+            String ssid = UUID.randomUUID().toString();
+            response.setCookie("deftssid", ssid, 1800);
+            response.write("Set cookie deftssid: " + ssid);
+        }
+    }
+}

Propchange: incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/CookieHandlerExample.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/PatternHandlerExample.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/PatternHandlerExample.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/PatternHandlerExample.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/PatternHandlerExample.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,55 @@
+/*
+ *  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.deftserver.example.handler;
+
+import java.util.regex.Pattern;
+
+import org.deftserver.annotation.Path;
+import org.deftserver.example.DeftServerExample;
+import org.deftserver.web.handler.RequestHandler;
+import org.deftserver.web.http.HttpRequest;
+import org.deftserver.web.http.HttpResponse;
+
+/**
+ * This handler is invoked as a result of the combination of path and Regular
+ * Expression. When executed as part of the server example:
+ * <p>
+ * <code>http://localhost:8080/pattern/123</code> will be found.
+ * <code>http://localhost:8080/pattern/abc</code> will not be found.
+ * </p>
+ * <p>
+ * In the annotation below, the regular expression is "[0-9]+" which indicates
+ * that any number will be matched. Any pattern as understood by {@link Pattern}
+ * is suitable, and the handler will be invoked only when this pattern is
+ * matched.
+ * </p>
+ * 
+ * @see Path
+ * @see DeftServerExample
+ */
+@Path("/pattern/([0-9]+)")
+public class PatternHandlerExample extends RequestHandler {
+
+    @Override
+    public void get(HttpRequest request, HttpResponse response) {
+
+        response.write("The pattern was parsed successfully.");
+    }
+}

Propchange: incubator/deft/sandbox/src/main/java/org/deftserver/example/handler/PatternHandlerExample.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStore.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStore.java?rev=1153226&r1=1152652&r2=1153226&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStore.java (original)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStore.java Tue Aug  2 17:59:22 2011
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.deftserver.example.kv;
+package org.deftserver.example.keyvalue;
 
 import java.io.BufferedReader;
 import java.io.BufferedWriter;
@@ -32,80 +32,89 @@ import java.util.Map;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-
 /**
- * Mocked KeyValueStoreHandler server (accepts a connection and echoes back the input)
- *
+ * Mocked KeyValueStoreHandler server (accepts a connection and echoes back the
+ * input)
+ * 
  */
 public class KeyValueStore extends Thread {
 
-	private final static Logger logger = LoggerFactory.getLogger(KeyValueStore.class);
-
-	public static final String HOST = "127.0.0.1";
-	public static final int PORT = 6379;
+    private final static Logger logger = LoggerFactory.getLogger(KeyValueStore.class);
 
-	private final static Map<String, String> dict = new HashMap<String, String>() {
-		{ put("deft", "kickass"); }
-	};
-
-	private ServerSocket serverSocket;
-
-	public KeyValueStore() {
-		logger.debug("Initializing KeyValueStore");
-		initialize();
-	}
-	
-	public void run() {
-		try {
-			logger.debug("KeyValueStore waiting for clients...");	
-			Socket clientSocket = serverSocket.accept();
-			logger.debug("KeyValueStore client connected...");
-			BufferedWriter os = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
-			BufferedReader is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
-			String input = is.readLine();
-			logger.debug("KeyValueStore received input: {}", input);
-			if (input.split("\\s+").length == 2) {
-				input = input.split("\\s+")[1];	// "GET deft" => "deft"
-			}
-			int sleep = 250;
-			if (input != null) {
-				logger.debug("KeyValueStore server sleeps " + sleep + "ms..." );
-				try {
-					Thread.sleep(sleep);
-				} catch (InterruptedException e) {
-					e.printStackTrace();
-				}
-				logger.debug("KeyValueStore woke up...");
-				String value = dict.get(input) + "\r\n";
-				os.write(value, 0, value.length());
-				logger.debug("KeyValueStore echoed back: " + value);
-				os.flush();
-			}
-
-			try {
-				Thread.sleep(sleep);
-			} catch (InterruptedException e) {
-				e.printStackTrace();
-			}
-			{	// cleanup
-				try {
-					if (is != null)
-						is.close();
-					if (os != null)
-						os.close();
-					if (clientSocket != null)
-						clientSocket.close();
-				}
-				catch (IOException ignore) {}
-			}
-		} catch (IOException e) { e.printStackTrace(); }
-		logger.debug("Closing KeyValueStore");
-	}
-
-	private void initialize() {
-		try {
-			serverSocket = new ServerSocket(PORT);
-		} catch (IOException e) { e.printStackTrace(); }
-	}
+    public static final String HOST = "127.0.0.1";
+    public static final int PORT = 6379;
 
+    private final static Map<String, String> dict = new HashMap<String, String>() {
+        {
+            put("deft", "kickass");
+        }
+    };
+
+    private ServerSocket serverSocket;
+
+    public KeyValueStore() {
+        logger.debug("Initializing KeyValueStore");
+        initialize();
+    }
+
+    @Override
+    public void run() {
+        try {
+            logger.debug("KeyValueStore waiting for clients...");
+            Socket clientSocket = serverSocket.accept();
+            logger.debug("KeyValueStore client connected...");
+            BufferedWriter os = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
+            BufferedReader is = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
+            String input = is.readLine();
+            logger.debug("KeyValueStore received input: {}", input);
+            if (input.split("\\s+").length == 2) {
+                input = input.split("\\s+")[1]; // "GET deft" => "deft"
+            }
+            int sleep = 250;
+            if (input != null) {
+                logger.debug("KeyValueStore server sleeps " + sleep + "ms...");
+                try {
+                    Thread.sleep(sleep);
+                } catch (InterruptedException e) {
+                    e.printStackTrace();
+                }
+                logger.debug("KeyValueStore woke up...");
+                String value = dict.get(input) + "\r\n";
+                os.write(value, 0, value.length());
+                logger.debug("KeyValueStore echoed back: " + value);
+                os.flush();
+            }
+
+            try {
+                Thread.sleep(sleep);
+            } catch (InterruptedException e) {
+                e.printStackTrace();
+            }
+            { // cleanup
+                try {
+                    if (is != null) {
+                        is.close();
+                    }
+                    if (os != null) {
+                        os.close();
+                    }
+                    if (clientSocket != null) {
+                        clientSocket.close();
+                    }
+                } catch (IOException ignore) {
+                }
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        logger.debug("Closing KeyValueStore");
+    }
+
+    private void initialize() {
+        try {
+            serverSocket = new ServerSocket(PORT);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
 }

Modified: incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreClient.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreClient.java?rev=1153226&r1=1152652&r2=1153226&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreClient.java (original)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreClient.java Tue Aug  2 17:59:22 2011
@@ -17,7 +17,7 @@
  *  under the License. 
  *  
  */
-package org.deftserver.example.kv;
+package org.deftserver.example.keyvalue;
 
 import java.io.IOException;
 import java.net.InetSocketAddress;
@@ -33,47 +33,47 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class KeyValueStoreClient {
-	
-	private final static Logger logger = LoggerFactory.getLogger(KeyValueStoreClient.class);
-	
-	private AsynchronousSocket socket;
-	private SocketChannel channel;
-	private final String host;
-	private final int port;
-	
-	public KeyValueStoreClient(String host, int port) {
-		this.host = host;
-		this.port = port;
-	}
-
-	public void connect() {
-		try {
-			channel = SocketChannel.open(new InetSocketAddress(host, port));
-			channel.configureBlocking(false);
-		} catch (IOException e) { e.printStackTrace(); }
-		socket = new AsynchronousSocket(channel);
-		IOLoop.INSTANCE.addHandler(channel, socket, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
-	}
-	
-	public void get(String value, AsyncResult<byte[]> cb) {
-		socket.write("GET deft\r\n".getBytes(), new WriteCallback(cb));
-	}
-	
-	private class WriteCallback implements AsyncCallback {
-
-		private final AsyncResult<byte[]> cb;
-		
-		public WriteCallback(AsyncResult<byte[]> cb) { 
-			this.cb = cb; 
-		}
-		
-		@Override
-		public void onCallback() {
-			// write is finished. read response from server
-			logger.debug("readUntil: \r\n");
-			socket.readUntil("\r\n".getBytes(), cb);
-		}
-		
-	}
-	
+
+    private final static Logger logger = LoggerFactory.getLogger(KeyValueStoreClient.class);
+
+    private AsynchronousSocket socket;
+    private SocketChannel channel;
+    private final String host;
+    private final int port;
+
+    public KeyValueStoreClient(String host, int port) {
+        this.host = host;
+        this.port = port;
+    }
+
+    public void connect() {
+        try {
+            channel = SocketChannel.open(new InetSocketAddress(host, port));
+            channel.configureBlocking(false);
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        socket = new AsynchronousSocket(channel);
+        IOLoop.INSTANCE.addHandler(channel, socket, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
+    }
+
+    public void get(String value, AsyncResult<byte[]> cb) {
+        socket.write("GET deft\r\n".getBytes(), new WriteCallback(cb));
+    }
+
+    private class WriteCallback implements AsyncCallback {
+
+        private final AsyncResult<byte[]> cb;
+
+        public WriteCallback(AsyncResult<byte[]> cb) {
+            this.cb = cb;
+        }
+
+        @Override
+        public void onCallback() {
+            // write is finished. read response from server
+            logger.debug("readUntil: \r\n");
+            socket.readUntil("\r\n".getBytes(), cb);
+        }
+    }
 }

Modified: incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreExample.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreExample.java?rev=1153226&r1=1152652&r2=1153226&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreExample.java (original)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreExample.java Tue Aug  2 17:59:22 2011
@@ -17,13 +17,10 @@
  *  under the License. 
  *  
  */
-package org.deftserver.example.kv;
-
-import java.util.HashMap;
-import java.util.Map;
+package org.deftserver.example.keyvalue;
 
+import org.deftserver.configuration.Configuration;
 import org.deftserver.io.IOLoop;
-import org.deftserver.web.Application;
 import org.deftserver.web.AsyncResult;
 import org.deftserver.web.Asynchronous;
 import org.deftserver.web.HttpServer;
@@ -35,37 +32,39 @@ import org.slf4j.LoggerFactory;
 
 public class KeyValueStoreExample {
 
-	private final static Logger logger = LoggerFactory.getLogger(KeyValueStoreExample.class);
-	private final static int PORT = 8080;
-	
-	private static class KeyValueStoreExampleRequestHandler extends RequestHandler {
-
-		private final KeyValueStoreClient client = new KeyValueStoreClient(KeyValueStore.HOST, KeyValueStore.PORT);
-		
-		public KeyValueStoreExampleRequestHandler() {
-			new KeyValueStore().start();
-			client.connect();
-		}
-		
-		@Override
-		@Asynchronous
-		public void get(HttpRequest request, final HttpResponse response) {
-			client.get("deft", new AsyncResult<byte[]>() {
-				@Override public void onFailure(Throwable caught) { /* ignore */}
-				@Override public void onSuccess(byte[] result) { response.write(new String(result)).finish(); }
-			});
-		}
-
-	}
-	
-	public static void main(String[] args) {
-		Map<String, RequestHandler> handlers = new HashMap<String, RequestHandler>();
-		handlers.put("/kv", new KeyValueStoreExampleRequestHandler());
-		Application application = new Application(handlers);
-		logger.debug("Starting up server on port: " + PORT);
-		HttpServer server = new HttpServer(application);
-		server.listen(PORT);
-		IOLoop.INSTANCE.start();
-	}
+    private final static Logger logger = LoggerFactory.getLogger(KeyValueStoreExample.class);
+    private final static int PORT = 8080;
+
+    private static class KeyValueStoreExampleRequestHandler extends RequestHandler {
+
+        private final KeyValueStoreClient client = new KeyValueStoreClient(KeyValueStore.HOST, KeyValueStore.PORT);
+
+        public KeyValueStoreExampleRequestHandler() {
+            new KeyValueStore().start();
+            client.connect();
+        }
+
+        @Override
+        @Asynchronous
+        public void get(HttpRequest request, final HttpResponse response) {
+            client.get("deft", new AsyncResult<byte[]>() {
+                @Override
+                public void onFailure(Throwable caught) { /* ignore */ }
+
+                @Override
+                public void onSuccess(byte[] result) { response.write(new String(result)).finish(); }
+            });
+        }
+    }
+
+    public static void main(String[] args) {
+
+        Configuration configuration = new Configuration();
+        configuration.setHandlerPackage("org.deftserver.example.kv");
+
+        HttpServer server = new HttpServer(configuration);
+        server.listen(PORT);
+        IOLoop.INSTANCE.start();
+    }
 
 }

Added: incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreHandler.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreHandler.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreHandler.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreHandler.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,56 @@
+/*
+ *  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.deftserver.example.keyvalue;
+
+import org.deftserver.annotation.Path;
+import org.deftserver.web.AsyncResult;
+import org.deftserver.web.Asynchronous;
+import org.deftserver.web.handler.RequestHandler;
+import org.deftserver.web.http.HttpRequest;
+import org.deftserver.web.http.HttpResponse;
+
+/**
+ * 
+ */
+@Path("/kv")
+public class KeyValueStoreHandler extends RequestHandler {
+
+    private final KeyValueStoreClient client = new KeyValueStoreClient(KeyValueStore.HOST, KeyValueStore.PORT);
+
+    public KeyValueStoreHandler() {
+        new KeyValueStore().start();
+        client.connect();
+    }
+
+    @Override
+    @Asynchronous
+    public void get(HttpRequest request, final HttpResponse response) {
+        client.get("deft", new AsyncResult<byte[]>() {
+            @Override
+            public void onFailure(Throwable caught) { /* ignore */
+            }
+
+            @Override
+            public void onSuccess(byte[] result) {
+                response.write(new String(result)).finish();
+            }
+        });
+    }
+}

Propchange: incubator/deft/sandbox/src/main/java/org/deftserver/example/keyvalue/KeyValueStoreHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/deft/sandbox/src/main/java/org/deftserver/util/ReflectionTools.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/util/ReflectionTools.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/util/ReflectionTools.java (added)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/util/ReflectionTools.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,62 @@
+/*
+ *  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.deftserver.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Common functionality relating to the use of Reflection.
+ */
+public class ReflectionTools {
+
+    private final static Logger logger = LoggerFactory.getLogger(ReflectionTools.class);
+
+    /**
+     * Prevent instantiation of this type.
+     */
+    private ReflectionTools() {
+        // Do nothing.
+    }
+
+    /**
+     * Create an instance of the given type.
+     * 
+     * @param fqcn the fully-qualified class name of the required type.
+     * @return an <code>Object</code> of the requested type, or
+     *         <code>null</code> on any problem.
+     */
+    public static Object createInstance(String fqcn) {
+
+        Object instance = null;
+
+        try {
+            instance = Class.forName(fqcn).newInstance();
+        } catch (InstantiationException e) {
+            logger.error("InstantiationException", e);
+        } catch (IllegalAccessException e) {
+            logger.error("IllegalAccessException", e);
+        } catch (ClassNotFoundException e) {
+            logger.error("ClassNotFoundException", e);
+        }
+
+        return instance;
+    }
+}

Propchange: incubator/deft/sandbox/src/main/java/org/deftserver/util/ReflectionTools.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/deft/sandbox/src/main/java/org/deftserver/web/HttpServer.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/main/java/org/deftserver/web/HttpServer.java?rev=1153226&r1=1153225&r2=1153226&view=diff
==============================================================================
--- incubator/deft/sandbox/src/main/java/org/deftserver/web/HttpServer.java (original)
+++ incubator/deft/sandbox/src/main/java/org/deftserver/web/HttpServer.java Tue Aug  2 17:59:22 2011
@@ -24,99 +24,115 @@ import java.net.InetSocketAddress;
 import java.nio.channels.SelectionKey;
 import java.nio.channels.ServerSocketChannel;
 import java.util.List;
+import java.util.Map;
 
+import org.deftserver.configuration.AnnotationsScanner;
+import org.deftserver.configuration.Configuration;
 import org.deftserver.io.IOLoop;
 import org.deftserver.util.Closeables;
+import org.deftserver.web.handler.RequestHandler;
 import org.deftserver.web.http.HttpProtocol;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 
 public class HttpServer {
-	
-	private final Logger logger = LoggerFactory.getLogger(HttpServer.class);
-	
-	private static final int MIN_PORT_NUMBER = 1;
-	private static final int MAX_PORT_NUMBER = 65535;
-	
-	private ServerSocketChannel serverChannel;
-	private final List<IOLoop> ioLoops = Lists.newLinkedList();
-	
-	private final Application application;
-	
-	public HttpServer(Application application) {
-		this.application = application;
-	}
-
-	/**
-	 * If you want to run Deft on multiple threads first invoke {@link #bind(int)} then {@link #start(int)} 
-	 * instead of {@link #listen(int)} (listen starts Deft http server on a single thread with the default IOLoop 
-	 * instance: {@code IOLoop.INSTANCE}).
-	 * 
-	 * @return this for chaining purposes
-	 */
-	public void listen(int port) {
-		bind(port);
-		ioLoops.add(IOLoop.INSTANCE);
-		registerHandler(IOLoop.INSTANCE, new HttpProtocol(application));
-	}
-	
-	public void bind(int port) {
-		if (port <= MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) {
-			throw new IllegalArgumentException("Invalid port number. Valid range: [" + 
-					MIN_PORT_NUMBER + ", " + MAX_PORT_NUMBER + ")");
-		}
-		
-		try {
-			serverChannel = ServerSocketChannel.open();
-			serverChannel.configureBlocking(false);
-		} catch (IOException e) {
-			logger.error("Error creating ServerSocketChannel: {}", e);
-		}
-		
-		InetSocketAddress endpoint = new InetSocketAddress(port);	// use "any" address
-		try {
-			serverChannel.socket().bind(endpoint);
-		} catch (IOException e) {
-			logger.error("Could not bind socket: {}", e);
-		}	
-	}
-	
-	public void start(int numThreads) {
-		for (int i = 0; i < numThreads; i++) {
-			final IOLoop ioLoop = new IOLoop();
-			ioLoops.add(ioLoop);
-			final HttpProtocol protocol = new HttpProtocol(ioLoop, application);
-			new Thread(new Runnable() {
-				
-				@Override public void run() {
-					registerHandler(ioLoop, protocol);
-					ioLoop.start();
-				}
-			}).start();
-		}
-	}
-	
-	/**
-	 * Unbinds the port and shutdown the HTTP server
-	 */
-	public void stop() {
-		logger.debug("Stopping HTTP server");
-		for (IOLoop ioLoop : ioLoops) {
-			// TODO RS 110527 Should probably do this in each IOLoop through an AsyncCallback 
-			// (hint: ioloop.addCallback(..))
-			Closeables.closeQuietly(ioLoop, serverChannel);
-		}
-	}
-	
-	private void registerHandler(IOLoop ioLoop, HttpProtocol protocol) {
-		ioLoop.addHandler(
-				serverChannel,
-				protocol, 
-				SelectionKey.OP_ACCEPT,
-				null /*attachment*/
-		);
-	}
+
+    private final Logger logger = LoggerFactory.getLogger(HttpServer.class);
+
+    private static final int MIN_PORT_NUMBER = 1;
+    private static final int MAX_PORT_NUMBER = 65535;
+
+    private ServerSocketChannel serverChannel;
+    private final List<IOLoop> ioLoops = Lists.newLinkedList();
+
+    private final Application application;
+
+    public HttpServer(Configuration configuration) {
+
+        if (Strings.isNullOrEmpty(configuration.getHandlerPackage())) {
+            logger.warn("No RequestHandler found under package [" + configuration.getHandlerPackage() + "]");
+        }
+
+        application = createApplication(configuration.getHandlerPackage());
+    }
+
+    protected Application createApplication(String packageName) {
+
+        Map<String, RequestHandler> handlers = new AnnotationsScanner().findHandlers(packageName);
+        return new Application(handlers);
+    }
+
+    /**
+     * If you want to run Deft on multiple threads first invoke
+     * {@link #bind(int)} then {@link #start(int)} instead of
+     * {@link #listen(int)} (listen starts Deft http server on a single thread
+     * with the default IOLoop instance: {@code IOLoop.INSTANCE}).
+     * 
+     * @return this for chaining purposes
+     */
+    public void listen(int port) {
+        bind(port);
+        ioLoops.add(IOLoop.INSTANCE);
+        registerHandler(IOLoop.INSTANCE, new HttpProtocol(application));
+    }
+
+    public void bind(int port) {
+        if (port <= MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) {
+            throw new IllegalArgumentException("Invalid port number. Valid range: [" + MIN_PORT_NUMBER + ", "
+                    + MAX_PORT_NUMBER + ")");
+        }
+
+        try {
+            serverChannel = ServerSocketChannel.open();
+            serverChannel.configureBlocking(false);
+        } catch (IOException e) {
+            logger.error("Error creating ServerSocketChannel: {}", e);
+        }
+
+        InetSocketAddress endpoint = new InetSocketAddress(port); // use "any"
+        // address
+        try {
+            serverChannel.socket().bind(endpoint);
+        } catch (IOException e) {
+            logger.error("Could not bind socket: {}", e);
+        }
+    }
+
+    public void start(int numThreads) {
+        for (int i = 0; i < numThreads; i++) {
+            final IOLoop ioLoop = new IOLoop();
+            ioLoops.add(ioLoop);
+            final HttpProtocol protocol = new HttpProtocol(ioLoop, application);
+            new Thread(new Runnable() {
+
+                @Override
+                public void run() {
+                    registerHandler(ioLoop, protocol);
+                    ioLoop.start();
+                }
+            }).start();
+        }
+    }
+
+    /**
+     * Unbinds the port and shutdown the HTTP server
+     */
+    public void stop() {
+        logger.debug("Stopping HTTP server");
+        for (IOLoop ioLoop : ioLoops) {
+            // TODO RS 110527 Should probably do this in each IOLoop through an
+            // AsyncCallback
+            // (hint: ioloop.addCallback(..))
+            Closeables.closeQuietly(ioLoop, serverChannel);
+        }
+    }
+
+    private void registerHandler(IOLoop ioLoop, HttpProtocol protocol) {
+        ioLoop.addHandler(serverChannel, protocol, SelectionKey.OP_ACCEPT, null /* attachment */
+        );
+    }
 
 }

Added: incubator/deft/sandbox/src/test/java/org/deftserver/configuration/AnnotationsScannerTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/test/java/org/deftserver/configuration/AnnotationsScannerTest.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/test/java/org/deftserver/configuration/AnnotationsScannerTest.java (added)
+++ incubator/deft/sandbox/src/test/java/org/deftserver/configuration/AnnotationsScannerTest.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,51 @@
+/*
+ *  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.deftserver.configuration;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.deftserver.web.handler.RequestHandler;
+import org.junit.Test;
+
+/**
+ * Test cases for {@link AnnotationsScanner}.
+ */
+public class AnnotationsScannerTest {
+
+    @Test
+    public void testFindHandlers() {
+
+        AnnotationsScanner scanner = new AnnotationsScanner();
+        Map<String, RequestHandler> handlers = scanner.findHandlers("org.deftserver.example.handler");
+
+        assertEquals(3, handlers.size());
+    }
+
+    @Test
+    public void testFindHandlersForBadPath() {
+
+        AnnotationsScanner scanner = new AnnotationsScanner();
+        Map<String, RequestHandler> handlers = scanner.findHandlers("org.does.not.exist");
+
+        assertEquals(0, handlers.size());
+    }
+}

Propchange: incubator/deft/sandbox/src/test/java/org/deftserver/configuration/AnnotationsScannerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/deft/sandbox/src/test/java/org/deftserver/configuration/ConfigurationTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/test/java/org/deftserver/configuration/ConfigurationTest.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/test/java/org/deftserver/configuration/ConfigurationTest.java (added)
+++ incubator/deft/sandbox/src/test/java/org/deftserver/configuration/ConfigurationTest.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,61 @@
+/*
+ *  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.deftserver.configuration;
+
+import static org.deftserver.configuration.Configuration.DEFAULT_STATIC_DIRECTORY;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+/**
+ * Test cases for {@link Configuration}.
+ */
+public class ConfigurationTest {
+
+    @Test
+    public void testGetHandlerPackage() {
+
+        Configuration configuration = new Configuration();
+
+        assertNull(configuration.getHandlerPackage());
+
+        configuration.setHandlerPackage("org.apache.deft");
+        assertEquals("org.apache.deft", configuration.getHandlerPackage());
+    }
+
+    @Test
+    public void testGetStaticDirectory() {
+
+        Configuration configuration = new Configuration();
+
+        configuration.setStaticDirectory(null);
+        assertEquals(DEFAULT_STATIC_DIRECTORY, configuration.getStaticDirectory());
+
+        configuration.setStaticDirectory("  ");
+        assertEquals(DEFAULT_STATIC_DIRECTORY, configuration.getStaticDirectory());
+
+        configuration.setStaticDirectory("");
+        assertEquals(DEFAULT_STATIC_DIRECTORY, configuration.getStaticDirectory());
+
+        configuration.setStaticDirectory("files");
+        assertEquals("files", configuration.getStaticDirectory());
+    }
+}

Propchange: incubator/deft/sandbox/src/test/java/org/deftserver/configuration/ConfigurationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/deft/sandbox/src/test/java/org/deftserver/util/ReflectionToolsTest.java
URL: http://svn.apache.org/viewvc/incubator/deft/sandbox/src/test/java/org/deftserver/util/ReflectionToolsTest.java?rev=1153226&view=auto
==============================================================================
--- incubator/deft/sandbox/src/test/java/org/deftserver/util/ReflectionToolsTest.java (added)
+++ incubator/deft/sandbox/src/test/java/org/deftserver/util/ReflectionToolsTest.java Tue Aug  2 17:59:22 2011
@@ -0,0 +1,39 @@
+/*
+ *  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.deftserver.util;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+
+/**
+ * Test cases for {@link ReflectionTools}.
+ */
+public class ReflectionToolsTest {
+
+    @Test
+    public void testCreateInstance() {
+
+        Object created = ReflectionTools.createInstance(ReflectionToolsTest.class.getCanonicalName());
+        assertNotNull(created);
+        assertTrue(created instanceof ReflectionToolsTest);
+    }
+}

Propchange: incubator/deft/sandbox/src/test/java/org/deftserver/util/ReflectionToolsTest.java
------------------------------------------------------------------------------
    svn:eol-style = native