deltaspike-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gpetra...@apache.org
Subject deltaspike git commit: DELTASPIKE-828 improved cycle detection and tests for SecurityUtils#getAllAnnotations
Date Sat, 31 Jan 2015 20:41:01 GMT
Repository: deltaspike
Updated Branches:
  refs/heads/master f2a3ea4e1 -> 4604814f9


DELTASPIKE-828 improved cycle detection and tests for SecurityUtils#getAllAnnotations


Project: http://git-wip-us.apache.org/repos/asf/deltaspike/repo
Commit: http://git-wip-us.apache.org/repos/asf/deltaspike/commit/4604814f
Tree: http://git-wip-us.apache.org/repos/asf/deltaspike/tree/4604814f
Diff: http://git-wip-us.apache.org/repos/asf/deltaspike/diff/4604814f

Branch: refs/heads/master
Commit: 4604814f93e45cb7571b69eddb50ff1756592671
Parents: f2a3ea4
Author: gpetracek <gpetracek@apache.org>
Authored: Sat Jan 31 21:31:42 2015 +0100
Committer: gpetracek <gpetracek@apache.org>
Committed: Sat Jan 31 21:34:07 2015 +0100

----------------------------------------------------------------------
 .../deltaspike/core/util/AnnotationUtils.java   |   9 +-
 .../deltaspike/core/util/ReflectionUtils.java   | 114 ++++++++++++++-
 .../SecuredAnnotationAuthorizer.java            |   4 +-
 .../security/impl/util/SecurityUtils.java       |  27 ++--
 .../impl/authorization/util/Annotation1.java    |  35 +++++
 .../impl/authorization/util/Annotation2.java    |  34 +++++
 .../impl/authorization/util/Annotation3.java    |  35 +++++
 ...IndirectCycleWithAnnotationMemberValues.java |  26 ++++
 .../authorization/util/SecurityUtilsTest.java   |  18 ++-
 .../testcontrol/impl/mock/BeanCacheKey.java     | 146 +------------------
 10 files changed, 284 insertions(+), 164 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/AnnotationUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/AnnotationUtils.java
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/AnnotationUtils.java
index 0e3fbe3..d59a743 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/AnnotationUtils.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/AnnotationUtils.java
@@ -94,14 +94,7 @@ public abstract class AnnotationUtils
             }
 
             final Object annotationMemberValue;
-            try
-            {
-                annotationMemberValue = ReflectionUtils.invokeMethod(annotation, member,
Object.class, true);
-            }
-            catch (IllegalAccessException e)
-            {
-                throw ExceptionUtils.throwAsRuntimeException(e);
-            }
+            annotationMemberValue = ReflectionUtils.invokeMethod(annotation, member, Object.class,
true);
 
             final int arrayValue;
             if (annotationMemberValue.getClass().isArray())

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
index 60f10e1..b30f953 100644
--- a/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
+++ b/deltaspike/core/api/src/main/java/org/apache/deltaspike/core/util/ReflectionUtils.java
@@ -20,7 +20,9 @@
 package org.apache.deltaspike.core.util;
 
 import javax.enterprise.inject.Typed;
+import javax.enterprise.util.Nonbinding;
 import java.io.Serializable;
+import java.lang.annotation.Annotation;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Member;
@@ -30,6 +32,7 @@ import java.lang.reflect.ParameterizedType;
 import java.lang.reflect.Type;
 import java.lang.reflect.WildcardType;
 import java.security.AccessController;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
@@ -44,6 +47,8 @@ import org.apache.deltaspike.core.util.securitymanaged.SetAccessiblePrivilegedAc
 @Typed()
 public abstract class ReflectionUtils
 {
+    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+
     private ReflectionUtils()
     {
         // prevent instantiation
@@ -170,7 +175,7 @@ public abstract class ReflectionUtils
     public static <T> T invokeMethod(Object instance, 
                                      Method method, Class<T> expectedReturnType,
                                      boolean setAccessible,
-                                     Object... args) throws IllegalAccessException, IllegalArgumentException
+                                     Object... args)
     {
         if (setAccessible && !method.isAccessible())
         {
@@ -397,4 +402,111 @@ public abstract class ReflectionUtils
         Class<?> rawType = getRawType(type);
         return rawType != null && rawType.isPrimitive();
     }
+
+    public static int calculateHashCodeOfAnnotation(Annotation annotation, boolean ignoreNonbindingMembers)
+    {
+        Class annotationClass = annotation.annotationType();
+
+        if (annotationClass == null)
+        {
+            return calculateHashCodeOfType(annotation.annotationType());
+        }
+
+        // the hashCode of an Annotation is calculated solely via the hashCodes
+        // of it's members. If there are no members, it is 0.
+        // thus we first need to get the annotation-class hashCode
+        int hashCode = calculateHashCodeOfType(annotationClass);
+
+        // and now add the hashCode of all it's Nonbinding members
+        // the following algorithm is defined by the Annotation class definition
+        // see the JavaDoc for Annotation!
+        // we only change it so far that we skip evaluating @Nonbinding members
+        final Method[] members = annotationClass.getDeclaredMethods();
+
+        for (Method member : members)
+        {
+            if (ignoreNonbindingMembers && member.isAnnotationPresent(Nonbinding.class))
+            {
+                // ignore the non binding
+                continue;
+            }
+
+            // Member value
+            final Object object = invokeMethod(annotation, member, Object.class, true, EMPTY_OBJECT_ARRAY);
+            final int value;
+            if (object.getClass().isArray())
+            {
+                Class<?> type = object.getClass().getComponentType();
+                if (type.isPrimitive())
+                {
+                    if (Long.TYPE == type)
+                    {
+                        value = Arrays.hashCode((long[]) object);
+                    }
+                    else if (Integer.TYPE == type)
+                    {
+                        value = Arrays.hashCode((int[])object);
+                    }
+                    else if (Short.TYPE == type)
+                    {
+                        value = Arrays.hashCode((short[])object);
+                    }
+                    else if (Double.TYPE == type)
+                    {
+                        value = Arrays.hashCode((double[])object);
+                    }
+                    else if (Float.TYPE == type)
+                    {
+                        value = Arrays.hashCode((float[])object);
+                    }
+                    else if (Boolean.TYPE == type)
+                    {
+                        value = Arrays.hashCode((boolean[])object);
+                    }
+                    else if (Byte.TYPE == type)
+                    {
+                        value = Arrays.hashCode((byte[])object);
+                    }
+                    else if (Character.TYPE == type)
+                    {
+                        value = Arrays.hashCode((char[])object);
+                    }
+                    else
+                    {
+                        value = 0;
+                    }
+                }
+                else
+                {
+                    value = Arrays.hashCode((Object[])object);
+                }
+            }
+            else
+            {
+                value = object.hashCode();
+            }
+
+            hashCode = 29 * hashCode + value;
+            hashCode = 29 * hashCode + member.getName().hashCode();
+        }
+
+        return hashCode;
+    }
+
+    /**
+     * We need this method as some weird JVMs return 0 as hashCode for classes.
+     * In that case we return the hashCode of the String.
+     */
+    public static int calculateHashCodeOfType(Type type)
+    {
+        int typeHash = type.hashCode();
+        if (typeHash == 0 && type instanceof Class)
+        {
+            return ((Class)type).getName().hashCode();
+            // the type.toString() is always the same: "java.lang.Class@<hexid>"
+            // was: return type.toString().hashCode();
+        }
+
+        return typeHash;
+    }
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java
b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java
index edc30e0..6f004f4 100644
--- a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/authorization/SecuredAnnotationAuthorizer.java
@@ -85,9 +85,9 @@ public class SecuredAnnotationAuthorizer
         Method method = invocationContext.getMethod();
 
         result.addAll(SecurityUtils.getAllAnnotations(method.getAnnotations(),
-            new HashSet<Class<? extends Annotation>>()));
+            new HashSet<Integer>()));
         result.addAll(SecurityUtils.getAllAnnotations(method.getDeclaringClass().getAnnotations(),
-            new HashSet<Class<? extends Annotation>>()));
+            new HashSet<Integer>()));
 
         return result;
     }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/SecurityUtils.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/SecurityUtils.java
b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/SecurityUtils.java
index 2e06f3d..5f7db84 100644
--- a/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/SecurityUtils.java
+++ b/deltaspike/modules/security/impl/src/main/java/org/apache/deltaspike/security/impl/util/SecurityUtils.java
@@ -18,6 +18,7 @@
  */
 package org.apache.deltaspike.security.impl.util;
 
+import org.apache.deltaspike.core.util.ReflectionUtils;
 import org.apache.deltaspike.security.api.authorization.SecurityBindingType;
 import org.apache.deltaspike.security.api.authorization.SecurityParameterBinding;
 
@@ -72,7 +73,7 @@ public abstract class SecurityUtils
         }
 
         List<Annotation> result = getAllAnnotations(annotation.annotationType().getAnnotations(),
-            new HashSet<Class<? extends Annotation>>());
+            new HashSet<Integer>());
 
         for (Annotation foundAnnotation : result)
         {
@@ -87,7 +88,7 @@ public abstract class SecurityUtils
     public static Annotation resolveSecurityBindingType(Annotation annotation)
     {
         List<Annotation> result = getAllAnnotations(annotation.annotationType().getAnnotations(),
-            new HashSet<Class<? extends Annotation>>());
+            new HashSet<Integer>());
 
         for (Annotation foundAnnotation : result)
         {
@@ -108,7 +109,7 @@ public abstract class SecurityUtils
         }
 
         List<Annotation> result = getAllAnnotations(annotation.annotationType().getAnnotations(),
-            new HashSet<Class<? extends Annotation>>());
+            new HashSet<Integer>());
 
         for (Annotation foundAnnotation : result)
         {
@@ -120,8 +121,7 @@ public abstract class SecurityUtils
         return false;
     }
 
-    public static List<Annotation> getAllAnnotations(Annotation[] annotations,
-                                                     Set<Class<? extends Annotation>>
annotationPath)
+    public static List<Annotation> getAllAnnotations(Annotation[] annotations, Set<Integer>
annotationPath)
     {
         List<Annotation> result = new ArrayList<Annotation>();
 
@@ -134,15 +134,24 @@ public abstract class SecurityUtils
                 continue;
             }
 
-            result.add(annotation);
-
-            if (!annotationPath.contains(annotation.annotationType()))
+            int annotationHashCode = hashCodeOfAnnotation(annotation);
+            if (!annotationPath.contains(annotationHashCode))
             {
-                annotationPath.add(annotation.annotationType());
+                result.add(annotation);
+                annotationPath.add(annotationHashCode);
                 result.addAll(getAllAnnotations(annotation.annotationType().getAnnotations(),
annotationPath));
             }
         }
 
         return result;
     }
+
+    private static int hashCodeOfAnnotation(Annotation annotation)
+    {
+        //with using System#identityHashCode instead, we could detect the real instances
+        //-> that would lead to multiple entries in the result which look the same (same
type and members)
+
+        //to detect real cycles, nonbinding members aren't ignored here
+        return ReflectionUtils.calculateHashCodeOfAnnotation(annotation, false);
+    }
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation1.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation1.java
b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation1.java
new file mode 100644
index 0000000..b58528a
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation1.java
@@ -0,0 +1,35 @@
+/*
+ * 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.security.impl.authorization.util;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Retention(value = RUNTIME)
+@Target({TYPE, ANNOTATION_TYPE } )
+
+@Annotation1("1")
+public @interface Annotation1
+{
+    String value();
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation2.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation2.java
b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation2.java
new file mode 100644
index 0000000..7e58195
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation2.java
@@ -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.deltaspike.test.security.impl.authorization.util;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Retention(value = RUNTIME)
+@Target({TYPE, ANNOTATION_TYPE } )
+
+@Annotation1("2")
+public @interface Annotation2
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation3.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation3.java
b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation3.java
new file mode 100644
index 0000000..4b92f72
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/Annotation3.java
@@ -0,0 +1,35 @@
+/*
+ * 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.security.impl.authorization.util;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.ANNOTATION_TYPE;
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Retention(value = RUNTIME)
+@Target({TYPE, ANNOTATION_TYPE } )
+
+@Annotation1("3")
+@Annotation2
+public @interface Annotation3
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/IndirectCycleWithAnnotationMemberValues.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/IndirectCycleWithAnnotationMemberValues.java
b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/IndirectCycleWithAnnotationMemberValues.java
new file mode 100644
index 0000000..f15eb09
--- /dev/null
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/IndirectCycleWithAnnotationMemberValues.java
@@ -0,0 +1,26 @@
+/*
+ * 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.security.impl.authorization.util;
+
+@Annotation1("usage")
+@Annotation2
+@Annotation3
+public class IndirectCycleWithAnnotationMemberValues
+{
+}

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/SecurityUtilsTest.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/SecurityUtilsTest.java
b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/SecurityUtilsTest.java
index 99263b4..89f29fb 100644
--- a/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/SecurityUtilsTest.java
+++ b/deltaspike/modules/security/impl/src/test/java/org/apache/deltaspike/test/security/impl/authorization/util/SecurityUtilsTest.java
@@ -32,19 +32,29 @@ public class SecurityUtilsTest
     public void directCycleDetection()
     {
         List<Annotation> result = SecurityUtils.getAllAnnotations(
-            DirectCycle.class.getAnnotations(), new HashSet<Class<? extends Annotation>>());
+            DirectCycle.class.getAnnotations(), new HashSet<Integer>());
 
         Assert.assertNotNull(result);
-        Assert.assertEquals(2, result.size());
+        Assert.assertEquals(1, result.size());
     }
 
     @Test
     public void indirectCycleDetection()
     {
         List<Annotation> result = SecurityUtils.getAllAnnotations(
-            IndirectCycle.class.getAnnotations(), new HashSet<Class<? extends Annotation>>());
+            IndirectCycle.class.getAnnotations(), new HashSet<Integer>());
 
         Assert.assertNotNull(result);
-        Assert.assertEquals(4, result.size());
+        Assert.assertEquals(3, result.size());
+    }
+
+    @Test
+    public void indirectCycleDetection6()
+    {
+        List<Annotation> result = SecurityUtils.getAllAnnotations(
+            IndirectCycleWithAnnotationMemberValues.class.getAnnotations(), new HashSet<Integer>());
+
+        Assert.assertNotNull(result);
+        Assert.assertEquals(6, result.size());
     }
 }

http://git-wip-us.apache.org/repos/asf/deltaspike/blob/4604814f/deltaspike/modules/test-control/impl/src/main/java/org/apache/deltaspike/testcontrol/impl/mock/BeanCacheKey.java
----------------------------------------------------------------------
diff --git a/deltaspike/modules/test-control/impl/src/main/java/org/apache/deltaspike/testcontrol/impl/mock/BeanCacheKey.java
b/deltaspike/modules/test-control/impl/src/main/java/org/apache/deltaspike/testcontrol/impl/mock/BeanCacheKey.java
index 1b29cc1..c3b0840 100644
--- a/deltaspike/modules/test-control/impl/src/main/java/org/apache/deltaspike/testcontrol/impl/mock/BeanCacheKey.java
+++ b/deltaspike/modules/test-control/impl/src/main/java/org/apache/deltaspike/testcontrol/impl/mock/BeanCacheKey.java
@@ -18,6 +18,8 @@
  */
 package org.apache.deltaspike.testcontrol.impl.mock;
 
+import org.apache.deltaspike.core.util.ReflectionUtils;
+
 import javax.enterprise.util.Nonbinding;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Array;
@@ -29,7 +31,6 @@ import java.util.Comparator;
 //class from OWB
 public class BeanCacheKey
 {
-    private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
     private static final Comparator<Annotation> ANNOTATION_COMPARATOR = new AnnotationComparator();
 
     private final Type type;
@@ -128,28 +129,11 @@ public class BeanCacheKey
     }
 
     /**
-     * We need this method as some weird JVMs return 0 as hashCode for classes.
-     * In that case we return the hashCode of the String.
-     */
-    private int getTypeHashCode(Type type)
-    {
-        int typeHash = type.hashCode();
-        if (typeHash == 0 && type instanceof Class)
-        {
-            return ((Class)type).getName().hashCode();
-            // the type.toString() is always the same: "java.lang.Class@<hexid>"
-            // was: return type.toString().hashCode();
-        }
-
-        return typeHash;
-    }
-
-    /**
      * Compute the HashCode. This should be called only in the constructor.
      */
     private int computeHashCode()
     {
-        int computedHashCode = 31 * getTypeHashCode(type);
+        int computedHashCode = 31 * ReflectionUtils.calculateHashCodeOfType(type);
         if (qualifier != null)
         {
             computedHashCode = 31 * computedHashCode + getQualifierHashCode(qualifier);
@@ -169,92 +153,7 @@ public class BeanCacheKey
      */
     private int getQualifierHashCode(Annotation a)
     {
-        Class annotationClass = getAnnotationClass(a.getClass());
-
-        if (annotationClass == null)
-        {
-            return getTypeHashCode(a.getClass());
-        }
-
-        // the hashCode of an Annotation is calculated solely via the hashCodes
-        // of it's members. If there are no members, it is 0.
-        // thus we first need to get the annotation-class hashCode
-        int hashCode = getTypeHashCode(annotationClass);
-
-        // and now add the hashCode of all it's Nonbinding members
-        // the following algorithm is defined by the Annotation class definition
-        // see the JavaDoc for Annotation!
-        // we only change it so far that we skip evaluating @Nonbinding members
-        final Method[] members = annotationClass.getDeclaredMethods();
-
-        for (Method member : members)
-        {
-            if (member.isAnnotationPresent(Nonbinding.class))
-            {
-                // ignore the non binding
-                continue;
-            }
-
-            // Member value
-            final Object object = callMethod(a, member);
-            final int value;
-            if (object.getClass().isArray())
-            {
-                Class<?> type = object.getClass().getComponentType();
-                if (type.isPrimitive())
-                {
-                    if (Long.TYPE == type)
-                    {
-                        value = Arrays.hashCode((long[]) object);
-                    }
-                    else if (Integer.TYPE == type)
-                    {
-                        value = Arrays.hashCode((int[])object);
-                    }
-                    else if (Short.TYPE == type)
-                    {
-                        value = Arrays.hashCode((short[])object);
-                    }
-                    else if (Double.TYPE == type)
-                    {
-                        value = Arrays.hashCode((double[])object);
-                    }
-                    else if (Float.TYPE == type)
-                    {
-                        value = Arrays.hashCode((float[])object);
-                    }
-                    else if (Boolean.TYPE == type)
-                    {
-                        value = Arrays.hashCode((boolean[])object);
-                    }
-                    else if (Byte.TYPE == type)
-                    {
-                        value = Arrays.hashCode((byte[])object);
-                    }
-                    else if (Character.TYPE == type)
-                    {
-                        value = Arrays.hashCode((char[])object);
-                    }
-                    else
-                    {
-                        value = 0;
-                    }
-                }
-                else
-                {
-                    value = Arrays.hashCode((Object[])object);
-                }
-            }
-            else
-            {
-                value = object.hashCode();
-            }
-
-            hashCode = 29 * hashCode + value;
-            hashCode = 29 * hashCode + member.getName().hashCode();
-        }
-
-        return hashCode;
+        return ReflectionUtils.calculateHashCodeOfAnnotation(a, true);
     }
 
     /**
@@ -265,39 +164,6 @@ public class BeanCacheKey
         return ANNOTATION_COMPARATOR.compare(qualifier1, qualifier2) == 0;
     }
 
-    private static Class getAnnotationClass(Class a)
-    {
-        for (Class i : a.getInterfaces())
-        {
-            if (i.isAnnotation())
-            {
-                return i;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Helper method for calculating the hashCode of an annotation.
-     */
-    private static Object callMethod(Object instance, Method method)
-    {
-        try
-        {
-            if (!method.isAccessible())
-            {
-                method.setAccessible(true);
-            }
-
-            return method.invoke(instance, EMPTY_OBJECT_ARRAY);
-        }
-        catch (Exception e)
-        {
-            throw new RuntimeException("Exception in method call : " + method.getName(),
e);
-        }
-
-    }
-
     /**
      * for debugging ...
      */
@@ -365,8 +231,8 @@ public class BeanCacheKey
                     {
                         return c;
                     }
-                    final Object value1 = callMethod(annotation1, member1[i]);
-                    final Object value2 = callMethod(annotation2, member2[j]);
+                    final Object value1 = ReflectionUtils.invokeMethod(annotation1, member1[i],
Object.class, true);
+                    final Object value2 = ReflectionUtils.invokeMethod(annotation2, member2[j],
Object.class, true);
                     assert value1.getClass().equals(value2.getClass());
 
                     if (value1 instanceof Comparable)


Mime
View raw message