You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by re...@apache.org on 2008/08/06 22:08:49 UTC

svn commit: r683388 - in /cocoon/whiteboard/corona/trunk/corona-rest: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/cocoon/ src/main/java/org/apache/cocoon/corona/ src/main/java/org/apache/cocoon...

Author: reinhard
Date: Wed Aug  6 13:08:48 2008
New Revision: 683388

URL: http://svn.apache.org/viewvc?rev=683388&view=rev
Log:
add a controller implementation optimized for the implementation of RESTful web services

Added:
    cocoon/whiteboard/corona/trunk/corona-rest/   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/pom.xml   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanNameGenerator.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanScopeResolver.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/MethodDelegator.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/SpringRESTController.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/BaseURL.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/Inject.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RESTController.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestHeader.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestParameter.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/SitemapParameter.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Delete.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Get.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Head.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Options.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Post.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Put.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Page.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/RestResponse.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Status.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/AnnotationCollector.java   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/
    cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/corona-rest.xml   (with props)
    cocoon/whiteboard/corona/trunk/corona-rest/src/test/
    cocoon/whiteboard/corona/trunk/corona-rest/src/test/java/
    cocoon/whiteboard/corona/trunk/corona-rest/src/test/resources/

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Aug  6 13:08:48 2008
@@ -0,0 +1,4 @@
+.settings
+target
+.classpath
+.project

Added: cocoon/whiteboard/corona/trunk/corona-rest/pom.xml
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/pom.xml?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/pom.xml (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/pom.xml Wed Aug  6 13:08:48 2008
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+ -->
+<!-- $Id$ -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+  <packaging>jar</packaging>
+
+  <parent>
+    <groupId>org.apache.cocoon.corona</groupId>
+    <artifactId>corona-parent</artifactId>
+    <version>1-SNAPSHOT</version>
+    <relativePath>../parent/pom.xml</relativePath>
+  </parent>
+
+  <artifactId>corona-rest</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <name>Cocoon Corona: REST support [jar]</name>
+  <description>RESTful web services with Corona.</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.cocoon.corona</groupId>
+      <artifactId>corona-controller</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.cocoon.corona</groupId>
+      <artifactId>corona-servlet</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <scope>provided</scope>
+    </dependency>    
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+</project>

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/pom.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/pom.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanNameGenerator.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanNameGenerator.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanNameGenerator.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanNameGenerator.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,21 @@
+package org.apache.cocoon.corona.rest.controller;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.BeanNameGenerator;
+
+/**
+ * Provide a bean name generator, that returns the fully qualified class name as bean name.
+ */
+public class ControllerBeanNameGenerator implements BeanNameGenerator {
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.springframework.beans.factory.support.BeanNameGenerator#generateBeanName(org.springframework.beans.factory.config.BeanDefinition,
+     *      org.springframework.beans.factory.support.BeanDefinitionRegistry)
+     */
+    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
+        return definition.getBeanClassName();
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanNameGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanNameGenerator.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanNameGenerator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanScopeResolver.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanScopeResolver.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanScopeResolver.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanScopeResolver.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,22 @@
+package org.apache.cocoon.corona.rest.controller;
+
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.context.annotation.ScopeMetadata;
+import org.springframework.context.annotation.ScopeMetadataResolver;
+
+/**
+ * Set the scope for all REST controller to {@link BeanDefinition#SCOPE_PROTOTYPE}.
+ */
+public class ControllerBeanScopeResolver implements ScopeMetadataResolver {
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.springframework.context.annotation.ScopeMetadataResolver#resolveScopeMetadata(org.springframework.beans.factory.config.BeanDefinition)
+     */
+    public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
+        ScopeMetadata scopeMetadata = new ScopeMetadata();
+        scopeMetadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
+        return scopeMetadata;
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanScopeResolver.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanScopeResolver.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/ControllerBeanScopeResolver.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/MethodDelegator.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/MethodDelegator.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/MethodDelegator.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/MethodDelegator.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,138 @@
+package org.apache.cocoon.corona.rest.controller;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.cocoon.corona.rest.controller.method.Delete;
+import org.apache.cocoon.corona.rest.controller.method.Get;
+import org.apache.cocoon.corona.rest.controller.method.Head;
+import org.apache.cocoon.corona.rest.controller.method.Options;
+import org.apache.cocoon.corona.rest.controller.method.Post;
+import org.apache.cocoon.corona.rest.controller.method.Put;
+import org.apache.cocoon.corona.rest.controller.response.RestResponse;
+import org.apache.cocoon.corona.rest.controller.response.Status;
+
+public class MethodDelegator {
+
+    private Map<String, MethodDelegate> delegates = new HashMap<String, MethodDelegate>();
+
+    public MethodDelegator() {
+        super();
+
+        this.delegates.put("DELETE", new DeleteDelegate());
+        this.delegates.put("GET", new GetDelegate());
+        this.delegates.put("HEAD", new HeadDelegate());
+        this.delegates.put("OPTIONS", new OptionsDelegate());
+        this.delegates.put("POST", new PostDelegate());
+        this.delegates.put("PUT", new PutDelegate());
+    }
+
+    public RestResponse delegate(HttpServletRequest request, Object controller) throws Exception {
+        if (request != null && request.getMethod() != null) {
+            String method = this.getMethod(request);
+
+            MethodDelegate methodDelegate = this.delegates.get(method);
+            if (methodDelegate != null) {
+                return methodDelegate.execute(controller);
+            }
+        }
+
+        return new Status(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+    }
+
+    private String getMethod(HttpServletRequest request) {
+        String alternativeMethod = request.getParameter("_method");
+        if (alternativeMethod != null) {
+            if (this.delegates.keySet().contains(alternativeMethod.toUpperCase())) {
+                return alternativeMethod.toUpperCase();
+            }
+
+            // TODO log the unsupported method name
+        }
+
+        return request.getMethod().toUpperCase();
+    }
+
+    private class DeleteDelegate extends MethodDelegate {
+
+        @Override
+        public RestResponse execute(Object controller) throws Exception {
+            if (controller instanceof Delete) {
+                Delete delete = (Delete) controller;
+                return delete.doDelete();
+            }
+            return super.execute(controller);
+        }
+    }
+
+    private class GetDelegate extends MethodDelegate {
+
+        @Override
+        public RestResponse execute(Object controller) throws Exception {
+            if (controller instanceof Get) {
+                Get get = (Get) controller;
+                return get.doGet();
+            }
+            return super.execute(controller);
+        }
+    }
+
+    private class HeadDelegate extends MethodDelegate {
+
+        @Override
+        public RestResponse execute(Object controller) throws Exception {
+            if (controller instanceof Head) {
+                Head head = (Head) controller;
+                return head.doHead();
+            }
+            return super.execute(controller);
+        }
+    }
+
+    private abstract class MethodDelegate {
+
+        public RestResponse execute(Object controller) throws Exception {
+            return new Status(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
+        }
+    }
+
+    private class OptionsDelegate extends MethodDelegate {
+
+        @Override
+        public RestResponse execute(Object controller) throws Exception {
+            if (controller instanceof Options) {
+                Options options = (Options) controller;
+                return options.doOptions();
+            }
+            return super.execute(controller);
+        }
+    }
+
+    private class PostDelegate extends MethodDelegate {
+
+        @Override
+        public RestResponse execute(Object controller) throws Exception {
+            if (controller instanceof Post) {
+                Post post = (Post) controller;
+                return post.doPost();
+            }
+
+            return super.execute(controller);
+        }
+    }
+
+    private class PutDelegate extends MethodDelegate {
+
+        @Override
+        public RestResponse execute(Object controller) throws Exception {
+            if (controller instanceof Put) {
+                Put put = (Put) controller;
+                return put.doPut();
+            }
+            return super.execute(controller);
+        }
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/MethodDelegator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/MethodDelegator.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/MethodDelegator.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/SpringRESTController.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/SpringRESTController.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/SpringRESTController.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/SpringRESTController.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,282 @@
+package org.apache.cocoon.corona.rest.controller;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.cocoon.corona.controller.Controller;
+import org.apache.cocoon.corona.pipeline.util.URLConnectionUtils;
+import org.apache.cocoon.corona.rest.controller.annotation.BaseURL;
+import org.apache.cocoon.corona.rest.controller.annotation.Inject;
+import org.apache.cocoon.corona.rest.controller.annotation.RESTController;
+import org.apache.cocoon.corona.rest.controller.annotation.RequestHeader;
+import org.apache.cocoon.corona.rest.controller.annotation.RequestParameter;
+import org.apache.cocoon.corona.rest.controller.annotation.SitemapParameter;
+import org.apache.cocoon.corona.rest.controller.response.Page;
+import org.apache.cocoon.corona.rest.controller.response.RestResponse;
+import org.apache.cocoon.corona.rest.controller.response.Status;
+import org.apache.cocoon.corona.rest.util.AnnotationCollector;
+import org.apache.cocoon.corona.servlet.controller.ControllerContextHelper;
+import org.apache.cocoon.corona.servlet.node.StatusCodeCollector;
+import org.apache.cocoon.corona.servlet.util.HttpContextHelper;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+/**
+ * <p>
+ * This controller is responsible for the execution of instances of REST controller beans. Note that each controller
+ * implementation must be available as Spring bean. For that purpose you can use the {@link RESTController} annotation
+ * and load all beans from a particular package automatically. See
+ * http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-classpath-scanning for details.
+ * </p>
+ */
+public class SpringRESTController implements Controller, ApplicationContextAware {
+
+    private org.apache.cocoon.corona.rest.util.AnnotationCollector annotationCollector;
+
+    private ApplicationContext applicationContext;
+
+    private MethodDelegator methodDelegator;
+
+    public void invoke(OutputStream outputStream, String functionName, Map<String, Object> inputParameters,
+            Map<String, ? extends Object> configuration) {
+        if (!this.applicationContext.isPrototype(functionName)) {
+            throw new RuntimeException("A REST controller bean MUST run within the 'prototype' scope.");
+        }
+
+        try {
+            // get the prepared controller
+            Object controller = this.getController(functionName, inputParameters, configuration);
+
+            // invoke the appropriate method
+            HttpServletRequest request = HttpContextHelper.getRequest(inputParameters);
+            RestResponse restResponse = this.methodDelegator.delegate(request, controller);
+
+            // forward the response
+            if (restResponse instanceof Status) {
+                Status status = (Status) restResponse;
+                StatusCodeCollector.setStatusCode(status.getStatus());
+            } else if (restResponse instanceof Page) {
+                Page page = (Page) restResponse;
+
+                ControllerContextHelper.storeContext(page.getData(), inputParameters);
+
+                URL pageUri = new URL(new URL("servlet:/"), page.getUri());
+                URLConnection servletConnection = pageUri.openConnection();
+                IOUtils.copy(servletConnection.getInputStream(), outputStream);
+                URLConnectionUtils.closeQuietly(servletConnection);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public void setAnnotationCollector(AnnotationCollector annotationCollector) {
+        this.annotationCollector = annotationCollector;
+    }
+
+    /**
+     * {@inheritDoc}
+     * 
+     * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
+     */
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        this.applicationContext = applicationContext;
+    }
+
+    public void setMethodDelegator(MethodDelegator methodDelegator) {
+        this.methodDelegator = methodDelegator;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Object getController(String controllerName, Map<String, Object> inputParameters,
+            Map<String, ? extends Object> configuration) throws Exception {
+        Object controller = this.applicationContext.getBean(controllerName);
+
+        Map<Class<? extends Annotation>, List<Field>> annotatedFields = this.annotationCollector
+                .getAnnotatedFields(controller.getClass());
+
+        // populate the annotated fields
+        populateInjectFields(inputParameters, controller, annotatedFields);
+        populateRequestFields(inputParameters, controller, annotatedFields);
+        populateRequestHeaderFields(inputParameters, controller, annotatedFields);
+        populateSitemapParameters(configuration, controller, annotatedFields);
+        this.populateBaseURL(configuration, controller, annotatedFields);
+
+        return controller;
+    }
+
+    private void populateBaseURL(Map<String, ? extends Object> configuration, Object controller,
+            Map<Class<? extends Annotation>, List<Field>> annotatedFields) throws IllegalAccessException, Exception {
+        List<Field> baseURLFields = annotatedFields.get(BaseURL.class);
+        if (baseURLFields == null || baseURLFields.isEmpty()) {
+            return;
+        }
+
+        for (Field field : baseURLFields) {
+            field.setAccessible(true);
+
+            Class<?> fieldType = field.getType();
+            if (fieldType == URL.class) {
+                field.set(controller, configuration.get("baseUrl"));
+            } else {
+                throw new Exception("The annotation " + BaseURL.class.getName() + " can only be set on fields of type "
+                        + URL.class.getName() + "." + " " + "(field=" + field.getName() + ", type="
+                        + fieldType.getName() + ")");
+            }
+        }
+
+    }
+
+    private static void populateInjectFields(Map<String, ? extends Object> parameters, Object controller,
+            Map<Class<? extends Annotation>, List<Field>> annotatedFields) throws IllegalAccessException, IOException,
+            Exception {
+        List<Field> injectFields = annotatedFields.get(Inject.class);
+        if (injectFields == null || injectFields.isEmpty()) {
+            return;
+        }
+
+        HttpServletRequest request = HttpContextHelper.getRequest(parameters);
+        HttpServletResponse response = HttpContextHelper.getResponse(parameters);
+        for (Field field : injectFields) {
+            field.setAccessible(true);
+
+            Class<?> fieldType = field.getType();
+            if (fieldType == HttpServletRequest.class) {
+                field.set(controller, request);
+            } else if (fieldType == HttpServletResponse.class) {
+                field.set(controller, response);
+            } else if (fieldType == Log.class) {
+                field.set(controller, LogFactory.getLog(controller.getClass()));
+            } else if (fieldType == ServletInputStream.class || fieldType == InputStream.class) {
+                field.set(controller, request.getInputStream());
+            } else if (fieldType == ServletOutputStream.class || fieldType == OutputStream.class) {
+                field.set(controller, response.getOutputStream());
+            } else {
+                throw new Exception("The annotation " + Inject.class.getName()
+                        + " doesn't support the injection of type " + fieldType.getName() + "." + " " + "(field="
+                        + field.getName() + ", type=" + fieldType.getName() + ")");
+            }
+        }
+    }
+
+    private static void populateRequestFields(Map<String, ? extends Object> parameters, Object controller,
+            Map<Class<? extends Annotation>, List<Field>> annotatedFields) throws IllegalAccessException, Exception {
+        List<Field> requestFields = annotatedFields.get(RequestParameter.class);
+        if (requestFields == null || requestFields.isEmpty()) {
+            return;
+        }
+
+        HttpServletRequest request = HttpContextHelper.getRequest(parameters);
+        for (Field field : requestFields) {
+            field.setAccessible(true);
+
+            String requestParameterName = field.getAnnotation(RequestParameter.class).value();
+            if (isBlank(requestParameterName)) {
+                requestParameterName = field.getName();
+            }
+
+            Class<?> fieldType = field.getType();
+            if (fieldType == String.class) {
+                String parameter = request.getParameter(requestParameterName);
+                if (parameter != null) {
+                    field.set(controller, parameter);
+                }
+            } else if (fieldType == String[].class) {
+                String[] parameterValues = request.getParameterValues(requestParameterName);
+                if (parameterValues != null) {
+                    field.set(controller, parameterValues);
+                }
+            } else {
+                throw new Exception("The annotation " + RequestParameter.class.getName()
+                        + " can only be set on fields of type " + String.class.getName() + " or "
+                        + String[].class.getName() + ". " + "(field=" + field.getName() + ", type="
+                        + fieldType.getName() + ")");
+            }
+        }
+    }
+
+    private static void populateRequestHeaderFields(Map<String, ? extends Object> parameters, Object controller,
+            Map<Class<? extends Annotation>, List<Field>> annotatedFields) throws IllegalAccessException, Exception {
+        List<Field> requestHeaderFields = annotatedFields.get(RequestHeader.class);
+        if (requestHeaderFields == null || requestHeaderFields.isEmpty()) {
+            return;
+        }
+
+        HttpServletRequest request = HttpContextHelper.getRequest(parameters);
+        for (Field field : requestHeaderFields) {
+            field.setAccessible(true);
+
+            String name = field.getAnnotation(RequestHeader.class).value();
+            if (isBlank(name)) {
+                name = field.getName();
+            }
+
+            Class<?> fieldType = field.getType();
+            if (fieldType == String.class) {
+                String header = request.getHeader(name);
+                if (header != null) {
+                    field.set(controller, header);
+                }
+            } else {
+                throw new Exception("The annotation " + RequestHeader.class.getName()
+                        + " can only be set on fields of type " + String.class.getName() + "." + " " + "(field="
+                        + field.getName() + ", type=" + fieldType.getName() + ")");
+            }
+        }
+    }
+
+    private static void populateSitemapParameters(Map<String, ? extends Object> configuration, Object controller,
+            Map<Class<? extends Annotation>, List<Field>> annotatedFields) throws IllegalAccessException, Exception {
+        List<Field> sitemapParameterFields = annotatedFields.get(SitemapParameter.class);
+        if (sitemapParameterFields == null || sitemapParameterFields.isEmpty()) {
+            return;
+        }
+
+        for (Field field : sitemapParameterFields) {
+            field.setAccessible(true);
+
+            String name = field.getAnnotation(SitemapParameter.class).value();
+            if (isBlank(name)) {
+                name = field.getName();
+            }
+
+            Class<?> fieldType = field.getType();
+            if (fieldType == String.class) {
+                field.set(controller, configuration.get(name));
+            } else {
+                throw new Exception("The annotation " + SitemapParameter.class.getName()
+                        + " can only be set on fields of type " + String.class.getName() + "." + " " + "(field="
+                        + field.getName() + ", type=" + fieldType.getName() + ")");
+            }
+        }
+    }
+
+    private static boolean isBlank(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return true;
+        }
+        for (int i = 0; i < strLen; i++) {
+            if (Character.isWhitespace(str.charAt(i)) == false) {
+                return false;
+            }
+        }
+        return true;
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/SpringRESTController.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/SpringRESTController.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/SpringRESTController.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/BaseURL.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/BaseURL.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/BaseURL.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/BaseURL.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,16 @@
+package org.apache.cocoon.corona.rest.controller.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation will be used in {@link RestController} classes to the base URL of the current request.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Inherited
+public @interface BaseURL {
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/BaseURL.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/BaseURL.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/BaseURL.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/Inject.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/Inject.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/Inject.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/Inject.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,16 @@
+package org.apache.cocoon.corona.rest.controller.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation will be used in {@link RestController} classes to inject the object that matches the field type.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Inherited
+public @interface Inject {
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/Inject.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/Inject.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/Inject.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RESTController.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RESTController.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RESTController.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RESTController.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,16 @@
+package org.apache.cocoon.corona.rest.controller.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation marks a REST controller bean.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.TYPE)
+@Inherited
+public @interface RESTController {
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RESTController.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RESTController.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RESTController.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestHeader.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestHeader.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestHeader.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestHeader.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,17 @@
+package org.apache.cocoon.corona.rest.controller.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation will be used {@link RestController} classes to access sitemap parameters.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Inherited
+public @interface RequestHeader {
+    String value() default "";
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestHeader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestHeader.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestHeader.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestParameter.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestParameter.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestParameter.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestParameter.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,17 @@
+package org.apache.cocoon.corona.rest.controller.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation will be used {@link RestController} classes to access sitemap parameters.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Inherited
+public @interface RequestParameter {
+    String value() default "";
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestParameter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestParameter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/RequestParameter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/SitemapParameter.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/SitemapParameter.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/SitemapParameter.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/SitemapParameter.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,17 @@
+package org.apache.cocoon.corona.rest.controller.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation will be used {@link RestController} classes to access sitemap parameters.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@Inherited
+public @interface SitemapParameter {
+    String value() default "";
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/SitemapParameter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/SitemapParameter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/annotation/SitemapParameter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Delete.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Delete.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Delete.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Delete.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,8 @@
+package org.apache.cocoon.corona.rest.controller.method;
+
+import org.apache.cocoon.corona.rest.controller.response.RestResponse;
+
+public interface Delete {
+
+    RestResponse doDelete() throws Exception;
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Delete.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Delete.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Delete.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Get.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Get.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Get.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Get.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,8 @@
+package org.apache.cocoon.corona.rest.controller.method;
+
+import org.apache.cocoon.corona.rest.controller.response.RestResponse;
+
+public interface Get {
+
+    RestResponse doGet() throws Exception;
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Get.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Get.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Get.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Head.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Head.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Head.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Head.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,8 @@
+package org.apache.cocoon.corona.rest.controller.method;
+
+import org.apache.cocoon.corona.rest.controller.response.RestResponse;
+
+public interface Head {
+
+    RestResponse doHead() throws Exception;
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Head.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Head.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Head.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Options.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Options.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Options.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Options.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,8 @@
+package org.apache.cocoon.corona.rest.controller.method;
+
+import org.apache.cocoon.corona.rest.controller.response.RestResponse;
+
+public interface Options {
+
+    RestResponse doOptions() throws Exception;
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Options.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Options.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Options.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Post.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Post.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Post.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Post.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,8 @@
+package org.apache.cocoon.corona.rest.controller.method;
+
+import org.apache.cocoon.corona.rest.controller.response.RestResponse;
+
+public interface Post {
+
+    RestResponse doPost() throws Exception;
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Post.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Post.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Post.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Put.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Put.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Put.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Put.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,8 @@
+package org.apache.cocoon.corona.rest.controller.method;
+
+import org.apache.cocoon.corona.rest.controller.response.RestResponse;
+
+public interface Put {
+
+    RestResponse doPut() throws Exception;
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Put.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Put.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/method/Put.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Page.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Page.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Page.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Page.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,27 @@
+package org.apache.cocoon.corona.rest.controller.response;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class Page implements RestResponse {
+
+    private String uri;
+
+    private Map<String, Object> data;
+
+    public Page(String uri, Map<String, Object> data) {
+        this.uri = uri;
+        this.data = data;
+    }
+
+    public Map<String, Object> getData() {
+        if (this.data == null) {
+            this.data = new HashMap<String, Object>();
+        }
+        return this.data;
+    }
+
+    public String getUri() {
+        return this.uri;
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Page.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Page.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Page.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/RestResponse.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/RestResponse.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/RestResponse.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/RestResponse.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,4 @@
+package org.apache.cocoon.corona.rest.controller.response;
+
+public interface RestResponse {
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/RestResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/RestResponse.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/RestResponse.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Status.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Status.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Status.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Status.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,14 @@
+package org.apache.cocoon.corona.rest.controller.response;
+
+public class Status implements RestResponse {
+
+    private int status;
+
+    public Status(int status) {
+        this.status = status;
+    }
+
+    public int getStatus() {
+        return this.status;
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Status.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Status.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/controller/response/Status.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/AnnotationCollector.java
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/AnnotationCollector.java?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/AnnotationCollector.java (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/AnnotationCollector.java Wed Aug  6 13:08:48 2008
@@ -0,0 +1,102 @@
+package org.apache.cocoon.corona.rest.util;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.cocoon.corona.rest.controller.annotation.BaseURL;
+import org.apache.cocoon.corona.rest.controller.annotation.Inject;
+import org.apache.cocoon.corona.rest.controller.annotation.RequestHeader;
+import org.apache.cocoon.corona.rest.controller.annotation.RequestParameter;
+import org.apache.cocoon.corona.rest.controller.annotation.SitemapParameter;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class AnnotationCollector {
+
+    private static final Log LOG = LogFactory.getLog(AnnotationCollector.class);
+
+    private Map<Class<?>, Map<Class<? extends Annotation>, List<Field>>> annotatedFields = new HashMap<Class<?>, Map<Class<? extends Annotation>, List<Field>>>();
+    private Set<Class<? extends Annotation>> relevantAnnotations;
+
+    public AnnotationCollector() {
+        super();
+
+        this.relevantAnnotations = new HashSet<Class<? extends Annotation>>();
+        this.relevantAnnotations.add(BaseURL.class);
+        this.relevantAnnotations.add(Inject.class);
+        this.relevantAnnotations.add(RequestHeader.class);
+        this.relevantAnnotations.add(RequestParameter.class);
+        this.relevantAnnotations.add(SitemapParameter.class);
+    }
+
+    public Map<Class<? extends Annotation>, List<Field>> getAnnotatedFields(Class<?> type) {
+        synchronized (type) {
+            Map<Class<? extends Annotation>, List<Field>> result = this.annotatedFields.get(type);
+
+            if (result == null) {
+                result = this.collectAnnotatedFields(type);
+                this.annotatedFields.put(type, result);
+            }
+
+            return result;
+        }
+    }
+
+    private Map<Class<? extends Annotation>, List<Field>> collectAnnotatedFields(Class<?> type) {
+        if (LOG.isDebugEnabled()) {
+            LOG.debug("Collecting annotations of class " + type + ".");
+        }
+
+        Map<Class<? extends Annotation>, List<Field>> result = new HashMap<Class<? extends Annotation>, List<Field>>();
+
+        for (Field field : this.getFields(type)) {
+            for (Annotation availableAnnotation : field.getAnnotations()) {
+                Class<? extends Annotation> annotationType = availableAnnotation.annotationType();
+                if (!this.relevantAnnotations.contains(annotationType)) {
+                    continue;
+                }
+
+                List<Field> annotatedFields = result.get(annotationType);
+                if (annotatedFields == null) {
+                    annotatedFields = new LinkedList<Field>();
+                    result.put(annotationType, annotatedFields);
+                }
+
+                annotatedFields.add(field);
+            }
+        }
+
+        return result;
+    }
+
+    private List<Field> getFields(Class<?> type) {
+        List<Field> result = new LinkedList<Field>();
+
+        Class<?> currentClass = type;
+        while (true) {
+            Field[] declaredFields = currentClass.getDeclaredFields();
+
+            for (Field declaredField : declaredFields) {
+                if (Modifier.isStatic(declaredField.getModifiers())) {
+                    continue;
+                }
+
+                result.add(declaredField);
+            }
+
+            currentClass = currentClass.getSuperclass();
+            if (currentClass == null) {
+                break;
+            }
+        }
+
+        return result;
+    }
+}

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/AnnotationCollector.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/AnnotationCollector.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/java/org/apache/cocoon/corona/rest/util/AnnotationCollector.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/corona-rest.xml
URL: http://svn.apache.org/viewvc/cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/corona-rest.xml?rev=683388&view=auto
==============================================================================
--- cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/corona-rest.xml (added)
+++ cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/corona-rest.xml Wed Aug  6 13:08:48 2008
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+ -->
+<!-- $Id$ -->
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
+  xmlns:context="http://www.springframework.org/schema/context"
+  xsi:schemaLocation="
+    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
+    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
+    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
+  ">
+
+  <!-- The REST controller -->
+  <bean name="org.apache.cocoon.corona.controller.Controller/rest-controller" class="org.apache.cocoon.corona.rest.controller.SpringRESTController">
+    <property name="methodDelegator" ref="org.apache.cocoon.corona.rest.controller.MethodDelegator" />
+    <property name="annotationCollector" ref="org.apache.cocoon.corona.rest.forms.util.AnnotationCollector" />
+  </bean>
+
+  <bean name="org.apache.cocoon.corona.rest.controller.MethodDelegator" class="org.apache.cocoon.corona.rest.controller.MethodDelegator" />
+
+  <bean name="org.apache.cocoon.corona.rest.forms.util.AnnotationCollector" class="org.apache.cocoon.corona.rest.util.AnnotationCollector" />
+
+</beans>

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/corona-rest.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/corona-rest.xml
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: cocoon/whiteboard/corona/trunk/corona-rest/src/main/resources/META-INF/cocoon/spring/corona-rest.xml
------------------------------------------------------------------------------
    svn:mime-type = text/xml