Repository: deltaspike Updated Branches: refs/heads/master afa433335 -> 26ff7d00d
DELTASPIKE-904 Stereotype support for interceptor binding lookup on partial beans Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/26ff7d00 Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/26ff7d00 Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/26ff7d00 Branch: refs/heads/master Commit: 26ff7d00d740197f8eace44c9e217a78f5d68bd8 Parents: afa4333 Author: Thomas Andraschko <[email protected]> Authored: Sun Jul 12 11:42:17 2015 +0200 Committer: Thomas Andraschko <[email protected]> Committed: Sun Jul 12 11:42:17 2015 +0200 ---------------------------------------------------------------------- .../shared/CustomInterceptorState.java | 1 + .../uc007/CustomInterceptorStereotype.java | 36 ++++++++++++++ .../uc007/MethodLevelInterceptorTest.java | 14 ++++++ .../core/api/partialbean/uc007/PartialBean.java | 6 +++ .../api/DeltaSpikeProxyContextualLifecycle.java | 2 +- .../proxy/api/DeltaSpikeProxyFactory.java | 37 +++++++++----- .../AbstractManualInvocationHandler.java | 52 ++++++++++++++------ 7 files changed, 120 insertions(+), 28 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/deltaspike/blob/26ff7d00/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/shared/CustomInterceptorState.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/shared/CustomInterceptorState.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/shared/CustomInterceptorState.java index 7fad111..ef077e6 100644 --- a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/shared/CustomInterceptorState.java +++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/shared/CustomInterceptorState.java @@ -34,4 +34,5 @@ public class CustomInterceptorState { this.intercepted = intercepted; } + } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/deltaspike/blob/26ff7d00/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/CustomInterceptorStereotype.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/CustomInterceptorStereotype.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/CustomInterceptorStereotype.java new file mode 100644 index 0000000..92a03bd --- /dev/null +++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/CustomInterceptorStereotype.java @@ -0,0 +1,36 @@ +/* + * 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.deltaspike.test.core.api.partialbean.uc007; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import javax.enterprise.inject.Stereotype; +import org.apache.deltaspike.test.core.api.partialbean.shared.CustomInterceptor; + +@Inherited +@Target({ ElementType.TYPE, ElementType.METHOD, ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +@Stereotype +@CustomInterceptor +public @interface CustomInterceptorStereotype { + +} http://git-wip-us.apache.org/repos/asf/deltaspike/blob/26ff7d00/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/MethodLevelInterceptorTest.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/MethodLevelInterceptorTest.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/MethodLevelInterceptorTest.java index 6cd400d..a33ee85 100644 --- a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/MethodLevelInterceptorTest.java +++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/MethodLevelInterceptorTest.java @@ -84,6 +84,20 @@ public class MethodLevelInterceptorTest partialBean.doSomething(); Assert.assertEquals(true, state.isIntercepted()); } + + @Test + public void testMethodLevelInterceptorStereotype() throws Exception + { + // this test is known to not work under weld-2.0.0.Final and weld-2.0.0.SP1 + Assume.assumeTrue(!CdiContainerUnderTest.is(CONTAINER_WELD_2_0_0)); + + PartialBean partialBean = BeanProvider.getContextualReference(PartialBean.class); + CustomInterceptorState state = BeanProvider.getContextualReference(CustomInterceptorState.class); + + Assert.assertNotNull(partialBean); + partialBean.doSomething2(); + Assert.assertEquals(true, state.isIntercepted()); + } @Test public void testMethodLevelInterceptorOnAbstractMethod() throws Exception http://git-wip-us.apache.org/repos/asf/deltaspike/blob/26ff7d00/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/PartialBean.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/PartialBean.java b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/PartialBean.java index 8708683..bf71e84 100644 --- a/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/PartialBean.java +++ b/deltaspike/modules/partial-bean/impl/src/test/java/org/apache/deltaspike/test/core/api/partialbean/uc007/PartialBean.java @@ -35,4 +35,10 @@ public abstract class PartialBean { String a = "test"; } + + @CustomInterceptorStereotype + public void doSomething2() + { + String a = "test2"; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/deltaspike/blob/26ff7d00/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java index 2b57a2d..e550b88 100644 --- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java +++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyContextualLifecycle.java @@ -59,7 +59,7 @@ public class DeltaSpikeProxyContextualLifecycle<T, H extends InvocationHandler> { this.targetClass = targetClass; this.delegateInvocationHandlerClass = delegateInvocationHandlerClass; - this.proxyClass = proxyFactory.getProxyClass(targetClass, delegateInvocationHandlerClass); + this.proxyClass = proxyFactory.getProxyClass(beanManager, targetClass, delegateInvocationHandlerClass); if (!targetClass.isInterface()) { http://git-wip-us.apache.org/repos/asf/deltaspike/blob/26ff7d00/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java index 7cb24b3..1e19ab1 100644 --- a/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java +++ b/deltaspike/modules/proxy/api/src/main/java/org/apache/deltaspike/proxy/api/DeltaSpikeProxyFactory.java @@ -26,6 +26,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; +import javax.enterprise.inject.spi.BeanManager; import javax.interceptor.InterceptorBinding; @@ -77,21 +78,22 @@ public abstract class DeltaSpikeProxyFactory return GeneratorHolder.generator; } - public <T> Class<T> getProxyClass(Class<T> targetClass, + public <T> Class<T> getProxyClass(BeanManager beanManager, Class<T> targetClass, Class<? extends InvocationHandler> delegateInvocationHandlerClass) { // check if a proxy is already defined for this class Class<T> proxyClass = ClassUtils.tryToLoadClassForName(constructProxyClassName(targetClass), targetClass); if (proxyClass == null) { - proxyClass = createProxyClass(targetClass.getClassLoader(), targetClass, delegateInvocationHandlerClass); + proxyClass = createProxyClass(beanManager, targetClass.getClassLoader(), targetClass, + delegateInvocationHandlerClass); } return proxyClass; } - private synchronized <T> Class<T> createProxyClass(ClassLoader classLoader, Class<T> targetClass, - Class<? extends InvocationHandler> delegateInvocationHandlerClass) + private synchronized <T> Class<T> createProxyClass(BeanManager beanManager, ClassLoader classLoader, + Class<T> targetClass, Class<? extends InvocationHandler> delegateInvocationHandlerClass) { Class<T> proxyClass = ClassUtils.tryToLoadClassForName(constructProxyClassName(targetClass), targetClass); if (proxyClass == null) @@ -103,7 +105,7 @@ public abstract class DeltaSpikeProxyFactory // check if a interceptor is defined on class level. if not, skip interceptor methods if (delegateMethods != null && interceptMethods.size() > 0 - && !containsInterceptorBinding(targetClass.getDeclaredAnnotations())) + && !containsInterceptorBinding(beanManager, targetClass.getDeclaredAnnotations())) { // loop every method and check if a interceptor is defined on the method -> otherwise don't overwrite // interceptMethods @@ -111,7 +113,7 @@ public abstract class DeltaSpikeProxyFactory while (iterator.hasNext()) { Method method = iterator.next(); - if (!containsInterceptorBinding(method.getDeclaredAnnotations())) + if (!containsInterceptorBinding(beanManager, method.getDeclaredAnnotations())) { iterator.remove(); } @@ -134,16 +136,29 @@ public abstract class DeltaSpikeProxyFactory return proxyClass; } - - // TODO stereotypes - protected boolean containsInterceptorBinding(Annotation[] annotations) + + protected boolean containsInterceptorBinding(BeanManager beanManager, Annotation[] annotations) { for (Annotation annotation : annotations) - { - if (annotation.annotationType().isAnnotationPresent(InterceptorBinding.class)) + { + Class<? extends Annotation> annotationType = annotation.annotationType(); + + if (annotationType.isAnnotationPresent(InterceptorBinding.class)) { return true; } + + if (beanManager.isStereotype(annotationType)) + { + boolean containsInterceptorBinding = containsInterceptorBinding( + beanManager, + annotationType.getDeclaredAnnotations()); + + if (containsInterceptorBinding) + { + return true; + } + } } return false; http://git-wip-us.apache.org/repos/asf/deltaspike/blob/26ff7d00/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java ---------------------------------------------------------------------- diff --git a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java index 6760bc2..3df3dbf 100644 --- a/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java +++ b/deltaspike/modules/proxy/impl-asm5/src/main/java/org/apache/deltaspike/proxy/impl/invocation/AbstractManualInvocationHandler.java @@ -76,39 +76,59 @@ public abstract class AbstractManualInvocationHandler implements InvocationHandl protected List<Interceptor<?>> resolveInterceptors(Object instance, Method method) { - Annotation[] interceptorBindings = extractInterceptorBindings(instance, method); + BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager(); + + Annotation[] interceptorBindings = extractInterceptorBindings(beanManager, instance, method); if (interceptorBindings.length > 0) { - BeanManager beanManager = BeanManagerProvider.getInstance().getBeanManager(); return beanManager.resolveInterceptors(InterceptionType.AROUND_INVOKE, interceptorBindings); } return null; } - // TODO stereotypes - protected Annotation[] extractInterceptorBindings(Object instance, Method method) + protected Annotation[] extractInterceptorBindings(BeanManager beanManager, Object instance, Method method) { ArrayList<Annotation> bindings = new ArrayList<Annotation>(); - for (Annotation annotation : instance.getClass().getDeclaredAnnotations()) + addInterceptorBindings(beanManager, bindings, instance.getClass().getDeclaredAnnotations()); + addInterceptorBindings(beanManager, bindings, method.getDeclaredAnnotations()); + + return bindings.toArray(new Annotation[bindings.size()]); + } + + protected void addInterceptorBindings(BeanManager beanManager, ArrayList<Annotation> bindings, + Annotation[] declaredAnnotations) + { + for (Annotation annotation : declaredAnnotations) { - if (annotation.annotationType().isAnnotationPresent(InterceptorBinding.class) - && !bindings.contains(annotation)) + if (bindings.contains(annotation)) { - bindings.add(annotation); + continue; } - } - - for (Annotation annotation : method.getDeclaredAnnotations()) - { - if (annotation.annotationType().isAnnotationPresent(InterceptorBinding.class) - && !bindings.contains(annotation)) + + Class<? extends Annotation> annotationType = annotation.annotationType(); + + if (annotationType.isAnnotationPresent(InterceptorBinding.class)) { bindings.add(annotation); } - } + + if (beanManager.isStereotype(annotationType)) + { + for (Annotation subAnnotation : annotationType.getDeclaredAnnotations()) + { + if (bindings.contains(subAnnotation)) + { + continue; + } - return bindings.toArray(new Annotation[bindings.size()]); + if (subAnnotation.annotationType().isAnnotationPresent(InterceptorBinding.class)) + { + bindings.add(subAnnotation); + } + } + } + } } }
