commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mben...@apache.org
Subject svn commit: r967275 [1/2] - in /commons/proper/proxy/branches/version-2.0-work: ./ stub/ stub/src/ stub/src/main/ stub/src/main/java/ stub/src/main/java/org/ stub/src/main/java/org/apache/ stub/src/main/java/org/apache/commons/ stub/src/main/java/org/a...
Date Fri, 23 Jul 2010 21:44:42 GMT
Author: mbenson
Date: Fri Jul 23 21:44:40 2010
New Revision: 967275

URL: http://svn.apache.org/viewvc?rev=967275&view=rev
Log:
add stub module

Added:
    commons/proper/proxy/branches/version-2.0-work/stub/   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/pom.xml   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfiguration.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfigurer.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubInterceptor.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubProxyFactory.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/package-info.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractStubProxyFactoryTest.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibAnnotationFactoryTest.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibStubProxyFactoryTest.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/JavassistAnnotationFactoryTest.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/JavassistStubProxyFactoryTest.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/JdkAnnotationFactoryTest.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/JdkStubProxyFactoryTest.java   (with props)
    commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/StubConfigurerTest.java   (with props)
Modified:
    commons/proper/proxy/branches/version-2.0-work/pom.xml

Modified: commons/proper/proxy/branches/version-2.0-work/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/pom.xml?rev=967275&r1=967274&r2=967275&view=diff
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/pom.xml (original)
+++ commons/proper/proxy/branches/version-2.0-work/pom.xml Fri Jul 23 21:44:40 2010
@@ -26,6 +26,7 @@
         <module>jdk</module>
         <module>javassist</module>
         <module>cglib</module>
+        <module>stub</module>
         <module>test</module>
     </modules>
     <parent>

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Jul 23 21:44:40 2010
@@ -0,0 +1,4 @@
+.classpath
+.project
+.settings
+target

Added: commons/proper/proxy/branches/version-2.0-work/stub/pom.xml
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/pom.xml?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/pom.xml (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/pom.xml Fri Jul 23 21:44:40 2010
@@ -0,0 +1,64 @@
+<?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.
+    -->
+
+<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/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>commons-proxy-parent</artifactId>
+        <groupId>org.apache.commons</groupId>
+        <version>2.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>commons-proxy-stub</artifactId>
+    <name>Commons Proxy Stub</name>
+    <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>commons-proxy</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.8.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>commons-proxy-jdk</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>commons-proxy-cglib</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>cglib</groupId>
+            <artifactId>cglib-nodep</artifactId>
+            <version>2.1_3</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>commons-proxy-javassist</artifactId>
+            <version>${project.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/pom.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+import org.apache.commons.proxy2.Invoker;
+import org.apache.commons.proxy2.ProxyFactory;
+import org.apache.commons.proxy2.ProxyUtils;
+
+/**
+ * {@link AnnotationFactory} provides a simplified API over {@link StubProxyFactory}
+ * to stub a Java {@link Annotation}.  Non-stubbed methods will return the values
+ * that would have been returned from a "real" annotation whose methods' values
+ * were unspecified.
+ *
+ * @author Matt Benson
+ */
+public class AnnotationFactory {
+    private static final Invoker ANNOTATION_INVOKER = new Invoker() {
+
+        /** Serialization version */
+        private static final long serialVersionUID = 1L;
+
+        public Object invoke(Object proxy, Method method, Object[] arguments)
+                throws Throwable {
+            Object result = method.getDefaultValue();
+            return result == null && method.getReturnType().isPrimitive() ? ProxyUtils
+                    .nullValue(method.getReturnType())
+                    : result;
+        }
+    };
+
+    private ProxyFactory proxyFactory;
+
+    /**
+     * Create a new AnnotationFactory instance.
+     * @param proxyFactory
+     */
+    public AnnotationFactory(ProxyFactory proxyFactory) {
+        super();
+        this.proxyFactory = proxyFactory;
+    }
+
+    /**
+     * Create an annotation of the type supported by <code>configurer</code>.
+     * @param <A>
+     * @param configurer
+     * @return stubbed annotation proxy
+     */
+    public <A extends Annotation> A create(
+            AnnotationStubConfigurer<A> configurer) {
+        return create(Thread.currentThread().getContextClassLoader(),
+                configurer);
+    }
+
+    /**
+     * Create an annotation of the type supported by <code>configurer</code> in the specified classpath.
+     * @param <A>
+     * @param classLoader
+     * @param configurer
+     * @return stubbed annotation proxy
+     */
+    public <A extends Annotation> A create(ClassLoader classLoader,
+            AnnotationStubConfigurer<A> configurer) {
+        return create(classLoader, configurer.getStubType(), configurer);
+    }
+
+    /**
+     * Create an annotation of <code>annotationType</code> with fully default behavior.
+     * @param <A>
+     * @param classLoader
+     * @param annotationType
+     * @return stubbed annotation proxy
+     */
+    public <A extends Annotation> A create(Class<A> annotationType) {
+        return create(Thread.currentThread().getContextClassLoader(),
+                annotationType, new AnnotationStubConfigurer<A>(annotationType));
+    }
+
+    /**
+     * Create an annotation of <code>annotationType</code> with fully default behavior.
+     * @param <A>
+     * @param classLoader
+     * @param annotationType
+     * @return stubbed annotation proxy
+     */
+    public <A extends Annotation> A create(ClassLoader classLoader,
+            Class<A> annotationType) {
+        return create(classLoader, annotationType,
+                new AnnotationStubConfigurer<A>(annotationType));
+    }
+
+    private <A extends Annotation> A create(ClassLoader classLoader,
+            Class<A> annotationType, AnnotationStubConfigurer<A> configurer) {
+        StubProxyFactory stubFactory = new StubProxyFactory(proxyFactory,
+                configurer);
+        @SuppressWarnings("unchecked")
+        final A result = (A) stubFactory.createInvokerProxy(classLoader, ANNOTATION_INVOKER,
+                annotationType);
+        return result;
+    }
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import java.lang.annotation.Annotation;
+
+/**
+ * {@link StubConfigurer} for annotation types:  handles <code>{@link Annotation#annotationType()}</code>.
+ */
+public class AnnotationStubConfigurer<T extends Annotation> extends
+        StubConfigurer<T> {
+
+    /**
+     * Create a new AnnotationStubConfigurer instance.
+     */
+    public AnnotationStubConfigurer() {
+        super();
+    }
+
+    /**
+     * Create a new AnnotationStubConfigurer instance.
+     */
+    public AnnotationStubConfigurer(Class<T> stubType) {
+        super(stubType);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    protected final void configure(T stub) {
+        when(stub.annotationType()).thenReturn(getStubType());
+        configureAnnotation(stub);
+    };
+
+    /**
+     * Configure stub as usual. Default implementation is a noop.
+     * @param stub
+     */
+    protected void configureAnnotation(T stub) {
+    }
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationStubConfigurer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfiguration.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfiguration.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfiguration.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfiguration.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,347 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import org.apache.commons.proxy2.ObjectProvider;
+
+/**
+ * Fluent stub configuration interface inspired by Mockito stubbing mechanisms.
+ * This interface declares all the methods necessary to, in particular, allow
+ * varargs to be used to specify return values for any array type.
+ */
+public interface StubConfiguration {
+
+    /**
+     * Permits the setup of thrown {@link Throwable}s when stubbing.
+     */
+    interface MayThrow {
+        /**
+         * Throw something.
+         * @param t
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenThrow(Throwable t);
+
+        /**
+         * Throw something, deferring construction.
+         * @param throwableProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenThrow(
+                ObjectProvider<? extends Throwable> throwableProvider);
+    }
+
+    /**
+     * Intermediate result of a generic when(...) call
+     *
+     * @param <RT>
+     */
+    interface When<RT> extends MayThrow {
+        /**
+         * Declare return value.
+         * @param result
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(RT result);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(
+                ObjectProvider<? extends RT> objectProvider);
+
+    }
+
+    /**
+     * "when(...)"
+     * @param <RT>
+     * @param call
+     * @return {@link When}
+     */
+    <RT> When<RT> when(RT call);
+
+    /**
+     * Intermediate result of a when(boolean[]) call
+     */
+    interface WhenBooleanArray extends MayThrow {
+        /**
+         * Declare return value.
+         * @param b
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(boolean... b);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<boolean[]> objectProvider);
+    }
+
+    /**
+     * "when(boolean[])"
+     * @param call
+     * @return {@link WhenBooleanArray}
+     */
+    WhenBooleanArray when(boolean[] call);
+
+    /**
+     * Intermediate result of a when(byte[]) call
+     */
+    interface WhenByteArray extends MayThrow {
+        /**
+         * Declare return value.
+         * @param b
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(byte... b);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<byte[]> objectProvider);
+    }
+
+    /**
+     * "when(byte[])"
+     * @param call
+     * @return {@link WhenByteArray}
+     */
+    WhenByteArray when(byte[] call);
+
+    /**
+     * Intermediate result of a when(short[]) call
+     */
+    interface WhenShortArray extends MayThrow {
+        /**
+         * Declare return value
+         * @param s
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(short... s);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<short[]> objectProvider);
+    }
+
+    /**
+     * "when(short[])"
+     * @param call
+     * @return {@link WhenShortArray}
+     */
+    WhenShortArray when(short[] call);
+
+    /**
+     * Intermediate result of a when(int[]) call
+     *
+     * @param
+     */
+    interface WhenIntArray extends MayThrow {
+        /**
+         * Declare return value
+         * @param i
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(int... i);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<int[]> objectProvider);
+    }
+
+    /**
+     * "when(int[])"
+     * @param call
+     * @return {@link WhenIntArray}
+     */
+    WhenIntArray when(int[] call);
+
+    /**
+     * Intermediate result of a when(char[]) call
+     */
+    interface WhenCharArray extends MayThrow {
+        /**
+         * Declare return value
+         * @param c
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(char... c);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<char[]> objectProvider);
+    }
+
+    /**
+     * "when(char[])"
+     * @param call
+     * @return {@link WhenCharArray}
+     */
+    WhenCharArray when(char[] call);
+
+    /**
+     * Intermediate result of a when(long[]) call
+     */
+    interface WhenLongArray extends MayThrow {
+        /**
+         * Declare return value
+         * @param l
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(long... l);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<long[]> objectProvider);
+    }
+
+    /**
+     * "when(long[])"
+     * @param call
+     * @return {@link WhenLongArray}
+     */
+    WhenLongArray when(long[] call);
+
+    /**
+     * Intermediate result of a when(float[]) call
+     */
+    interface WhenFloatArray extends MayThrow {
+        /**
+         * Declare return value
+         * @param f
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(float... f);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<float[]> objectProvider);
+    }
+
+    /**
+     * "when(float[])"
+     * @param call
+     * @return {@link WhenFloatArray}
+     */
+    WhenFloatArray when(float[] call);
+
+    /**
+     * Intermediate result of a when(double[]) call
+     */
+    interface WhenDoubleArray extends MayThrow {
+        /**
+         * Declare return value
+         * @param d
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(double... d);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<double[]> objectProvider);
+    }
+
+    /**
+     * "when(double[])"
+     * @param call
+     * @return {@link WhenDoubleArray}
+     */
+    WhenDoubleArray when(double[] call);
+
+    /**
+     * Intermediate result of a when(Object[]) call
+     *
+     * @param <C>
+     */
+    interface WhenObjectArray<C> extends MayThrow {
+        /**
+         * Declare return value
+         * @param c
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(C... c);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<Object[]> objectProvider);
+    }
+
+    /**
+     * "when(Object[])"
+     * @param call
+     * @return {@link WhenObjectArray}
+     */
+    <C> WhenObjectArray<C> when(C[] call);
+
+    /**
+     * Intermediate result of a when(Class) call.
+     * Provided because it is such a common case to have a mismatch between a
+     * declared Class<?> return type and the bound parameter of a class literal.
+     */
+    interface WhenClass extends MayThrow {
+        /**
+         * Declare return value
+         * @param c
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenReturn(Class<?> c);
+
+        /**
+         * Defer return value.
+         * @param objectProvider
+         * @return the original {@link StubConfiguration} for chaining
+         */
+        StubConfiguration thenAnswer(ObjectProvider<Class<?>> objectProvider);
+    }
+
+    /**
+     * "when(Class<?>)" (because it is such a common case to have a mismatch between a
+     * declared Class<?> return type and the bound parameter of a class literal)
+     * @param call
+     * @return {@link WhenClass}
+     */
+    WhenClass when(Class<?> call);
+
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfiguration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfigurer.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfigurer.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfigurer.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfigurer.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,553 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+
+import org.apache.commons.proxy2.ObjectProvider;
+import org.apache.commons.proxy2.provider.ConstantProvider;
+
+/**
+ * Configuration mechanism for a stub.  Implements {@link StubConfiguration} for maximum fluency.
+ * A {@link StubConfigurer} needs to know the type of stub object to which it applies.
+ * Any useful runtime subclass should have the type variable non-generically
+ * declared (else its {@link #configure(Object)} implementation wouldn't be worth much),
+ * so usually the no-arg constructor can be used.  Example:
+ * <code><pre>
+ * new StubConfigurer&lt;java.util.Iterable&lt;String&gt;&gt;() {
+ *     protected void configure(Iterable&lt;String&gt; stub) {
+ *         when(stub.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator());
+ *     }
+ * }
+ * </pre></code>
+ *
+ * @param <T>
+ * @author Matt Benson
+ */
+//TODO add argument matcher capturing
+public abstract class StubConfigurer<T> implements StubConfiguration {
+    private Class<T> stubType;
+
+    /** Stateful reference to the StubInterceptor currently being configured */
+    private StubInterceptor stubInterceptor;
+
+    /**
+     * Create a new StubConfigurer instance.  This constructor should only be called
+     * by classes that explicitly assign the T type parameter in the class definition.
+     * This should include basically any runtime-usable subclass.
+     */
+    protected StubConfigurer() {
+        this(null);
+    }
+
+    /**
+     * Create a new StubConfigurer instance.
+     * @param stubType
+     */
+    protected StubConfigurer(Class<T> stubType) {
+        super();
+        if (stubType != null) {
+            this.stubType = stubType;
+            return;
+        }
+        //TODO replace with lang3 TypeUtils calls
+        @SuppressWarnings("unchecked")
+        final Class<T> resolvedVariable = (Class<T>) getRawType(getClass(),
+                StubConfigurer.class.getTypeParameters()[0]);
+        if (resolvedVariable == null) {
+            throw new IllegalArgumentException(
+                    "stubType was not specified and could not be calculated for "
+                            + getClass());
+        }
+        this.stubType = resolvedVariable;
+    }
+
+    /**
+     * Get the stubType.
+     * @return Class<T>
+     */
+    public Class<T> getStubType() {
+        return stubType;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <RT> org.apache.commons.proxy2.stub.StubConfiguration.When<RT> when(
+            RT call) {
+        return new When<RT>() {
+
+            public StubConfiguration thenReturn(RT result) {
+                requireStubInterceptor().addAnswer(result);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<? extends RT> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenBooleanArray when(
+            boolean[] call) {
+        return new WhenBooleanArray() {
+
+            public StubConfiguration thenReturn(boolean... b) {
+                requireStubInterceptor().addAnswer(b);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<boolean[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenByteArray when(
+            byte[] call) {
+        return new WhenByteArray() {
+
+            public StubConfiguration thenReturn(byte... b) {
+                requireStubInterceptor().addAnswer(b);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<byte[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenShortArray when(
+            short[] call) {
+        return new WhenShortArray() {
+
+            public StubConfiguration thenReturn(short... s) {
+                requireStubInterceptor().addAnswer(s);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<short[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenIntArray when(
+            int[] call) {
+        return new WhenIntArray() {
+
+            public StubConfiguration thenReturn(int... i) {
+                requireStubInterceptor().addAnswer(i);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<int[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenCharArray when(
+            char[] call) {
+        return new WhenCharArray() {
+
+            public StubConfiguration thenReturn(char... c) {
+                requireStubInterceptor().addAnswer(c);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<char[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenLongArray when(
+            long[] call) {
+        return new WhenLongArray() {
+
+            public StubConfiguration thenReturn(long... l) {
+                requireStubInterceptor().addAnswer(l);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<long[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenFloatArray when(
+            float[] call) {
+        return new WhenFloatArray() {
+
+            public StubConfiguration thenReturn(float... f) {
+                requireStubInterceptor().addAnswer(f);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<float[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenDoubleArray when(
+            double[] call) {
+        return new WhenDoubleArray() {
+
+            public StubConfiguration thenReturn(double... d) {
+                requireStubInterceptor().addAnswer(d);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<double[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <C> org.apache.commons.proxy2.stub.StubConfiguration.WhenObjectArray<C> when(
+            C[] call) {
+        return new WhenObjectArray<C>() {
+
+            public StubConfiguration thenReturn(C... c) {
+                requireStubInterceptor().addAnswer(c);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<Object[]> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public org.apache.commons.proxy2.stub.StubConfiguration.WhenClass when(
+            Class<?> call) {
+        return new WhenClass() {
+
+            public StubConfiguration thenReturn(Class<?> c) {
+                requireStubInterceptor().addAnswer(c);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenAnswer(
+                    ObjectProvider<Class<?>> objectProvider) {
+                requireStubInterceptor().addAnswer(objectProvider);
+                return StubConfigurer.this;
+            }
+
+            public StubConfiguration thenThrow(Throwable t) {
+                return thenThrow(new ConstantProvider<Throwable>(t));
+            }
+
+            public StubConfiguration thenThrow(
+                    ObjectProvider<? extends Throwable> throwableProvider) {
+                requireStubInterceptor().addThrow(throwableProvider);
+                return StubConfigurer.this;
+            }
+        };
+    }
+
+    /**
+     * Apply thyself against the specified stub interceptor.
+     * @param stubInterceptor
+     */
+    final void configure(StubInterceptor stubInterceptor, T stub) {
+        if (stubInterceptor == null) {
+            throw new IllegalArgumentException(
+                    "Cannot configure null StubInterceptor");
+        }
+        synchronized (this) {
+            this.stubInterceptor = stubInterceptor;
+            try {
+                configure(stub);
+            } finally {
+                this.stubInterceptor = null;
+            }
+        }
+    }
+
+    /**
+     * Specify the behavior of <code>stub</code> via the {@link StubConfiguration} interface.
+     * @param stub
+     */
+    protected abstract void configure(T stub);
+
+    private synchronized StubInterceptor requireStubInterceptor() {
+        if (stubInterceptor == null) {
+            throw new IllegalStateException(
+                    "no StubInterceptor currently in use");
+        }
+        return stubInterceptor;
+    }
+
+    /**
+     * Get the raw type of a Java type, given its context. Primarily for use
+     * with {@link TypeVariable}s and {@link GenericArrayType}s, or when you do
+     * not know the runtime type of <code>type</code>: if you know you have a
+     * {@link Class} instance, it is already raw; if you know you have a
+     * {@link ParameterizedType}, its raw type is only a method call away.
+     * @param enclosingType context
+     * @param type to read
+     * @return Class<?>
+     */
+    // adapted from unreleased commons-lang 3.0 trunk r924407
+    private static Class<?> getRawType(Type enclosingType, Type type) {
+        if (type instanceof Class<?>) {
+            // it is raw, no problem
+            return (Class<?>) type;
+        }
+        if (type instanceof ParameterizedType) {
+            // simple enough to get the raw type of a ParameterizedType
+            return (Class<?>) ((ParameterizedType) type).getRawType();
+        }
+        if (enclosingType != null) {
+            if (type instanceof TypeVariable<?>) {
+                // resolve the variable against the enclosing type, hope for the best (casting)
+                Type resolved = resolveVariable(enclosingType,
+                        (TypeVariable<?>) type);
+                //this is the only change from commons-lang r924407
+                return getRawType(enclosingType, resolved);
+            }
+            if (type instanceof GenericArrayType) {
+                validateNotNull(enclosingType,
+                        "Cannot get raw type of GenericArrayType without enclosing type");
+                // not included in original code, but not too difficult:  just have to get raw component type...
+                Class<?> rawComponentType = getRawType(enclosingType,
+                        ((GenericArrayType) type).getGenericComponentType());
+                // ...and know how to reflectively create array types, uncommon but not unheard of:
+                return Array.newInstance(rawComponentType, 0).getClass();
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Handle recursion and falling back up the graph.
+     * @param enclosingType
+     * @param typeVar
+     * @return Type resolved
+     */
+    // adapted from unreleased commons-lang 3.0 trunk r924407
+    private static Type resolveVariable(Type enclosingType,
+            TypeVariable<?> typeVar) {
+        if (enclosingType instanceof ParameterizedType) {
+            ParameterizedType parameterizedEnclosingType = (ParameterizedType) enclosingType;
+            TypeVariable<?>[] typeVariables = getRawType(null,
+                    parameterizedEnclosingType.getRawType())
+                    .getTypeParameters();
+            //look for the matching variable:
+            for (int i = 0; i < typeVariables.length; i++) {
+                if (typeVariables[i].equals(typeVar)) {
+                    return parameterizedEnclosingType.getActualTypeArguments()[i];
+                }
+            }
+            //otherwise recurse to try against raw class
+            Type result = resolveVariable(parameterizedEnclosingType
+                    .getRawType(), typeVar);
+            //unroll variable if returned
+            if (result instanceof TypeVariable<?>) {
+                return resolveVariable(enclosingType, (TypeVariable<?>) result);
+            }
+            return result;
+        }
+        if (enclosingType instanceof Class<?>) {
+            Class<?> enclosingClass = (Class<?>) enclosingType;
+            Type result = null;
+            Type genericSuperclass = enclosingClass.getGenericSuperclass();
+            if (genericSuperclass != null
+                    && !Object.class.equals(genericSuperclass)) {
+                result = resolveVariable(genericSuperclass, typeVar);
+            }
+            if (result == null) {
+                for (Type genericInterface : enclosingClass
+                        .getGenericInterfaces()) {
+                    result = resolveVariable(genericInterface, typeVar);
+                    if (result != null) {
+                        break;
+                    }
+                }
+            }
+            return result;
+        }
+        return null;
+    }
+
+    private static void validateNotNull(Object o, String message) {
+        if (o == null) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubConfigurer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubInterceptor.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubInterceptor.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubInterceptor.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubInterceptor.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Deque;
+
+import org.apache.commons.proxy2.Interceptor;
+import org.apache.commons.proxy2.Invocation;
+import org.apache.commons.proxy2.ObjectProvider;
+import org.apache.commons.proxy2.ProxyUtils;
+import org.apache.commons.proxy2.invoker.RecordedInvocation;
+
+/**
+ * StubInterceptor collects, then replays on demand, the stubbing information.
+ *
+ * @author Matt Benson
+ */
+/*
+ * Handling with an interceptor means we get the parent ProxyFactory's implementation of an Invocation
+ */
+abstract class StubInterceptor implements Interceptor {
+    /** Serialization version */
+    private static final long serialVersionUID = 1L;
+
+    private interface InvocationMatcher {
+        boolean matches(Invocation invocation);
+    }
+
+    private static abstract class Result {
+        InvocationMatcher invocationMatcher;
+
+        Result(InvocationMatcher invocationMatcher) {
+            super();
+            this.invocationMatcher = invocationMatcher;
+        }
+
+        abstract Object getResult() throws Throwable;
+    }
+
+    private static class Answer extends Result {
+        private Object answer;
+
+        Answer(InvocationMatcher invocationMatcher, Object answer) {
+            super(invocationMatcher);
+            this.answer = answer;
+        }
+
+        /**
+         * Get the answer.
+         * @return Object
+         */
+        public Object getResult() throws Throwable {
+            return answer instanceof ObjectProvider<?> ? ((ObjectProvider<?>) answer)
+                    .getObject()
+                    : answer;
+        }
+    }
+
+    private static class Throw extends Result {
+        private ObjectProvider<? extends Throwable> throwableProvider;
+
+        /**
+         * Create a new Throw instance.
+         * @param invocationMatcher
+         */
+        Throw(InvocationMatcher invocationMatcher,
+                ObjectProvider<? extends Throwable> throwableProvider) {
+            super(invocationMatcher);
+            this.throwableProvider = throwableProvider;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        Object getResult() throws Throwable {
+            throw throwableProvider.getObject();
+        }
+    }
+
+    private boolean complete;
+    private RecordedInvocation currentInvocation;
+    private Deque<Result> resultStack = new ArrayDeque<Result>();
+
+    /**
+     * Create a new StubInterceptor instance.
+     */
+    StubInterceptor() {
+        super();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public Object intercept(Invocation invocation) throws Throwable {
+        if (complete) {
+            for (Result result : resultStack) {
+                if (result.invocationMatcher.matches(invocation)) {
+                    return result.getResult();
+                }
+            }
+            return interceptFallback(invocation);
+        }
+        RecordedInvocation incoming = new RecordedInvocation(invocation
+                .getMethod(), invocation.getArguments());
+        synchronized (this) {
+            if (currentInvocation == null) {
+                currentInvocation = incoming;
+            } else {
+                throw new IllegalStateException("Called " + incoming
+                        + " while stubbing of " + currentInvocation
+                        + " is incomplete.");
+            }
+        }
+        return ProxyUtils.nullValue(invocation.getMethod().getReturnType());
+    }
+
+    void addAnswer(Object o) {
+        resultStack.push(new Answer(currentMatcher(), o));
+    }
+
+    void addThrow(ObjectProvider<? extends Throwable> throwableProvider) {
+        resultStack.push(new Throw(currentMatcher(), throwableProvider));
+    }
+
+    private synchronized InvocationMatcher currentMatcher() {
+        if (complete) {
+            throw new IllegalStateException(
+                    "Answers not permitted; stubbing already marked as complete.");
+        }
+        if (currentInvocation == null) {
+            throw new IllegalStateException(
+                    "No ongoing stubbing found for any method");
+        }
+        try {
+            final RecordedInvocation recordedInvocation = currentInvocation;
+            return new InvocationMatcher() {
+
+                public boolean matches(Invocation invocation) {
+                    return invocation.getMethod().getName().equals(
+                            recordedInvocation.getInvokedMethod().getName())
+                            && Arrays.equals(invocation.getArguments(),
+                                    recordedInvocation.getArguments());
+                }
+
+            };
+        } finally {
+            currentInvocation = null;
+        }
+    }
+
+    void complete() {
+        this.complete = true;
+    }
+
+    /**
+     * Fallback behavior
+     * @param invocation
+     * @return result
+     * @throws Throwable
+     */
+    protected abstract Object interceptFallback(Invocation invocation)
+            throws Throwable;
+}
\ No newline at end of file

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubProxyFactory.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubProxyFactory.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubProxyFactory.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubProxyFactory.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,227 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import org.apache.commons.proxy2.Interceptor;
+import org.apache.commons.proxy2.Invocation;
+import org.apache.commons.proxy2.Invoker;
+import org.apache.commons.proxy2.ObjectProvider;
+import org.apache.commons.proxy2.ProxyFactory;
+import org.apache.commons.proxy2.ProxyUtils;
+
+/**
+ * {@link ProxyFactory} that stubs proxies' behavior using {@link StubConfigurer}s.
+ * The {@link ObjectProvider}|{@link Interceptor}|{@link Invoker} specified per the
+ * {@link ProxyFactory} contract provides the default behavior for non-stubbed method calls.
+ *
+ * @author Matt Benson
+ */
+public class StubProxyFactory implements ProxyFactory {
+    private ProxyFactory parent;
+    private StubConfigurer<?>[] stubConfigurers;
+
+    /**
+     * Create a new StubProxyFactory instance.
+     * @param stubConfigurers for each proxy created by <code>parent</code>, any {@link StubConfigurer}s
+     *  whose <code>stubType</code> is assignable from the proxy will be invoked to stub behavior.
+     */
+    public StubProxyFactory(StubConfigurer<?>... stubConfigurers) {
+        this(ProxyUtils.proxyFactory(), stubConfigurers);
+    }
+
+    /**
+     * Create a new StubProxyFactory instance.
+     * @param parent
+     * @param stubConfigurers for each proxy created by <code>parent</code>, any {@link StubConfigurer}s
+     *  whose <code>stubType</code> is assignable from the proxy will be invoked to stub behavior.
+     */
+    public StubProxyFactory(ProxyFactory parent,
+            StubConfigurer<?>... stubConfigurers) {
+        super();
+        if (parent == null) {
+            throw new IllegalArgumentException(
+                    "no parent ProxyFactory specified");
+        }
+        this.parent = parent;
+        if (stubConfigurers == null || stubConfigurers.length == 0) {
+            throw new IllegalArgumentException("no StubConfigurers specified");
+        }
+        this.stubConfigurers = stubConfigurers;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public boolean canProxy(Class<?>... proxyClasses) {
+        return parent.canProxy(proxyClasses);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T> T createDelegatorProxy(ObjectProvider<?> delegateProvider,
+            Class<?>... proxyClasses) {
+        @SuppressWarnings("unchecked")
+        final T result = (T) create(null, new DelegatorInterceptor(
+                delegateProvider), proxyClasses);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T> T createDelegatorProxy(ClassLoader classLoader,
+            final ObjectProvider<?> delegateProvider, Class<?>... proxyClasses) {
+        @SuppressWarnings("unchecked")
+        final T result = (T) create(classLoader, null,
+                new DelegatorInterceptor(delegateProvider), proxyClasses);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T> T createInterceptorProxy(Object target, Interceptor interceptor,
+            Class<?>... proxyClasses) {
+        @SuppressWarnings("unchecked")
+        final T result = (T) create(target, new InterceptorInterceptor(
+                interceptor), proxyClasses);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T> T createInterceptorProxy(ClassLoader classLoader, Object target,
+            final Interceptor interceptor, Class<?>... proxyClasses) {
+        @SuppressWarnings("unchecked")
+        final T result = (T) create(classLoader, target,
+                new InterceptorInterceptor(interceptor), proxyClasses);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T> T createInvokerProxy(Invoker invoker, Class<?>... proxyClasses) {
+        @SuppressWarnings("unchecked")
+        final T result = (T) create(null, new InvokerInterceptor(invoker),
+                proxyClasses);
+        return result;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public <T> T createInvokerProxy(ClassLoader classLoader,
+            final Invoker invoker, Class<?>... proxyClasses) {
+        @SuppressWarnings("unchecked")
+        final T result = (T) create(classLoader, null, new InvokerInterceptor(
+                invoker), proxyClasses);
+        return result;
+    }
+
+    private <T> T create(Object target, StubInterceptor stubInterceptor,
+            Class<?>... proxyClasses) {
+        @SuppressWarnings("unchecked")
+        final T result = (T) parent.createInterceptorProxy(target,
+                stubInterceptor, proxyClasses);
+        configure(result, stubInterceptor);
+        return result;
+    }
+
+    private <T> T create(ClassLoader classLoader, Object target,
+            StubInterceptor stubInterceptor, Class<?>... proxyClasses) {
+        @SuppressWarnings("unchecked")
+        final T result = (T) parent.createInterceptorProxy(classLoader, target,
+                stubInterceptor, proxyClasses);
+        configure(result, stubInterceptor);
+        return result;
+    }
+
+    private <T> void configure(T stub, StubInterceptor stubInterceptor) {
+        for (StubConfigurer<?> stubConfigurer : stubConfigurers) {
+            if (stubConfigurer.getStubType().isInstance(stub)) {
+                @SuppressWarnings("unchecked")
+                final StubConfigurer<T> typedStubConfigurer = (StubConfigurer<T>) stubConfigurer;
+                typedStubConfigurer.configure(stubInterceptor, stub);
+            }
+        }
+        stubInterceptor.complete();
+
+    }
+
+    private static class DelegatorInterceptor extends StubInterceptor {
+        /** Serialization version */
+        private static final long serialVersionUID = 1L;
+
+        private ObjectProvider<?> delegateProvider;
+
+        private DelegatorInterceptor(ObjectProvider<?> delegateProvider) {
+            super();
+            this.delegateProvider = delegateProvider;
+        }
+
+        @Override
+        protected Object interceptFallback(Invocation invocation)
+                throws Throwable {
+            return invocation.getMethod().invoke(delegateProvider.getObject(),
+                    invocation.getArguments());
+        }
+    }
+
+    private static class InterceptorInterceptor extends StubInterceptor {
+        /** Serialization version */
+        private static final long serialVersionUID = 1L;
+
+        private Interceptor interceptor;
+
+        private InterceptorInterceptor(Interceptor interceptor) {
+            super();
+            this.interceptor = interceptor;
+        }
+
+        @Override
+        protected Object interceptFallback(Invocation invocation)
+                throws Throwable {
+            return interceptor.intercept(invocation);
+        }
+    }
+
+    private static class InvokerInterceptor extends StubInterceptor {
+        /** Serialization version */
+        private static final long serialVersionUID = 1L;
+
+        private Invoker invoker;
+
+        private InvokerInterceptor(Invoker invoker) {
+            super();
+            this.invoker = invoker;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        protected Object interceptFallback(Invocation invocation)
+                throws Throwable {
+            return invoker.invoke(invocation.getProxy(),
+                    invocation.getMethod(), invocation.getArguments());
+        }
+    }
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/StubProxyFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/package-info.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/package-info.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/package-info.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/package-info.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,21 @@
+/*
+ * 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.
+ */
+
+/**
+ * Contains mechanisms for stubbing behavior on {@link org.apache.commons.proxy2.ProxyFactory}-generated proxy objects.
+ */
+package org.apache.commons.proxy2.stub;
\ No newline at end of file

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/main/java/org/apache/commons/proxy2/stub/package-info.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import static org.junit.Assert.*;
+
+import org.apache.commons.proxy2.ProxyFactory;
+import org.apache.commons.proxy2.stub.AnnotationFactory;
+import org.apache.commons.proxy2.stub.AnnotationStubConfigurer;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test {@link AnnotationFactory}.
+ */
+public abstract class AbstractAnnotationFactoryTest {
+    private AnnotationFactory annotationFactory;
+
+    @Before
+    public void setUp() {
+        annotationFactory = new AnnotationFactory(createProxyFactory());
+    }
+
+    protected abstract ProxyFactory createProxyFactory();
+
+    @Test
+    public void testDefaultAnnotation() {
+        CustomAnnotation customAnnotation = annotationFactory
+                .create(CustomAnnotation.class);
+        assertEquals(CustomAnnotation.class, customAnnotation.annotationType());
+        assertEquals("", customAnnotation.annString());
+        assertEquals(0, customAnnotation.finiteValues().length);
+        assertNull(customAnnotation.someType());
+
+    }
+
+    @Test
+    public void testStubbedAnnotation() {
+        CustomAnnotation customAnnotation = annotationFactory
+                .create(new AnnotationStubConfigurer<CustomAnnotation>() {
+
+                    @Override
+                    protected void configureAnnotation(CustomAnnotation stub) {
+                        when(stub.someType()).thenReturn(Object.class)
+                        .when(stub.finiteValues()).thenReturn(FiniteValues.ONE, FiniteValues.THREE)
+                        .when(stub.annString()).thenReturn("hey");
+                    }
+
+                });
+        assertEquals(CustomAnnotation.class, customAnnotation.annotationType());
+        assertEquals("hey", customAnnotation.annString());
+        assertArrayEquals(new FiniteValues[] { FiniteValues.ONE,
+                FiniteValues.THREE }, customAnnotation.finiteValues());
+        assertEquals(Object.class, customAnnotation.someType());
+    }
+
+    public @interface CustomAnnotation {
+        String annString() default "";
+
+        FiniteValues[] finiteValues() default {};
+
+        Class<?> someType();
+    }
+
+    public enum FiniteValues {
+        ONE, TWO, THREE;
+    }
+
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractAnnotationFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractStubProxyFactoryTest.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractStubProxyFactoryTest.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractStubProxyFactoryTest.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractStubProxyFactoryTest.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,373 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import static org.junit.Assert.*;
+import static org.junit.Assume.assumeTrue;
+
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.Iterator;
+
+import org.apache.commons.proxy2.Interceptor;
+import org.apache.commons.proxy2.Invocation;
+import org.apache.commons.proxy2.Invoker;
+import org.apache.commons.proxy2.ObjectProvider;
+import org.apache.commons.proxy2.ProxyFactory;
+import org.apache.commons.proxy2.invoker.NullInvoker;
+import org.apache.commons.proxy2.provider.BeanProvider;
+import org.apache.commons.proxy2.stub.StubConfigurer;
+import org.apache.commons.proxy2.stub.StubProxyFactory;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Test {@link StubProxyFactory}.
+ */
+public abstract class AbstractStubProxyFactoryTest {
+    private static final StubConfigurer<Foo> FOO_CONFIGURER = new StubConfigurer<Foo>() {
+
+        @Override
+        protected void configure(Foo stub) {
+            when(stub.fooString()).thenReturn("foo").when(stub.fooInt())
+                    .thenReturn(0).when(stub.fooInteger()).thenReturn(100);
+        }
+    };
+
+    private static final StubConfigurer<Bar> BAR_CONFIGURER = new StubConfigurer<Bar>() {
+
+        @Override
+        protected void configure(Bar stub) {
+            when(stub.barString()).thenReturn("bar").when(stub.barLong())
+                    .thenReturn(0L).when(stub.barLongObject()).thenReturn(100L);
+        }
+    };
+
+    private static final StubConfigurer<CollideFoo> COLLIDE_FOO_CONFIGURER = new StubConfigurer<CollideFoo>() {
+
+        @Override
+        protected void configure(CollideFoo stub) {
+            when(stub.fooString()).thenReturn("collideFoo");
+        }
+    };
+
+    private static final StubConfigurer<ArrayValues> ARRAY_VALUES_CONFIGURER = new StubConfigurer<ArrayValues>() {
+
+        @Override
+        protected void configure(ArrayValues stub) {
+            when(stub.booleanArray()).thenReturn(true, false)
+            .when(stub.byteArray()).thenReturn((byte) 0, (byte) 1, (byte) 2)
+            .when(stub.shortArray()).thenReturn(new short[] { 3, 4, 5 })
+            .when(stub.intArray()).thenReturn(6, 7, 8)
+            .when(stub.charArray()).thenReturn('a', 'b', 'c')
+            .when(stub.longArray()).thenReturn(9L, 10L, 11L)
+            .when(stub.floatArray()).thenReturn(0.0f, 0.1f, 0.2f)
+            .when(stub.doubleArray()).thenReturn(0.0, 0.1, 0.2)
+            .when(stub.stringArray()).thenReturn("foo", "bar", "baz")
+            .when(stub.objectArray()).thenReturn("foo", 1, null);
+        }
+    };
+
+    private static final StubConfigurer<CurrentTime> CURRENT_TIME_CONFIGURER = new StubConfigurer<CurrentTime>() {
+
+        @Override
+        protected void configure(CurrentTime stub) {
+            when(stub.currentTimeMillis()).thenAnswer(
+                    new ObjectProvider<Long>() {
+
+                        public Long getObject() {
+                            return System.currentTimeMillis();
+                        }
+                    });
+        }
+
+    };
+
+    private static final StubConfigurer<AcceptArguments> ACCEPT_ARGUMENTS_CONFIGURER = new StubConfigurer<AcceptArguments>() {
+
+        @Override
+        protected void configure(AcceptArguments stub) {
+            when(stub.respondTo("foo")).thenReturn("who")
+            .when(stub.respondTo("bar")).thenReturn("far")
+            .when(stub.respondTo("baz")).thenReturn("spazz");
+        }
+    };
+
+    private StubProxyFactory proxyFactory;
+
+    @Before
+    public void setUp() {
+        proxyFactory = new StubProxyFactory(createParent(), FOO_CONFIGURER,
+                BAR_CONFIGURER, COLLIDE_FOO_CONFIGURER,
+                ARRAY_VALUES_CONFIGURER, CURRENT_TIME_CONFIGURER, ACCEPT_ARGUMENTS_CONFIGURER);
+    }
+
+    protected abstract ProxyFactory createParent();
+
+    @Test
+    public void testBasic() {
+        Foo foo = proxyFactory.createInvokerProxy(NullInvoker.INSTANCE, Foo.class);
+        assertEquals("foo", foo.fooString());
+        assertEquals(0, foo.fooInt());
+        assertEquals(100, foo.fooInteger().intValue());
+        Bar bar = proxyFactory.createInvokerProxy(NullInvoker.INSTANCE, Bar.class);
+        assertEquals("bar", bar.barString());
+        assertEquals(0L, bar.barLong());
+        assertEquals(100L, bar.barLongObject().longValue());
+    }
+
+    @Test
+    public void testCombined() {
+        Foo foobar = proxyFactory.createInvokerProxy(NullInvoker.INSTANCE, Foo.class, Bar.class);
+        assertEquals("foo", foobar.fooString());
+        assertEquals(0, foobar.fooInt());
+        assertEquals(100, foobar.fooInteger().intValue());
+        assertEquals("bar", ((Bar) foobar).barString());
+        assertEquals(0L, ((Bar) foobar).barLong());
+        assertEquals(100L, ((Bar) foobar).barLongObject().longValue());
+    }
+
+    @Test
+    public void testCollision() {
+        Foo foo = proxyFactory.createInvokerProxy(NullInvoker.INSTANCE, Foo.class, CollideFoo.class);
+        assertEquals(0, foo.fooInt());
+        assertEquals(100, foo.fooInteger().intValue());
+        assertEquals("collideFoo", foo.fooString());
+    }
+
+    @Test
+    public void testArrays() {
+        ArrayValues arrayValues = proxyFactory.createInvokerProxy(NullInvoker.INSTANCE, ArrayValues.class);
+        assertBooleanArrayEquals(new boolean[] { true, false }, arrayValues.booleanArray());
+        assertArrayEquals(new byte[] { 0, 1, 2 }, arrayValues.byteArray());
+        assertArrayEquals(new short[] { 3, 4, 5 }, arrayValues.shortArray());
+        assertArrayEquals(new int[] { 6, 7, 8 }, arrayValues.intArray());
+        assertArrayEquals(new char[] { 'a', 'b', 'c' }, arrayValues.charArray());
+        assertArrayEquals(new long[] { 9L, 10L, 11L }, arrayValues.longArray());
+        assertArrayEquals(new float[] { 0.0f, 0.1f, 0.2f }, arrayValues.floatArray(), 0.0f);
+        assertArrayEquals(new double[] { 0.0, 0.1, 0.2 }, arrayValues.doubleArray(), 0.0);
+        assertArrayEquals(new String[] { "foo", "bar", "baz" }, arrayValues.stringArray());
+        assertArrayEquals(new Object[] { "foo", 1, null }, arrayValues.objectArray());
+    }
+
+    private void assertBooleanArrayEquals(boolean[] expected, boolean[] actual) {
+        if (actual == expected) {
+            return;
+        }
+        if (expected != null && actual != null) {
+            if (actual.length == expected.length) {
+                for (int i = 0; i < actual.length; i++) {
+                    assertTrue(actual[i] == expected[i]);
+                }
+            }
+            return;
+        }
+        fail();
+    }
+
+    @Test
+    public void testDeferredResult() {
+        CurrentTime currentTime = proxyFactory.createInvokerProxy(
+                NullInvoker.INSTANCE, CurrentTime.class);
+        assertTrue(System.currentTimeMillis() <= currentTime
+                .currentTimeMillis());
+    }
+
+    @SuppressWarnings("serial")
+    @Test(expected=UnsupportedOperationException.class)
+    public void testUnhandled() {
+        Baz baz = proxyFactory.createInvokerProxy(new Invoker() {
+
+            public Object invoke(Object proxy, Method method, Object[] arguments)
+                    throws Throwable {
+                throw new UnsupportedOperationException();
+            }
+        }, Baz.class);
+        baz.dontTouchMe();
+    }
+
+    @Test
+    public void testAcceptArguments() {
+        AcceptArguments acceptArguments = proxyFactory.createInvokerProxy(NullInvoker.INSTANCE, AcceptArguments.class);
+        assertEquals("who", acceptArguments.respondTo("foo"));
+        assertEquals("far", acceptArguments.respondTo("bar"));
+        assertEquals("spazz", acceptArguments.respondTo("baz"));
+    }
+
+    @Test
+    public void testDelegator() {
+        ProxyFactory partialConfiguration = new StubProxyFactory(createParent(), new StubConfigurer<Foo>() {
+           /**
+             * {@inheritDoc}
+             */
+            @Override
+            protected void configure(Foo stub) {
+                when(stub.fooInt()).thenReturn(0).when(stub.fooInteger()).thenReturn(100);
+            }
+        });
+        Foo foo = partialConfiguration.createDelegatorProxy(new BeanProvider<Foo>(FooImpl.class), Foo.class);
+        assertEquals(0, foo.fooInt());
+        assertEquals(100, foo.fooInteger().intValue());
+        assertEquals("FooImpl", foo.fooString());
+    }
+
+    @Test
+    public void testInterceptor() {
+        ProxyFactory partialConfiguration = new StubProxyFactory(createParent(), new StubConfigurer<Foo>() {
+            /**
+              * {@inheritDoc}
+              */
+             @Override
+             protected void configure(Foo stub) {
+                 when(stub.fooInt()).thenReturn(0);
+             }
+         });
+
+        @SuppressWarnings("serial")
+        final Interceptor interceptor = new Interceptor() {
+
+            @Override
+            public Object intercept(Invocation invocation) throws Throwable {
+                if (invocation.getMethod().getName().equals("fooInteger")) {
+                    return 100;
+                }
+                return invocation.proceed();
+            }
+        };
+
+        Foo foo = partialConfiguration.createInterceptorProxy(new FooImpl(),
+                interceptor, Foo.class);
+
+        assertEquals(0, foo.fooInt());
+        assertEquals(100, foo.fooInteger().intValue());
+        assertEquals("FooImpl", foo.fooString());
+    }
+
+    @Test
+    public void testSubclassing() {
+        assumeTrue(proxyFactory.canProxy(FooImpl.class));
+        FooImpl foo = proxyFactory.createInvokerProxy(NullInvoker.INSTANCE, FooImpl.class);
+        assertEquals("foo", foo.fooString());
+        assertEquals(0, foo.fooInt());
+        assertEquals(100, foo.fooInteger().intValue());
+    }
+
+    @Test
+    public void testGenericStub() {
+        ProxyFactory iterableStubFactory = new StubProxyFactory(createParent(), new StubConfigurer<Iterable<String>>() {
+
+            @Override
+            protected void configure(Iterable<String> stub) {
+                when(stub.iterator()).thenReturn(Arrays.asList("foo", "bar", "baz").iterator());
+            }
+
+        });
+        Iterable<String> strings = iterableStubFactory.createInvokerProxy(NullInvoker.INSTANCE, Iterable.class);
+        assertIterator(strings.iterator(), "foo", "bar", "baz");
+    }
+
+    private <T> void assertIterator(Iterator<T> iter, T... expected) {
+        for (T t : expected) {
+            assertTrue(iter.hasNext());
+            assertEquals(t, iter.next());
+        }
+        assertFalse(iter.hasNext());
+    }
+
+    public interface Foo {
+        String fooString();
+
+        int fooInt();
+
+        Integer fooInteger();
+    }
+
+    public static class FooImpl implements Foo {
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public int fooInt() {
+            return 666;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public Integer fooInteger() {
+            return 667;
+        }
+
+        /**
+         * {@inheritDoc}
+         */
+        @Override
+        public String fooString() {
+            return "FooImpl";
+        }
+
+    }
+
+    public interface Bar {
+        String barString();
+
+        long barLong();
+
+        Long barLongObject();
+    }
+
+    public interface Baz {
+        Object dontTouchMe();
+    }
+
+    public interface CollideFoo {
+        String fooString();
+    }
+
+    public interface ArrayValues {
+        boolean[] booleanArray();
+
+        byte[] byteArray();
+
+        short[] shortArray();
+
+        int[] intArray();
+
+        char[] charArray();
+
+        long[] longArray();
+
+        float[] floatArray();
+
+        double[] doubleArray();
+
+        String[] stringArray();
+
+        Object[] objectArray();
+    }
+
+    public interface CurrentTime {
+        long currentTimeMillis();
+    }
+
+    public interface AcceptArguments {
+        String respondTo(String s);
+    }
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/AbstractStubProxyFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibAnnotationFactoryTest.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibAnnotationFactoryTest.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibAnnotationFactoryTest.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibAnnotationFactoryTest.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import org.apache.commons.proxy2.ProxyFactory;
+import org.apache.commons.proxy2.cglib.CglibProxyFactory;
+import org.apache.commons.proxy2.stub.AnnotationFactory;
+
+/**
+ * Test {@link AnnotationFactory} with {@link CglibProxyFactory}.
+ */
+public class CglibAnnotationFactoryTest extends
+        AbstractAnnotationFactoryTest {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected ProxyFactory createProxyFactory() {
+        return new CglibProxyFactory();
+    }
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibAnnotationFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibStubProxyFactoryTest.java
URL: http://svn.apache.org/viewvc/commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibStubProxyFactoryTest.java?rev=967275&view=auto
==============================================================================
--- commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibStubProxyFactoryTest.java (added)
+++ commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibStubProxyFactoryTest.java Fri Jul 23 21:44:40 2010
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.proxy2.stub;
+
+import org.apache.commons.proxy2.ProxyFactory;
+import org.apache.commons.proxy2.cglib.CglibProxyFactory;
+
+/**
+ * Test {@link StubProxyFactory} with {@link CglibProxyFactory}.
+ */
+public class CglibStubProxyFactoryTest extends AbstractStubProxyFactoryTest {
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    protected ProxyFactory createParent() {
+        return new CglibProxyFactory();
+    }
+}

Propchange: commons/proper/proxy/branches/version-2.0-work/stub/src/test/java/org/apache/commons/proxy2/stub/CglibStubProxyFactoryTest.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message