You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@deltaspike.apache.org by gp...@apache.org on 2015/01/31 21:41:01 UTC
deltaspike git commit: DELTASPIKE-828 improved cycle detection and
tests for SecurityUtils#getAllAnnotations
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 <gp...@apache.org>
Authored: Sat Jan 31 21:31:42 2015 +0100
Committer: gpetracek <gp...@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)