Author: plightbo
Date: Wed May  3 15:22:02 2006
New Revision: 399458

URL: http://svn.apache.org/viewcvs?rev=399458&view=rev
Log:
bob's API work, milestone 1

Added:
    incubator/webwork2/action-api/src/main/java/org/
    incubator/webwork2/action-api/src/main/java/org/apache/
    incubator/webwork2/action-api/src/main/java/org/apache/struts/
    incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Action.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ErrorAware.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/MessageAware.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Messages.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ResultNames.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Validatable.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/AbstractAttribute.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/ApplicationAttribute.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/Attribute.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/RequestAttribute.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/SessionAttribute.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/UnitOfWork.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/package-info.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/package-info.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ParameterAware.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletRequestAware.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletResponseAware.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/package-info.java
    incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Interceptor.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Request.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/RequestAware.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Result.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ThreadLocalRequest.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ValueStack.java
    
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/package-info.java
    incubator/webwork2/action-api/src/test/java/org/
    incubator/webwork2/action-api/src/test/java/org/apache/
    incubator/webwork2/action-api/src/test/java/org/apache/struts/
    incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/
    
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/
    
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/AttributeTest.java
    
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/ReferenceTest.java
    incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/spi/
    
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/spi/ThreadLocalRequestTest.java
Modified:
    incubator/webwork2/action-api/pom.xml

Modified: incubator/webwork2/action-api/pom.xml
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/pom.xml?rev=399458&r1=399457&r2=399458&view=diff
==============================================================================
--- incubator/webwork2/action-api/pom.xml (original)
+++ incubator/webwork2/action-api/pom.xml Wed May  3 15:22:02 2006
@@ -12,6 +12,34 @@
     <packaging>jar</packaging>
     <name>Struts Action Framework 2.0 API</name>
     <dependencies>
-
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+            <optional>true</optional>
+        </dependency>            
+        <dependency>
+            <groupId>easymock</groupId>
+            <artifactId>easymock</artifactId>
+            <scope>test</scope>
+            <version>2.0</version>
+        </dependency>
     </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <showPackage>false</showPackage>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Action.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Action.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Action.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Action.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,45 @@
+package org.apache.struts.action2;
+
+/**
+ * Default action interface. Provided purely for user convenience. Struts does 
not require actions to implement any
+ * interfaces. Actions need only implement a public, no argument method which 
returns [EMAIL PROTECTED] String}. If a user does
+ * not specify a method name, Struts defaults to [EMAIL PROTECTED] execute()}.
+ *
+ * <p>For example:
+ *
+ * <pre>
+ *   static import ResultNames.*;
+ *
+ *   public class MyAction <b>implements Action</b> {
+ *
+ *     public String execute() {
+ *       return SUCCESS;
+ *     }
+ *   }
+ * </pre>
+ *
+ * <p>is equivalent to:
+ *
+ * <pre>
+ *   static import ResultNames.*;
+ *
+ *   public class MyAction {
+ *
+ *     public String execute() {
+ *       return SUCCESS;
+ *     }
+ *   }
+ * </pre>
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface Action {
+
+    /**
+     * Executes this action.
+     *
+     * @return result name which matches a result name from the action mapping 
in the configuration file. See [EMAIL PROTECTED]
+     *  ResultNames} for common suggestions.
+     */
+    String execute();
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ErrorAware.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ErrorAware.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ErrorAware.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ErrorAware.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,45 @@
+package org.apache.struts.action2;
+
+/**
+ * Implemented by actions that may need to record error messages. For example:
+ *
+ * <pre>
+ *   static import ResultNames.*;
+ *
+ *   public class SetName implements ErrorAware {
+ *
+ *     Messages errors;
+ *     String name;
+ *
+ *     public String execute() {
+ *       if ("".equals(name) {
+ *         errors.add("name.required");
+ *         return INPUT;
+ *       }
+ *
+ *       ...
+ *       return SUCCESS;
+ *     }
+ *
+ *     public void setErrors(Messages errors) {
+ *       this.errors = errors;
+ *     }
+ *
+ *     public void setName(String name) {
+ *       this.name = name;
+ *     }
+ *   }
+ * </pre>
+ *
+ * @see MessageAware
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface ErrorAware {
+
+    /**
+     * Sets error messages.
+     *
+     * @param errors error messages
+     */
+    void setErrors(Messages errors);
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/MessageAware.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/MessageAware.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/MessageAware.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/MessageAware.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,35 @@
+package org.apache.struts.action2;
+
+/**
+ * Implemented by actions that may need to record messages.
+ *
+ * <pre>
+ *   static import ResultNames.*;
+ *
+ *   public class Welcome implements MessageAware {
+ *
+ *     Messages messages;
+ *
+ *     public String execute() {
+ *       messages.add("welcome");
+ *       return SUCCESS;
+ *     }
+ *
+ *     public void setMessages(Messages messages) {
+ *       this.messages = messages;
+ *     }
+ *   }
+ * </pre>
+ *
+ * @see ErrorAware
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface MessageAware {
+
+    /**
+     * Sets messages.
+     *
+     * @param messages messages
+     */
+    void setMessages(Messages messages);
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Messages.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Messages.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Messages.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Messages.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,72 @@
+package org.apache.struts.action2;
+
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Request and field-scoped messages or errors. Uses keys instead of actual 
messages to decouple code from messages.
+ * Messages may come from multiple actions and interceptors.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface Messages {
+
+    /**
+     * Adds request-scoped message.
+     *
+     * @param key message key
+     */
+    void add(String key);
+
+    /**
+     * Adds request-scoped message.
+     *
+     * @param key message key
+     * @param arguments message arguments
+     */
+    void add(String key, Object... arguments);
+
+    /**
+     * Adds field-scoped message.
+     *
+     * @param fieldName name of field to attach message to
+     * @param key message key
+     */
+    void add(String fieldName, String key);
+
+    /**
+     * Adds field-scoped message.
+     *
+     * @param fieldName name of field to attach message to
+     * @param key message key
+     * @param arguments message arguments
+     */
+    void add(String fieldName, String key, Object... arguments);
+
+    /**
+     * Gets request-scoped messages.
+     *
+     * @return unmodifiable list of messages for this request.
+     */
+    List<String> forRequest();
+
+    /**
+     * Gets field-scoped messages.
+     *
+     * @param fieldName field name
+     * @return unmodifiable list of messages for the given field name.
+     */
+    List<String> forField(String fieldName);
+
+    /**
+     * Gets names of fields which have messages attached.
+     *
+     * @return unmodifiable set of field names with messages attached.
+     */
+    Set<String> getFieldNames();
+
+    /**
+     * Returns true if no request or field-scoped messages have been added.
+     */
+    boolean isEmpty();
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ResultNames.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ResultNames.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ResultNames.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/ResultNames.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,36 @@
+package org.apache.struts.action2;
+
+/**
+ * Commonly used result names returned by action methods.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public final class ResultNames {
+
+    private ResultNames() {}
+
+    /**
+     * The action executed successfully.
+     */
+    public static final String SUCCESS = "success";
+
+    /**
+     * The action requires more input, i.e.&nbsp;a validation error occurred.
+     */
+    public static final String INPUT = "input";
+
+    /**
+     * The action requires the user to log in before executing.
+     */
+    public static final String LOGIN = "login";
+
+    /**
+     * The action execution failed irrecoverably.
+     */
+    public static final String ERROR = "error";
+
+    /**
+     * The action executed successfully, but do not execute a result.
+     */
+    public static final String NONE = "none";
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Validatable.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Validatable.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Validatable.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/Validatable.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,16 @@
+package org.apache.struts.action2;
+
+/**
+ * Implemented by actions which wish to execute some validation logic before 
their action method. Useful for
+ * cross-field validations.
+ *
+ * @see ErrorAware
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface Validatable {
+
+    /**
+     * Validates input. Executes before action method.
+     */
+    public void validate();
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/AbstractAttribute.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/AbstractAttribute.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/AbstractAttribute.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/AbstractAttribute.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,67 @@
+package org.apache.struts.action2.attribute;
+
+import java.util.Map;
+
+/**
+ * Support for [EMAIL PROTECTED] Attribute} implementations.
+ *
+ * <p>This class isn't public because we may want to optimize the 
implementation later. The current approach maximizes
+ * code reuse and only performs one thread local lookup per method invocation, 
but it also creates an object per
+ * invocation.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+abstract class AbstractAttribute<T> implements Attribute<T> {
+
+    String name;
+
+    AbstractAttribute(String name) {
+        if (name == null) {
+            throw new NullPointerException("Null name.");
+        }
+        this.name = name;
+    }
+
+    public T get() {
+        return execute(new UnitOfWork<T>() {
+            public T execute(Map<String, Object> map) {
+                T t = (T) map.get(name);
+                if (t == null) {
+                    t = initialValue();
+                    if (t != null) {
+                        map.put(name, t);
+                    }
+                }
+                return t;
+            }
+        });
+    }
+
+    public T set(final T t) {
+        return execute(new UnitOfWork<T>() {
+            public T execute(Map<String, Object> map) {
+                return (T) map.put(name, t);
+            }
+        });
+    }
+
+    public T remove() {
+        return execute(new UnitOfWork<T>() {
+            public T execute(Map<String, Object> map) {
+                return (T) map.remove(name);
+            }
+        });
+    }
+
+    abstract T execute(UnitOfWork<T> unitOfWork);
+
+    /**
+     * Called by [EMAIL PROTECTED] #get()} to initialize the attribute value 
when it is [EMAIL PROTECTED] null}. The default implementation
+     * returns [EMAIL PROTECTED] null}.
+     *
+     * @return initial attribute value
+     */
+    protected T initialValue() {
+        return null;
+    }
+}
\ No newline at end of file

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/ApplicationAttribute.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/ApplicationAttribute.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/ApplicationAttribute.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/ApplicationAttribute.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,28 @@
+package org.apache.struts.action2.attribute;
+
+import org.apache.struts.action2.spi.Request;
+import org.apache.struts.action2.spi.ThreadLocalRequest;
+
+/**
+ * A servlet context attribute. Synchronizes on the underlying [EMAIL 
PROTECTED] ServletContext} instance.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public class ApplicationAttribute<T> extends AbstractAttribute<T> {
+
+    /**
+     * Creates a new attribute.
+     *
+     * @param name attribute name
+     */
+    public ApplicationAttribute(String name) {
+        super(name);
+    }
+
+    T execute(UnitOfWork<T> unitOfWork) {
+        Request request = ThreadLocalRequest.get();
+        synchronized (request.getServletContext()) {
+            return unitOfWork.execute(request.getApplicationMap());
+        }
+    }
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/Attribute.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/Attribute.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/Attribute.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/Attribute.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,50 @@
+package org.apache.struts.action2.attribute;
+
+/**
+ * A key/value entry from a given scope. Provides better type safety and 
requires less code than accessing the
+ * [EMAIL PROTECTED] Map} view of a scope directly. For example:
+ *
+ * <pre>
+ *   Attribute&lt;Foo> fooAttribute = new SessionAttribute&lt;Foo>("foo") {
+ *     protected Foo initialValue() {
+ *       return new Foo();
+ *     }
+ *   };
+ *
+ *   public String execute() {
+ *     // get Foo instance from current session.
+ *     Foo foo = fooAttribute.get();
+ *
+ *     foo.doSomething();
+ *     return SUCCESS;
+ *   }
+ * </pre>
+ *
+ * <p>All operations are atomic. Implementations synchronize on underlying 
objects from the servlet API.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface Attribute<T> {
+
+    /**
+     * Gets attribute value.
+     *
+     * @return value
+     */
+    T get();
+
+    /**
+     * Sets attribute value.
+     *
+     * @param t value
+     * @return previous value
+     */
+    T set(T t);
+
+    /**
+     * Removes attribute.
+     *
+     * @return previous value
+     */
+    T remove();
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/RequestAttribute.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/RequestAttribute.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/RequestAttribute.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/RequestAttribute.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,28 @@
+package org.apache.struts.action2.attribute;
+
+import org.apache.struts.action2.spi.Request;
+import org.apache.struts.action2.spi.ThreadLocalRequest;
+
+/**
+ * A request attribute. Synchronizes on the underlying [EMAIL PROTECTED] 
HttpServletRequest} instance.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public class RequestAttribute<T> extends AbstractAttribute<T> {
+
+    /**
+     * Creates a new attribute.
+     *
+     * @param name attribute name
+     */
+    RequestAttribute(String name) {
+        super(name);
+    }
+
+    T execute(UnitOfWork<T> unitOfWork) {
+        Request request = ThreadLocalRequest.get();
+        synchronized (request.getServletRequest()) {
+            return unitOfWork.execute(request.getAttributeMap());
+        }
+    }
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/SessionAttribute.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/SessionAttribute.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/SessionAttribute.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/SessionAttribute.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,28 @@
+package org.apache.struts.action2.attribute;
+
+import org.apache.struts.action2.spi.Request;
+import org.apache.struts.action2.spi.ThreadLocalRequest;
+
+/**
+ * A session attribute. Synchronizes on the underlying [EMAIL PROTECTED] 
HttpSession}.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public class SessionAttribute<T> extends AbstractAttribute<T> {
+
+    /**
+     * Creates a new attribute.
+     *
+     * @param name attribute name
+     */
+    public SessionAttribute(String name) {
+        super(name);
+    }
+
+    T execute(UnitOfWork<T> unitOfWork) {
+        Request request = ThreadLocalRequest.get();
+        synchronized (request.getServletRequest().getSession()) {
+            return unitOfWork.execute(request.getSessionMap());
+        }
+    }
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/UnitOfWork.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/UnitOfWork.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/UnitOfWork.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/UnitOfWork.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,13 @@
+package org.apache.struts.action2.attribute;
+
+import java.util.Map;
+
+/**
+ * Unit of work which should be executed atomically.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+interface UnitOfWork<T> {
+
+    T execute(Map<String, Object> map);
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/package-info.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/package-info.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/package-info.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/attribute/package-info.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,4 @@
+/**
+ * @see Attribute
+ */
+package org.apache.struts.action2.attribute;
\ No newline at end of file

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/package-info.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/package-info.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/package-info.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/package-info.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,4 @@
+/**
+ * Struts Action 2.0 user API.
+ */
+package org.apache.struts.action2;
\ No newline at end of file

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ParameterAware.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ParameterAware.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ParameterAware.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ParameterAware.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,18 @@
+package org.apache.struts.action2.servlet;
+
+import java.util.Map;
+
+/**
+ * Implemented by actions which need direct access to the request parameters.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface ParameterAware {
+
+    /**
+     * Sets parameters.
+     *
+     * @param parameters map of parameter name to parameter values
+     */
+    void setParameters(Map<String, String[]> parameters);
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletRequestAware.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletRequestAware.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletRequestAware.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletRequestAware.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,18 @@
+package org.apache.struts.action2.servlet;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Implemented by actions which need direct access to the servlet request.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface ServletRequestAware {
+
+    /**
+     * Sets the servlet request.
+     *
+     * @param request servlet request.
+     */
+    void setServletRequest(HttpServletRequest request);
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletResponseAware.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletResponseAware.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletResponseAware.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/ServletResponseAware.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,18 @@
+package org.apache.struts.action2.servlet;
+
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Implemented by actions which need direct access to the servlet response.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface ServletResponseAware {
+
+    /**
+     * Sets the servlet response.
+     *
+     * @param response servlet response
+     */
+    void setServletResponse(HttpServletResponse response);
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/package-info.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/package-info.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/package-info.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/servlet/package-info.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,4 @@
+/**
+ * Interfaces for actions which need direct access to the underlying servlet 
API. Use judiciously.
+ */
+package org.apache.struts.action2.servlet;
\ No newline at end of file

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Interceptor.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Interceptor.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Interceptor.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Interceptor.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,16 @@
+package org.apache.struts.action2.spi;
+
+/**
+ * Intercepts an action request.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface Interceptor {
+
+    /**
+     * Intercepts an action request.
+     *
+     * @param request current request
+     */
+    String intercept(Request request) throws Exception;
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Request.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Request.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Request.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Request.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,126 @@
+package org.apache.struts.action2.spi;
+
+import org.apache.struts.action2.Messages;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.ServletContext;
+import java.util.Locale;
+import java.util.Map;
+import java.util.List;
+import java.lang.reflect.Method;
+
+/**
+ * A Struts request. A single request may span multiple actions with action 
chaining.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface Request {
+
+    /**
+     * Gets current action instance.
+     */
+    Object getAction();
+
+    /**
+     * Gets current action method.
+     */
+    Method getMethod();
+
+    /**
+     * Gets current action name.
+     */
+    String getActionName();
+
+    /**
+     * Gets the path for the current action's namespace.
+     */
+    String getNamespacePath();
+
+    /**
+     * Gets the [EMAIL PROTECTED] Result} instance for the current action.
+     *
+     * @return [EMAIL PROTECTED] Result} instance or [EMAIL PROTECTED] null} 
if we don't have a result yet.
+     */
+    Result getResult();
+
+    /**
+     * Adds a result interceptor for the current action. Enables executing 
code before and after a result, executing
+     * an alternate result, etc.
+     */
+    void addResultInterceptor(Result interceptor);
+
+    /**
+     * Gets map of request parameters.
+     */
+    Map<String, String[]> getParameterMap();
+
+    /**
+     * Gets map of request attributes.
+     */
+    Map<String, Object> getAttributeMap();
+
+    /**
+     * Gets map of session attributes.
+     */
+    Map<String, Object> getSessionMap();
+
+    /**
+     * Gets map of application (servlet context) attributes.
+     */
+    Map<String, Object> getApplicationMap();
+
+    /**
+     * Finds cookies with the given name,
+     */
+    List<Cookie> findCookiesForName(String name);
+
+    /**
+     * Gets locale.
+     */
+    Locale getLocale();
+
+    /**
+     * Sets locale. Stores the locale in the session for future requests.
+     */
+    void setLocale(Locale locale);
+
+    /**
+     * Gets messages.
+     */
+    Messages getMessages();
+
+    /**
+     * Gets error messages.
+     */
+    Messages getErrors();
+
+    /**
+     * Gets the servlet request.
+     */
+    HttpServletRequest getServletRequest();
+
+    /**
+     * Gets the servlet response.
+     */
+    HttpServletResponse getServletResponse();
+
+    /**
+     * Gets the servlet context.
+     */
+    ServletContext getServletContext();
+
+    /**
+     * Gets the value stack.
+     */
+    ValueStack getValueStack();
+
+    /**
+     * Invokes the next interceptor or the action method if no more 
interceptors remain.
+     *
+     * @return result name
+     * @throws IllegalStateException if already invoked or called from the 
action
+     */
+    String proceed() throws Exception;
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/RequestAware.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/RequestAware.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/RequestAware.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/RequestAware.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,16 @@
+package org.apache.struts.action2.spi;
+
+/**
+ * Implemented by actions that need access to the current [EMAIL PROTECTED] 
Request}. Use judiciously.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface RequestAware {
+
+    /**
+     * Sets [EMAIL PROTECTED] Request}.
+     *
+     * @param request
+     */
+    void setRequest(Request request);
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Result.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Result.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Result.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/Result.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,16 @@
+package org.apache.struts.action2.spi;
+
+/**
+ * The result of an action request. Struts creates a new [EMAIL PROTECTED] 
Result} instance for each request.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface Result {
+
+    /**
+     * Executes result.
+     *
+     * @param request
+     */
+    void execute(Request request) throws Exception;
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ThreadLocalRequest.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ThreadLocalRequest.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ThreadLocalRequest.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ThreadLocalRequest.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,54 @@
+package org.apache.struts.action2.spi;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Provides a reference to the current [EMAIL PROTECTED] Request} for this 
thread.
+ *
+ * <p>Actions which spawn additional threads are responsible for setting this 
value if access to Struts from the
+ * additional thread is needed.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public final class ThreadLocalRequest {
+
+    static ThreadLocal<Request> threadLocalRequest = new 
ThreadLocal<Request>();
+
+    private ThreadLocalRequest() {}
+
+    /**
+     * Sets [EMAIL PROTECTED] Request} for the current thread and invokes the 
provided [EMAIL PROTECTED] Callable}. Restores previous [EMAIL PROTECTED]
+     * Request} (if any) when finished.
+     *
+     * @param request for current thread
+     * @param callable
+     * @return result of [EMAIL PROTECTED] callable}
+     * @throws Exception from [EMAIL PROTECTED] callable}
+     */
+    public static <T> T setAndCall(Request request, Callable<T> callable) 
throws Exception {
+        Request old = threadLocalRequest.get();
+        try {
+            threadLocalRequest.set(request);
+            return callable.call();
+        } finally {
+            if (old == null)
+                threadLocalRequest.remove();
+            else
+                threadLocalRequest.set(old);
+        }
+    }
+
+    /**
+     * Gets the [EMAIL PROTECTED] Request} for the current thread.
+     *
+     * @return request for current thread
+     * @throws IllegalStateException if no request has been set
+     */
+    public static Request get() {
+        Request request = threadLocalRequest.get();
+        if (request == null) {
+            throw new IllegalStateException(ThreadLocalRequest.class.getName() 
+ " has not been set.");
+        }
+        return request;
+    }
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ValueStack.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ValueStack.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ValueStack.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/ValueStack.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,93 @@
+package org.apache.struts.action2.spi;
+
+/**
+ * A central fixture of the Struts Action framework, the [EMAIL PROTECTED] 
ValueStack} is a stack which contains the actions
+ * which have executed in addition to other objects. Users can get and set 
values on the stack using expressions. The
+ * [EMAIL PROTECTED] ValueStack} will search down the stack starting with the 
most recent objects until it finds an object to
+ * which the expression can apply.
+ *
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public interface ValueStack extends Iterable<Object> {
+
+    /**
+     * Gets the top, most recent object from the stack without changing the 
stack.
+     *
+     * @return the top object
+     */
+    Object peek();
+
+    /**
+     * Removes the top, most recent object from the stack.
+     *
+     * @return the top object
+     */
+    Object pop();
+
+    /**
+     * Pushes an object onto the stack.
+     *
+     * @param o
+     */
+    void push(Object o);
+
+    /**
+     * Creates a shallow copy of this stack.
+     *
+     * @return a new stack which contains the same objects as this one
+     */
+    ValueStack clone();
+
+    /**
+     * Queries the stack. Starts with the top, most recent object. If the 
expression can apply to the object, this
+     * method returns the result of evaluating the expression. If the 
expression does not apply, this method moves
+     * down the stack to the next object and repeats. Returns [EMAIL 
PROTECTED] null} if the expression doesn't apply to any
+     * objects.
+     *
+     * @param expression
+     * @return the evaluation of the expression against the first applicable 
object in the stack
+     */
+    Object get(String expression);
+
+    /**
+     * Queries the stack and converts the result to the specified type. Starts 
with the top, most recent object. If
+     * the expression can apply to the object, this method returns the result 
of evaluating the expression converted
+     * to the specified type. If the expression does not apply, this method 
moves down the stack to the next object
+     * and repeats. Returns [EMAIL PROTECTED] null} if the expression doesn't 
apply to any objects.
+     *
+     * @param expression
+     * @param asType the type to convert the result to
+     * @return the evaluation of the expression against the first applicable 
object in the stack converted to the
+     *  specified type
+     */
+    <T> T get(String expression, Class<T> asType);
+
+    /**
+     * Queries the stack and converts the result to a [EMAIL PROTECTED] 
String}. Starts with the top, most recent object. If the
+     * expression can apply to the object, this method returns the result of 
evaluating the expression converted to a
+     * [EMAIL PROTECTED] String}. If the expression does not apply, this 
method moves down the stack to the next object and
+     * repeats. Returns [EMAIL PROTECTED] null} if the expression doesn't 
apply to any objects.
+     *
+     * @param expression
+     * @return the evaluation of the expression against the first applicable 
object in the stack converted to a [EMAIL PROTECTED]
+     *  String}
+     */
+    String getString(String expression);
+
+    /**
+     * Sets a value on an object from the stack. This method starts at the 
top, most recent object. If the expression
+     * applies to that object, this methods sets the given value on that 
object using the expression and converting
+     * the type as necessary. If the expression does not apply, this method 
moves to the next object and repeats.
+     *
+     * @param expression
+     * @param value
+     */
+    void set(String expression, Object value);
+
+    /**
+     * Returns the number of object on the stack.
+     *
+     * @return size of stack
+     */
+    int size();
+}

Added: 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/package-info.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/package-info.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/package-info.java
 (added)
+++ 
incubator/webwork2/action-api/src/main/java/org/apache/struts/action2/spi/package-info.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,4 @@
+/**
+ * Struts Action 2.0 service provider API.
+ */
+package org.apache.struts.action2.spi;
\ No newline at end of file

Added: 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/AttributeTest.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/AttributeTest.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/AttributeTest.java
 (added)
+++ 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/AttributeTest.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,61 @@
+// Copyright 2006 Google Inc. All Rights Reserved.
+
+package org.apache.struts.action2.attribute;
+
+import junit.framework.TestCase;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public class AttributeTest extends TestCase {
+
+    public void testSetGetRemove() {
+        Map<String, Object> m = new HashMap<String, Object>();
+        Attribute<String> a = new AttributeTest.MockAttribute<String>(m, 
"key");
+
+        assertNull(a.get());
+        assertTrue(m.isEmpty());
+        a.set("foo");
+        assertEquals("foo", a.get());
+        assertFalse(m.isEmpty());
+        a.remove();
+        assertNull(a.get());
+        assertTrue(m.isEmpty());
+    }
+
+    public void testInitialValue() {
+        Map<String, Object> m = new HashMap<String, Object>();
+        Attribute<String> a = new AttributeTest.MockAttribute<String>(m, 
"key") {
+            protected String initialValue() {
+                return "foo";
+            }
+        };
+
+        getAndRemove(a, m);
+        getAndRemove(a, m);
+    }
+
+    void getAndRemove(Attribute<String> a, Map<String, Object> m) {
+        assertEquals("foo", a.get());
+        assertFalse(m.isEmpty());
+        a.remove();
+        assertTrue(m.isEmpty());
+    }
+
+    static class MockAttribute<T> extends AbstractAttribute<T> {
+
+        Map<String, Object> map;
+
+        MockAttribute(Map<String, Object> map, String name) {
+            super(name);
+            this.map = map;
+        }
+
+        T execute(UnitOfWork<T> unitOfWork) {
+            return unitOfWork.execute(map);
+        }
+    }
+}

Added: 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/ReferenceTest.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/ReferenceTest.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/ReferenceTest.java
 (added)
+++ 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/attribute/ReferenceTest.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,59 @@
+package org.apache.struts.action2.attribute;
+
+import junit.framework.TestCase;
+
+import java.util.Map;
+import java.util.HashMap;
+
+/**
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public class ReferenceTest extends TestCase {
+
+    public void testSetGetRemove() {
+        Map<String, Object> m = new HashMap<String, Object>();
+        Attribute<String> a = new MockAttribute<String>(m, "key");
+
+        assertNull(a.get());
+        assertTrue(m.isEmpty());
+        a.set("foo");
+        assertEquals("foo", a.get());
+        assertFalse(m.isEmpty());
+        a.remove();
+        assertNull(a.get());
+        assertTrue(m.isEmpty());
+    }
+
+    public void testInitialValue() {
+        Map<String, Object> m = new HashMap<String, Object>();
+        Attribute<String> a = new MockAttribute<String>(m, "key") {
+            protected String initialValue() {
+                return "foo";
+            }
+        };
+
+        getAndRemove(a, m);
+        getAndRemove(a, m);
+    }
+
+    void getAndRemove(Attribute<String> a, Map<String, Object> m) {
+        assertEquals("foo", a.get());
+        assertFalse(m.isEmpty());
+        a.remove();
+        assertTrue(m.isEmpty());
+    }
+
+    static class MockAttribute<T> extends AbstractAttribute<T> {
+
+        Map<String, Object> map;
+
+        MockAttribute(Map<String, Object> map, String key) {
+            super(key);
+            this.map = map;
+        }
+
+        T execute(UnitOfWork<T> unitOfWork) {
+            return unitOfWork.execute(map);
+        }
+    }
+}

Added: 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/spi/ThreadLocalRequestTest.java
URL: 
http://svn.apache.org/viewcvs/incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/spi/ThreadLocalRequestTest.java?rev=399458&view=auto
==============================================================================
--- 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/spi/ThreadLocalRequestTest.java
 (added)
+++ 
incubator/webwork2/action-api/src/test/java/org/apache/struts/action2/spi/ThreadLocalRequestTest.java
 Wed May  3 15:22:02 2006
@@ -0,0 +1,45 @@
+package org.apache.struts.action2.spi;
+
+import static org.easymock.EasyMock.*;
+import junit.framework.TestCase;
+
+import java.util.concurrent.Callable;
+
+/**
+ * @author [EMAIL PROTECTED] (Bob Lee)
+ */
+public class ThreadLocalRequestTest extends TestCase {
+
+    public void testSetAndCall() throws Exception {
+        final Request r1 = createMock(Request.class);
+        final Request r2 = createMock(Request.class);
+
+        ensureNotSet();
+
+        String result = ThreadLocalRequest.setAndCall(r1, new 
Callable<String>() {
+            public String call() throws Exception {
+                assertSame(r1, ThreadLocalRequest.get());
+                String result = ThreadLocalRequest.setAndCall(r2, new 
Callable<String>() {
+                    public String call() throws Exception {
+                        assertSame(r2, ThreadLocalRequest.get());
+                        return "foo";
+                    }
+                });
+                assertSame(r1, ThreadLocalRequest.get());
+                return result;
+            }
+        });
+
+        ensureNotSet();
+
+        assertEquals("foo", result);
+    }
+
+    private void ensureNotSet() {
+        try {
+           ThreadLocalRequest.get();
+           fail();
+        }
+        catch (IllegalStateException e) { /* ignore */ }
+    }
+}


Reply via email to