Author: struberg
Date: Sat Jan 12 10:31:03 2013
New Revision: 1432405

URL: http://svn.apache.org/viewvc?rev=1432405&view=rev
Log:
OWB-344 define rules for interceptor method overrides

Modified:
    
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java
    
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/InterceptorBeanBuilder.java

Modified: 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java?rev=1432405&r1=1432404&r2=1432405&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/AbstractBeanBuilder.java
 Sat Jan 12 10:31:03 2013
@@ -128,15 +128,15 @@ public abstract class AbstractBeanBuilde
     }
 
     /**
-     * @return the Type hierarchy in the order subclass first. Object.class is 
<b>not</b> included!
+     * @return the Type hierarchy in the order superclass first. Object.class 
is <b>not</b> included!
      */
-    protected List<Class> getClassHierarchy()
+    protected List<Class> getReverseClassHierarchy()
     {
         List<Class> hierarchy = new ArrayList<Class>();
         Class clazz = getBeanType();
         while (clazz != Object.class)
         {
-            hierarchy.add(clazz);
+            hierarchy.add(0, clazz);
             clazz = clazz.getSuperclass();
         }
 

Modified: 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/InterceptorBeanBuilder.java
URL: 
http://svn.apache.org/viewvc/openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/InterceptorBeanBuilder.java?rev=1432405&r1=1432404&r2=1432405&view=diff
==============================================================================
--- 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/InterceptorBeanBuilder.java
 (original)
+++ 
openwebbeans/trunk/webbeans-impl/src/main/java/org/apache/webbeans/component/creation/InterceptorBeanBuilder.java
 Sat Jan 12 10:31:03 2013
@@ -18,6 +18,8 @@
  */
 package org.apache.webbeans.component.creation;
 
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
 import javax.enterprise.context.Dependent;
 import javax.enterprise.inject.Produces;
 import javax.enterprise.inject.spi.AnnotatedMethod;
@@ -26,7 +28,10 @@ import javax.enterprise.inject.spi.Inter
 import javax.interceptor.AroundInvoke;
 
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
@@ -80,17 +85,29 @@ public abstract class InterceptorBeanBui
     }
 
     /**
-     * grab all methods which act as interceptors for the various
-     * {@link javax.enterprise.inject.spi.InterceptionType}s.
-     * This method will also check some rules, e.g. that there must not be
+     * <p>Grab all methods which act as interceptors for the various
+     * {@link javax.enterprise.inject.spi.InterceptionType}s.</p>
+     *
+     * <p>This method will also check some rules, e.g. that there must not be
      * more than a single {@link javax.interceptor.AroundInvoke} method
-     * on a class.
+     * on a class.</p>
+     *
+     * <p>For the interceptors where multiple are allowed, the following rules 
apply:
+     * <ul>
+     *     <li>Superclass methods first</li>
+     *     <li>Non-private methods override and derogates their superclass 
counterparts.</li>
+     *     <li>Private methods with the same signature stack (superclass 
first).</li>
+     *     <li>There must only be a single method for each InterceptorType in 
the same class.</li>
+     * </ul>
+     * </p>
      */
     protected void defineInterceptorMethods()
     {
-        List<Class> classHierarchy = getClassHierarchy();
+        List<Class> classHierarchy = getReverseClassHierarchy();
 
         AnnotatedMethod aroundInvokeMethod = null;
+        List<AnnotatedMethod> postConstructMethods = new 
ArrayList<AnnotatedMethod>();
+        List<AnnotatedMethod> preDestroyMethods = new 
ArrayList<AnnotatedMethod>();
 
         Set<AnnotatedMethod<? super T>> methods = getAnnotated().getMethods();
 
@@ -112,6 +129,19 @@ public abstract class InterceptorBeanBui
                         aroundInvokeMethod = m;
                     }
 
+                    // PostConstruct
+                    if (m.getAnnotation(PostConstruct.class) != null)
+                    {
+                        postConstructMethods.add(m); // add at last position
+                    }
+                    checkMethodOverrides(postConstructMethods, clazz, m);
+
+                    // PreDestroy
+                    if (m.getAnnotation(PreDestroy.class) != null)
+                    {
+                        preDestroyMethods.add(m); // add at last position
+                    }
+                    checkMethodOverrides(preDestroyMethods, clazz, m);
 
                 }
             }
@@ -131,5 +161,71 @@ public abstract class InterceptorBeanBui
         bean.setIntercepts(intercepts);
     }
 
+    /**
+     * Check if the given annotatedMethod overrides some previously defined 
interceptorMethods
+     * and remove them if non-private.
+     * This will also detect if there are multiple methods for the same 
InterceptionType
+     * in the same class
+     */
+    private void checkMethodOverrides(List<AnnotatedMethod> 
alreadyDefinedMethods, Class clazz, AnnotatedMethod annotatedMethod)
+    {
+        String methodName = null;
+        Class<?>[] methodParameterTypes = null;
+
+        Iterator<AnnotatedMethod> it = alreadyDefinedMethods.iterator();
+        while (it.hasNext())
+        {
+            AnnotatedMethod alreadyDefined = it.next();
+
+            if (methodName == null)
+            {
+                methodName = annotatedMethod.getJavaMember().getName();
+                methodParameterTypes = 
annotatedMethod.getJavaMember().getParameterTypes();
+            }
+
+            // check for same class -> Exception
+            if (alreadyDefined.getDeclaringType().getJavaClass() ==  clazz)
+            {
+                throw new WebBeansConfigurationException("Only one Interceptor 
of a certain type is allowed per class, but multiple found in class "
+                                                         + 
annotatedMethod.getDeclaringType().getJavaClass().getName()
+                                                         + " methods: " + 
annotatedMethod.getJavaMember().toString()
+                                                         + " and " + 
alreadyDefined.getJavaMember().toString());
+            }
+
+            // check method overrides
+            if 
(!Modifier.isPrivate(alreadyDefined.getJavaMember().getModifiers()))
+            {
+                // we only scan non-private methods, as private methods cannot 
get overridden.
+                if 
(methodName.equals(alreadyDefined.getJavaMember().getName()) &&
+                    methodParameterTypes.length == 
alreadyDefined.getJavaMember().getParameterTypes().length)
+                {
+                    boolean overridden = true;
+                    // same name and param length so we need to check if all 
the paramTypes are equal.
+                    if (methodParameterTypes.length > 0)
+                    {
+                        Class<?>[] otherParamTypes = 
alreadyDefined.getJavaMember().getParameterTypes();
+
+                        for (int i = 0; i < otherParamTypes.length; i++)
+                        {
+                            if 
(!otherParamTypes[i].equals(methodParameterTypes[i]))
+                            {
+                                overridden = false;
+                                break;
+                            }
+                        }
+                    }
+
+                    if (overridden)
+                    {
+                        // then we need to remove this method
+                        it.remove();
+                        continue;
+                    }
+                }
+            }
+        }
+
+    }
+
 
 }


Reply via email to