From b07984435fd3e684d4d7ca9ff0e948b90b2a5501 Mon Sep 17 00:00:00 2001 From: Adrian Cole Date: Sun, 13 Jan 2013 22:41:06 -0800 Subject: [PATCH] unwound a few stack traces by making DelegatesToInvocationFunction an invocation handler directly --- .../jclouds/reflect/FunctionalReflection.java | 21 ++--- .../java/org/jclouds/reflect/Invocation.java | 62 ------------- .../rest/config/AsyncHttpApiProvider.java | 12 +-- .../rest/config/CallGetOnFuturesProvider.java | 13 +-- .../jclouds/rest/config/HttpApiProvider.java | 13 +-- .../jclouds/rest/internal/BlockOnFuture.java | 11 +-- ...ava => DelegatesToInvocationFunction.java} | 93 +++++++++++++++---- .../internal/InvokeAndCallGetOnFutures.java | 18 ++-- .../rest/internal/InvokeHttpMethod.java | 7 +- .../reflect/FunctionalReflectionTest.java | 46 ++++----- 10 files changed, 136 insertions(+), 160 deletions(-) rename core/src/main/java/org/jclouds/rest/internal/{DelegatingInvocationFunction.java => DelegatesToInvocationFunction.java} (71%) diff --git a/core/src/main/java/org/jclouds/reflect/FunctionalReflection.java b/core/src/main/java/org/jclouds/reflect/FunctionalReflection.java index 30a6e245c8..42a20dd55b 100644 --- a/core/src/main/java/org/jclouds/reflect/FunctionalReflection.java +++ b/core/src/main/java/org/jclouds/reflect/FunctionalReflection.java @@ -32,8 +32,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.jclouds.reflect.Invocation.Result; - import com.google.common.annotations.Beta; import com.google.common.base.Function; import com.google.common.base.Objects; @@ -77,13 +75,13 @@ public final class FunctionalReflection { * @see com.google.common.reflect.AbstractInvocationHandler#invoke(Object, Method, Object[]) * @see com.google.common.reflect.Reflection#newProxy(Class, java.lang.reflect.InvocationHandler) */ - public static T newProxy(TypeToken enclosingType, Function invocationFunction) { + public static T newProxy(TypeToken enclosingType, Function invocationFunction) { checkNotNull(enclosingType, "enclosingType"); checkNotNull(invocationFunction, "invocationFunction"); return newProxy(enclosingType.getRawType(), new FunctionalInvocationHandler(enclosingType, invocationFunction)); } - public static T newProxy(Class enclosingType, Function invocationFunction) { + public static T newProxy(Class enclosingType, Function invocationFunction) { checkNotNull(invocationFunction, "invocationFunction"); return newProxy(enclosingType, new FunctionalInvocationHandler(TypeToken.of(enclosingType), invocationFunction)); @@ -100,9 +98,9 @@ public final class FunctionalReflection { private static final class FunctionalInvocationHandler extends com.google.common.reflect.AbstractInvocationHandler { private final TypeToken enclosingType; - private final Function invocationFunction; + private final Function invocationFunction; - private FunctionalInvocationHandler(TypeToken enclosingType, Function invocationFunction) { + private FunctionalInvocationHandler(TypeToken enclosingType, Function invocationFunction) { this.enclosingType = enclosingType; this.invocationFunction = invocationFunction; } @@ -117,17 +115,12 @@ public final class FunctionalReflection { Invokable invokable = Invokable.from(invoked); // not yet support the proxy arg Invocation invocation = Invocation.create(invokable, args); - Result result; try { - result = invocationFunction.apply(invocation); + return invocationFunction.apply(invocation); } catch (RuntimeException e) { - result = Result.fail(e); + propagateIfPossible(e, invocation.getInvokable().getExceptionTypes()); + throw propagate(e); } - if (result.getThrowable().isPresent()) { - propagateIfPossible(result.getThrowable().get(), invocation.getInvokable().getExceptionTypes()); - throw propagate(result.getThrowable().get()); - } - return result.getResult().orNull(); } @Override diff --git a/core/src/main/java/org/jclouds/reflect/Invocation.java b/core/src/main/java/org/jclouds/reflect/Invocation.java index 896b2d5861..1185663d43 100644 --- a/core/src/main/java/org/jclouds/reflect/Invocation.java +++ b/core/src/main/java/org/jclouds/reflect/Invocation.java @@ -23,11 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull; import java.util.List; -import org.jclouds.javax.annotation.Nullable; - import com.google.common.annotations.Beta; import com.google.common.base.Objects; -import com.google.common.base.Optional; import com.google.common.reflect.Invokable; /** @@ -90,63 +87,4 @@ public final class Invocation { public String toString() { return String.format("%s%s", invokable, args); } - - /** - * result of an invocation which is either successful or failed, but not both. - */ - @Beta - public final static class Result { - public static Result success(@Nullable Object result) { - return new Result(Optional.fromNullable(result), Optional. absent()); - } - - public static Result fail(Throwable throwable) { - return new Result(Optional.absent(), Optional.of(throwable)); - } - - private final Optional result; - private final Optional throwable; - - private Result(Optional result, Optional throwable) { - this.result = checkNotNull(result, "result"); - this.throwable = checkNotNull(throwable, "throwable"); - } - - /** - * result of{@link Invokable#invoke(Object, Object...)} - */ - public Optional getResult() { - return result; - } - - /** - * throwable received during {@link Invokable#invoke(Object, Object...)} - */ - public Optional getThrowable() { - return throwable; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - Result that = Result.class.cast(o); - return equal(this.result.orNull(), that.result.orNull()) - && equal(this.throwable.orNull(), that.throwable.orNull()); - } - - @Override - public int hashCode() { - return Objects.hashCode(result.orNull(), throwable.orNull()); - } - - @Override - public String toString() { - return Objects.toStringHelper("").omitNullValues().add("result", result.orNull()) - .add("throwable", throwable.orNull()).toString(); - } - } - } diff --git a/core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java b/core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java index a8125229a1..5f5037d15a 100644 --- a/core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java +++ b/core/src/main/java/org/jclouds/rest/config/AsyncHttpApiProvider.java @@ -18,11 +18,12 @@ */ package org.jclouds.rest.config; +import java.lang.reflect.Proxy; + import javax.inject.Inject; import javax.inject.Singleton; -import org.jclouds.reflect.FunctionalReflection; -import org.jclouds.rest.internal.DelegatingInvocationFunction; +import org.jclouds.rest.internal.DelegatesToInvocationFunction; import org.jclouds.rest.internal.InvokeHttpMethod; import com.google.inject.Provider; @@ -35,10 +36,10 @@ import com.google.inject.TypeLiteral; @Singleton public class AsyncHttpApiProvider implements Provider { private final Class asyncApiType; - private final DelegatingInvocationFunction> httpInvoker; + private final DelegatesToInvocationFunction> httpInvoker; @Inject - private AsyncHttpApiProvider(DelegatingInvocationFunction> httpInvoker, + private AsyncHttpApiProvider(DelegatesToInvocationFunction> httpInvoker, TypeLiteral asyncApiType) { this.httpInvoker = httpInvoker; this.asyncApiType = asyncApiType.getRawType(); @@ -47,7 +48,6 @@ public class AsyncHttpApiProvider implements Provider { @SuppressWarnings("unchecked") @Override public A get() { - return (A) FunctionalReflection.newProxy(asyncApiType, httpInvoker); + return (A) Proxy.newProxyInstance(asyncApiType.getClassLoader(), new Class[] { asyncApiType }, httpInvoker); } - } diff --git a/core/src/main/java/org/jclouds/rest/config/CallGetOnFuturesProvider.java b/core/src/main/java/org/jclouds/rest/config/CallGetOnFuturesProvider.java index edb266b379..d926c9ba9f 100644 --- a/core/src/main/java/org/jclouds/rest/config/CallGetOnFuturesProvider.java +++ b/core/src/main/java/org/jclouds/rest/config/CallGetOnFuturesProvider.java @@ -18,15 +18,16 @@ */ package org.jclouds.rest.config; +import java.lang.reflect.Proxy; + import javax.inject.Inject; import javax.inject.Singleton; -import org.jclouds.reflect.FunctionalReflection; -import com.google.common.reflect.Invokable; -import org.jclouds.rest.internal.DelegatingInvocationFunction; +import org.jclouds.rest.internal.DelegatesToInvocationFunction; import org.jclouds.rest.internal.InvokeAndCallGetOnFutures; import com.google.common.cache.Cache; +import com.google.common.reflect.Invokable; import com.google.common.reflect.TypeToken; import com.google.inject.Provider; @@ -37,11 +38,11 @@ import com.google.inject.Provider; public class CallGetOnFuturesProvider implements Provider { private final Class apiType; - private final DelegatingInvocationFunction> syncInvoker; + private final DelegatesToInvocationFunction> syncInvoker; @Inject private CallGetOnFuturesProvider(Cache, Invokable> invokables, - DelegatingInvocationFunction> syncInvoker, Class apiType, + DelegatesToInvocationFunction> syncInvoker, Class apiType, Class asyncApiType) { this.syncInvoker = syncInvoker; this.apiType = apiType; @@ -52,6 +53,6 @@ public class CallGetOnFuturesProvider implements Provider { @Override @Singleton public S get() { - return (S) FunctionalReflection.newProxy(apiType, syncInvoker); + return (S) Proxy.newProxyInstance(apiType.getClassLoader(), new Class[] { apiType }, syncInvoker); } } diff --git a/core/src/main/java/org/jclouds/rest/config/HttpApiProvider.java b/core/src/main/java/org/jclouds/rest/config/HttpApiProvider.java index cfdfa12fba..85730d86c8 100644 --- a/core/src/main/java/org/jclouds/rest/config/HttpApiProvider.java +++ b/core/src/main/java/org/jclouds/rest/config/HttpApiProvider.java @@ -18,15 +18,16 @@ */ package org.jclouds.rest.config; +import java.lang.reflect.Proxy; + import javax.inject.Inject; import javax.inject.Singleton; -import org.jclouds.reflect.FunctionalReflection; -import com.google.common.reflect.Invokable; -import org.jclouds.rest.internal.DelegatingInvocationFunction; +import org.jclouds.rest.internal.DelegatesToInvocationFunction; import org.jclouds.rest.internal.InvokeHttpMethod; import com.google.common.cache.Cache; +import com.google.common.reflect.Invokable; import com.google.common.reflect.TypeToken; import com.google.inject.Provider; @@ -37,11 +38,11 @@ import com.google.inject.Provider; @Singleton public class HttpApiProvider implements Provider { private final Class apiType; - private final DelegatingInvocationFunction> httpInvoker; + private final DelegatesToInvocationFunction> httpInvoker; @Inject private HttpApiProvider(Cache, Invokable> invokables, - DelegatingInvocationFunction> httpInvoker, Class apiType, Class asyncApiType) { + DelegatesToInvocationFunction> httpInvoker, Class apiType, Class asyncApiType) { this.httpInvoker = httpInvoker; this.apiType = apiType; RestModule.putInvokables(TypeToken.of(apiType), TypeToken.of(asyncApiType), invokables); @@ -51,7 +52,7 @@ public class HttpApiProvider implements Provider { @Override @Singleton public S get() { - return (S) FunctionalReflection.newProxy(apiType, httpInvoker); + return (S) Proxy.newProxyInstance(apiType.getClassLoader(), new Class[] { apiType }, httpInvoker); } } diff --git a/core/src/main/java/org/jclouds/rest/internal/BlockOnFuture.java b/core/src/main/java/org/jclouds/rest/internal/BlockOnFuture.java index ceb9a7a4bc..b07d684df0 100644 --- a/core/src/main/java/org/jclouds/rest/internal/BlockOnFuture.java +++ b/core/src/main/java/org/jclouds/rest/internal/BlockOnFuture.java @@ -34,7 +34,6 @@ import javax.inject.Named; import org.jclouds.logging.Logger; import org.jclouds.reflect.Invocation; -import org.jclouds.reflect.Invocation.Result; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; @@ -46,7 +45,7 @@ import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.UncheckedTimeoutException; import com.google.inject.assistedinject.Assisted; -public class BlockOnFuture implements Function, Result> { +public class BlockOnFuture implements Function, Object> { public static interface Factory { /** @@ -73,19 +72,19 @@ public class BlockOnFuture implements Function, Result> { } @Override - public Result apply(ListenableFuture future) { + public Object apply(ListenableFuture future) { Optional timeoutNanos = timeoutInNanos(invocation.getInvokable(), timeouts); return block(future, timeoutNanos); } - private Result block(ListenableFuture future, Optional timeoutNanos) { + private Object block(ListenableFuture future, Optional timeoutNanos) { try { if (timeoutNanos.isPresent()) { logger.debug(">> blocking on %s for %s", future, timeoutNanos); - return Result.success(getUninterruptibly(future, timeoutNanos.get(), NANOSECONDS)); + return getUninterruptibly(future, timeoutNanos.get(), NANOSECONDS); } else { logger.debug(">> blocking on %s", future); - return Result.success(getUninterruptibly(future)); + return getUninterruptibly(future); } } catch (ExecutionException e) { throw propagateCause(e); diff --git a/core/src/main/java/org/jclouds/rest/internal/DelegatingInvocationFunction.java b/core/src/main/java/org/jclouds/rest/internal/DelegatesToInvocationFunction.java similarity index 71% rename from core/src/main/java/org/jclouds/rest/internal/DelegatingInvocationFunction.java rename to core/src/main/java/org/jclouds/rest/internal/DelegatesToInvocationFunction.java index 61859b84c1..23b41a62d3 100644 --- a/core/src/main/java/org/jclouds/rest/internal/DelegatingInvocationFunction.java +++ b/core/src/main/java/org/jclouds/rest/internal/DelegatesToInvocationFunction.java @@ -19,25 +19,33 @@ package org.jclouds.rest.internal; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Predicates.notNull; import static com.google.common.base.Throwables.propagate; +import static com.google.common.collect.Iterables.all; import static com.google.common.collect.Iterables.find; import static com.google.inject.util.Types.newParameterizedType; import static org.jclouds.util.Optionals2.isReturnTypeOptional; import static org.jclouds.util.Optionals2.unwrapIfOptional; import static org.jclouds.util.Throwables2.getFirstThrowableOfType; +import static org.jclouds.util.Throwables2.propagateIfPossible; import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.inject.Qualifier; +import org.jclouds.javax.annotation.Nullable; import org.jclouds.reflect.FunctionalReflection; import org.jclouds.reflect.Invocation; -import org.jclouds.reflect.Invocation.Result; import org.jclouds.reflect.InvocationSuccess; -import com.google.common.reflect.Invokable; import org.jclouds.rest.AuthorizationException; import org.jclouds.rest.annotations.Delegate; import org.jclouds.rest.config.SetCaller; @@ -49,6 +57,8 @@ import com.google.common.base.Optional; import com.google.common.base.Predicate; import com.google.common.base.Supplier; import com.google.common.collect.ImmutableList; +import com.google.common.reflect.AbstractInvocationHandler; +import com.google.common.reflect.Invokable; import com.google.common.reflect.TypeToken; import com.google.inject.Binding; import com.google.inject.ConfigurationException; @@ -60,7 +70,6 @@ import com.google.inject.TypeLiteral; import com.google.inject.util.Types; /** - * * @param * The enclosing type of the interface that a dynamic proxy like this implements * @param @@ -69,8 +78,67 @@ import com.google.inject.util.Types; * The function that implements this dynamic proxy */ @Beta -public final class DelegatingInvocationFunction> implements - Function { +public final class DelegatesToInvocationFunction> implements + InvocationHandler { + + private static final Object[] NO_ARGS = {}; + + /** + * {@inheritDoc} + * + *

+ *

    + *
  • {@code proxy.hashCode()} delegates to {@link AbstractInvocationHandler#hashCode} + *
  • {@code proxy.toString()} delegates to {@link AbstractInvocationHandler#toString} + *
  • {@code proxy.equals(argument)} returns true if: + *
      + *
    • {@code proxy} and {@code argument} are of the same type + *
    • and {@link AbstractInvocationHandler#equals} returns true for the {@link InvocationHandler} of + * {@code argument} + *
    + *
  • other method calls are dispatched to {@link #handleInvocation}. + *
+ * @throws Throwable + */ + @Override + public final Object invoke(Object proxy, Method invoked, @Nullable Object[] argv) throws Throwable { + if (argv == null) { + argv = NO_ARGS; + } + if (argv.length == 0 && invoked.getName().equals("hashCode")) { + return hashCode(); + } + if (argv.length == 1 && invoked.getName().equals("equals") && invoked.getParameterTypes()[0] == Object.class) { + Object arg = argv[0]; + return proxy.getClass().isInstance(arg) && equals(Proxy.getInvocationHandler(arg)); + } + if (argv.length == 0 && invoked.getName().equals("toString")) { + return toString(); + } + List args = Arrays.asList(argv); + if (all(args, notNull())) + args = ImmutableList.copyOf(args); + else + args = Collections.unmodifiableList(args); + Invokable invokable = Invokable.from(invoked); + // not yet support the proxy arg + Invocation invocation = Invocation.create(invokable, args); + try { + return handle(invocation); + } catch (Throwable e) { + propagateIfPossible(e, invocation.getInvokable().getExceptionTypes()); + throw e; + } + } + + protected Object handle(Invocation invocation) { + if (invocation.getInvokable().isAnnotationPresent(Provides.class)) + return lookupValueFromGuice(invocation.getInvokable()); + else if (invocation.getInvokable().isAnnotationPresent(Delegate.class)) + return propagateContextToDelegate(invocation); + return methodInvoker.apply(invocation); + } + private final Injector injector; private final TypeToken enclosingType; private final SetCaller setCaller; @@ -80,7 +148,7 @@ public final class DelegatingInvocationFunction, Class> syncToAsync, + DelegatesToInvocationFunction(Injector injector, SetCaller setCaller, Map, Class> syncToAsync, TypeLiteral enclosingType, Function> optionalConverter, F methodInvoker) { this.injector = checkNotNull(injector, "injector"); this.enclosingType = (TypeToken) TypeToken.of(checkNotNull(enclosingType, "enclosingType").getType()); @@ -90,22 +158,13 @@ public final class DelegatingInvocationFunction returnType = unwrapIfOptional(caller.getInvokable().getReturnType()); - Function delegate; + Function delegate; setCaller.enter(enclosingType, caller); try { @SuppressWarnings("unchecked") - Key> delegateType = (Key>) methodInvokerFor(returnType); + Key> delegateType = (Key>) methodInvokerFor(returnType); delegate = injector.getInstance(delegateType); } finally { setCaller.exit(); diff --git a/core/src/main/java/org/jclouds/rest/internal/InvokeAndCallGetOnFutures.java b/core/src/main/java/org/jclouds/rest/internal/InvokeAndCallGetOnFutures.java index 53a98cfe90..3478754353 100644 --- a/core/src/main/java/org/jclouds/rest/internal/InvokeAndCallGetOnFutures.java +++ b/core/src/main/java/org/jclouds/rest/internal/InvokeAndCallGetOnFutures.java @@ -19,6 +19,8 @@ package org.jclouds.rest.internal; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Throwables.propagate; +import static com.google.common.util.concurrent.Futures.getUnchecked; import java.lang.reflect.InvocationTargetException; @@ -27,20 +29,18 @@ import javax.inject.Inject; import org.jclouds.logging.Logger; import org.jclouds.reflect.Invocation; -import org.jclouds.reflect.Invocation.Result; -import com.google.common.reflect.Invokable; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; import com.google.common.cache.Cache; -import com.google.common.util.concurrent.Futures; +import com.google.common.reflect.Invokable; import com.google.common.util.concurrent.ListenableFuture; /** * * @author Adrian Cole */ -public final class InvokeAndCallGetOnFutures implements Function { +public final class InvokeAndCallGetOnFutures implements Function { @Resource private Logger logger = Logger.NULL; @@ -62,7 +62,7 @@ public final class InvokeAndCallGetOnFutures implements Function implements Function target) { diff --git a/core/src/main/java/org/jclouds/rest/internal/InvokeHttpMethod.java b/core/src/main/java/org/jclouds/rest/internal/InvokeHttpMethod.java index 761b9f76dd..11661327a1 100644 --- a/core/src/main/java/org/jclouds/rest/internal/InvokeHttpMethod.java +++ b/core/src/main/java/org/jclouds/rest/internal/InvokeHttpMethod.java @@ -35,7 +35,6 @@ import org.jclouds.http.HttpCommandExecutorService; import org.jclouds.http.HttpResponse; import org.jclouds.logging.Logger; import org.jclouds.reflect.Invocation; -import org.jclouds.reflect.Invocation.Result; import org.jclouds.rest.InvocationContext; import org.jclouds.rest.annotations.Fallback; @@ -53,7 +52,7 @@ import com.google.common.util.concurrent.ListeningExecutorService; import com.google.inject.Injector; import com.google.inject.TypeLiteral; -public class InvokeHttpMethod implements Function { +public class InvokeHttpMethod implements Function { @Resource private Logger logger = Logger.NULL; @@ -98,9 +97,9 @@ public class InvokeHttpMethod implements Function { }); @Override - public Result apply(Invocation in) { + public Object apply(Invocation in) { if (isFuture(in.getInvokable())) { - return Result.success(createFuture(in)); + return createFuture(in); } @SuppressWarnings("rawtypes") Invokable async = checkNotNull(sync2AsyncInvokables.getIfPresent(in.getInvokable()), "invokable %s not in %s", diff --git a/core/src/test/java/org/jclouds/reflect/FunctionalReflectionTest.java b/core/src/test/java/org/jclouds/reflect/FunctionalReflectionTest.java index 6252da5eb4..6d9e80a701 100644 --- a/core/src/test/java/org/jclouds/reflect/FunctionalReflectionTest.java +++ b/core/src/test/java/org/jclouds/reflect/FunctionalReflectionTest.java @@ -27,9 +27,7 @@ import static org.testng.Assert.assertTrue; import java.io.Closeable; import java.io.IOException; import java.util.Set; -import java.util.concurrent.TimeoutException; -import org.jclouds.reflect.Invocation.Result; import org.testng.annotations.Test; import com.google.common.base.Function; @@ -45,8 +43,8 @@ public class FunctionalReflectionTest { @SuppressWarnings("unchecked") @Test(expectedExceptions = UnsupportedOperationException.class) public void testNullArgsAreAllowedAndUnmodifiable() { - final Function test = new Function() { - public Result apply(Invocation e) { + final Function test = new Function() { + public Object apply(Invocation e) { assertNotNull(e.getArgs()); assertNull(e.getArgs().get(0)); e.getArgs().add("foo"); @@ -59,8 +57,8 @@ public class FunctionalReflectionTest { @SuppressWarnings("unchecked") @Test(expectedExceptions = UnsupportedOperationException.class) public void testImmutableListWhenArgsAreNotNull() { - final Function test = new Function() { - public Result apply(Invocation e) { + final Function test = new Function() { + public Object apply(Invocation e) { assertNotNull(e.getArgs()); assertTrue(e.getArgs() instanceof ImmutableList); assertEquals(e.getArgs().get(0), "foo"); @@ -73,9 +71,9 @@ public class FunctionalReflectionTest { @Test(expectedExceptions = IOException.class, expectedExceptionsMessageRegExp = "io") public void testPropagatesDeclaredException() throws IOException { - final Function test = new Function() { - public Result apply(Invocation e) { - return Result.fail(new IOException("io")); + final Function test = new Function() { + public Object apply(Invocation e) { + throw new RuntimeException(new IOException("io")); } }; Closeable closeable = FunctionalReflection.newProxy(Closeable.class, test); @@ -87,21 +85,9 @@ public class FunctionalReflectionTest { */ @Test(expectedExceptions = AssertionError.class, expectedExceptionsMessageRegExp = "assert") public void testPropagatesError() throws IOException { - final Function test = new Function() { - public Result apply(Invocation e) { - return Result.fail(new AssertionError("assert")); - } - }; - Closeable closeable = FunctionalReflection.newProxy(Closeable.class, test); - closeable.close(); - } - - // TODO: coerce things like this to UncheckedTimeoutException and friends - @Test(expectedExceptions = RuntimeException.class, expectedExceptionsMessageRegExp = ".*timeout") - public void testWrapsDeclaredException() throws IOException { - final Function test = new Function() { - public Result apply(Invocation e) { - return Result.fail(new TimeoutException("timeout")); + final Function test = new Function() { + public Object apply(Invocation e) { + throw new AssertionError("assert"); } }; Closeable closeable = FunctionalReflection.newProxy(Closeable.class, test); @@ -109,9 +95,9 @@ public class FunctionalReflectionTest { } public void testToStringEqualsFunction() { - final Function test = new Function() { - public Result apply(Invocation e) { - return Result.success("foo"); + final Function test = new Function() { + public Object apply(Invocation e) { + return "foo"; } public String toString() { @@ -123,9 +109,9 @@ public class FunctionalReflectionTest { } public void testHashCodeDifferentiatesOnInterface() { - final Function test = new Function() { - public Result apply(Invocation e) { - return Result.success(null); + final Function test = new Function() { + public Object apply(Invocation e) { + return null; } public int hashCode() {