clean up nested context code a bit + reuse classloader for children
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/proxy/branches/version-2.0-work@1000560 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java b/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java
index 2345715..a184b1c 100644
--- a/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java
+++ b/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationConfigurer.java
@@ -18,14 +18,14 @@
import java.lang.annotation.Annotation;
+import org.apache.commons.lang3.Pair;
+
/**
* Special {@link StubConfigurer} subclass that makes creating nested annotations (somewhat more) convenient.
*
* @param <A>
*/
public abstract class AnnotationConfigurer<A extends Annotation> extends StubConfigurer<A> {
- AnnotationFactory annotationFactory;
-
/**
* Create a child annotation of the specified type using a StubConfigurer.
* @param <T>
@@ -38,7 +38,8 @@
if (configurer == this) {
throw new IllegalArgumentException("An AnnotationConfigurer cannot configure its own child annotation");
}
- return requireAnnotationFactory().create(configurer);
+ Pair<AnnotationFactory, ClassLoader> context = requireContext();
+ return context.left.create(context.right, configurer);
}
/**
@@ -49,18 +50,21 @@
* @throws IllegalStateException if called other than when an {@link AnnotationFactory} is executing {@link #configure(Object)}
*/
protected final <T extends Annotation> T child(Class<T> annotationType) {
- return requireAnnotationFactory().create(annotationType);
+ Pair<AnnotationFactory, ClassLoader> context = requireContext();
+ return context.left.create(context.right, annotationType);
}
/**
- * Get the registered annotationFactory.
- * @return AnnotationFactory
+ * Get the registered {@link AnnotationFactory}/{@link ClassLoader}.
+ * @return a {@link Pair}
* @throws IllegalStateException if no ongoing annotation stubbing could be detected
*/
- synchronized AnnotationFactory requireAnnotationFactory() throws IllegalStateException {
- if (annotationFactory == null) {
+ synchronized Pair<AnnotationFactory, ClassLoader> requireContext() throws IllegalStateException {
+ Pair<AnnotationFactory, ClassLoader> result = AnnotationFactory.CONTEXT.get();
+ if (result == null) {
throw new IllegalStateException("Could not detect ongoing annotation stubbing");
}
- return annotationFactory;
+ return result;
}
+
}
\ No newline at end of file
diff --git a/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java b/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
index e33fbfd..7e96787 100644
--- a/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
+++ b/stub/src/main/java/org/apache/commons/proxy2/stub/AnnotationFactory.java
@@ -25,6 +25,7 @@
import java.lang.reflect.Proxy;
import org.apache.commons.lang3.AnnotationUtils;
+import org.apache.commons.lang3.Pair;
import org.apache.commons.proxy2.Interceptor;
import org.apache.commons.proxy2.Invocation;
import org.apache.commons.proxy2.Invoker;
@@ -47,6 +48,12 @@
/** Statically available instance */
public static final AnnotationFactory INSTANCE;
+ /**
+ * Record the context of a call for possible use by nested annotation creations.
+ */
+ static final ThreadLocal<Pair<AnnotationFactory, ClassLoader>> CONTEXT =
+ new ThreadLocal<Pair<AnnotationFactory, ClassLoader>>();
+
private static final ProxyFactory PROXY_FACTORY;
static {
@@ -175,21 +182,7 @@
if (o instanceof StubConfigurer<?>) {
@SuppressWarnings("unchecked")
final StubConfigurer<Annotation> configurer = (StubConfigurer<Annotation>) o;
- boolean deregisterFactory = false;
- synchronized (configurer) {
- try {
- if (configurer instanceof AnnotationConfigurer<?>) {
- AnnotationConfigurer<?> annotationConfigurer = (AnnotationConfigurer<?>) configurer;
- deregisterFactory = true;
- annotationConfigurer.annotationFactory = AnnotationFactory.this;
- }
- configurer.configure(requireStubInterceptor(), stub);
- } finally {
- if (deregisterFactory) {
- ((AnnotationConfigurer<?>) configurer).annotationFactory = null;
- }
- }
- }
+ configurer.configure(requireStubInterceptor(), stub);
}
}
};
@@ -256,8 +249,12 @@
private <A extends Annotation> A createInternal(ClassLoader classLoader, Object configurer) {
final Object existingConfigurer = CONFIGURER.get();
+ final boolean outerContext = CONTEXT.get() == null;
try {
CONFIGURER.set(configurer);
+ if (outerContext) {
+ CONTEXT.set(Pair.of(this, classLoader));
+ }
@SuppressWarnings("unchecked")
final A result = (A) proxyFactory.createInvokerProxy(classLoader, ANNOTATION_INVOKER, getStubType());
return result;
@@ -267,6 +264,9 @@
} else {
CONFIGURER.set(existingConfigurer);
}
+ if (outerContext) {
+ CONTEXT.remove();
+ }
}
}