From 44cae6b2ee102496cfa3a0e4abe76a551da66134 Mon Sep 17 00:00:00 2001
From: Ben Alex
Date: Fri, 17 Nov 2006 02:17:45 +0000
Subject: [PATCH] SEC-274: Correctly handle bridge methods, using
AnnotationUtils when on classpath.
---
.../SecurityAnnotationAttributes.java | 19 ++-
.../SecurityAnnotationAttributesTests.java | 128 ++++++++++--------
2 files changed, 85 insertions(+), 62 deletions(-)
diff --git a/core-tiger/src/main/java/org/acegisecurity/annotation/SecurityAnnotationAttributes.java b/core-tiger/src/main/java/org/acegisecurity/annotation/SecurityAnnotationAttributes.java
index 5afea13e08..96fbd88bf5 100644
--- a/core-tiger/src/main/java/org/acegisecurity/annotation/SecurityAnnotationAttributes.java
+++ b/core-tiger/src/main/java/org/acegisecurity/annotation/SecurityAnnotationAttributes.java
@@ -12,13 +12,14 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.acegisecurity.annotation;
import org.acegisecurity.SecurityConfig;
import org.springframework.metadata.Attributes;
+import org.springframework.util.ClassUtils;
+
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@@ -43,6 +44,8 @@ import java.util.Set;
* </bean>
* These security annotations are similiar to the Commons Attributes approach, however they are using Java 5
* language-level metadata support.
+ * This class should be used with Spring 2.0 or above, as it relies upon utility classes in Spring 2.0 for
+ * correct introspection of annotations on bridge methods.
*
* @author Mark St.Godard
* @version $Id$
@@ -96,7 +99,19 @@ public class SecurityAnnotationAttributes implements Attributes {
public Collection getAttributes(Method method) {
Set attributes = new HashSet();
- for (Annotation annotation : method.getAnnotations()) {
+ Annotation[] annotations = null;
+
+ // Use AnnotationUtils if in classpath (ie Spring 1.2.9+ deployment)
+ try {
+ Class clazz = ClassUtils.forName("org.springframework.core.annotation.AnnotationUtils");
+ Method m = clazz.getMethod("getAnnotations", new Class[] {Method.class});
+ annotations = (Annotation[]) m.invoke(null, new Object[] {method});
+ } catch (Exception ex) {
+ // Fallback to manual retrieval if no AnnotationUtils available
+ annotations = method.getAnnotations();
+ }
+
+ for (Annotation annotation : annotations) {
// check for Secured annotations
if (annotation instanceof Secured) {
Secured attr = (Secured) annotation;
diff --git a/core-tiger/src/test/java/org/acegisecurity/annotation/SecurityAnnotationAttributesTests.java b/core-tiger/src/test/java/org/acegisecurity/annotation/SecurityAnnotationAttributesTests.java
index 2cf119d5c1..7a0ff5d42c 100644
--- a/core-tiger/src/test/java/org/acegisecurity/annotation/SecurityAnnotationAttributesTests.java
+++ b/core-tiger/src/test/java/org/acegisecurity/annotation/SecurityAnnotationAttributesTests.java
@@ -12,20 +12,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-
package org.acegisecurity.annotation;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
-import java.util.Collection;
-
import junit.framework.TestCase;
import org.acegisecurity.SecurityConfig;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+
import org.springframework.metadata.Attributes;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import java.util.Collection;
+
/**
* Tests for {@link org.acegisecurity.annotation.SecurityAnnotationAttributes}
@@ -47,6 +49,67 @@ public class SecurityAnnotationAttributesTests extends TestCase {
this.attributes = new SecurityAnnotationAttributes();
}
+ public void testGenericsSuperclassDeclarationsAreIncludedWhenSubclassesOverride() {
+ Method method = null;
+
+ try {
+ method = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] {Department.class});
+ } catch (NoSuchMethodException unexpected) {
+ fail("Should be a superMethod called 'someUserMethod3' on class!");
+ }
+
+ Collection attrs = this.attributes.getAttributes(method);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("attrs: ");
+ logger.debug(attrs);
+ }
+
+ assertNotNull(attrs);
+
+ // expect 1 attribute
+ assertTrue("Did not find 1 attribute", attrs.size() == 1);
+
+ // should have 1 SecurityConfig
+ for (Object obj : attrs) {
+ assertTrue(obj instanceof SecurityConfig);
+
+ SecurityConfig sc = (SecurityConfig) obj;
+ assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
+ }
+
+ Method superMethod = null;
+
+ try {
+ superMethod = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[] {Entity.class});
+ } catch (NoSuchMethodException unexpected) {
+ fail("Should be a superMethod called 'someUserMethod3' on class!");
+ }
+
+ System.out.println(superMethod);
+
+ Collection superAttrs = this.attributes.getAttributes(superMethod);
+
+ if (logger.isDebugEnabled()) {
+ logger.debug("superAttrs: ");
+ logger.debug(superAttrs);
+ }
+
+ assertNotNull(superAttrs);
+
+ // TODO: Enable this part of the test once we can build against Spring 2.0+ and above only (SEC-274)
+ /*
+ // expect 1 attribute
+ assertTrue("Did not find 1 attribute", superAttrs.size() == 1);
+ // should have 1 SecurityConfig
+ for (Object obj : superAttrs) {
+ assertTrue(obj instanceof SecurityConfig);
+ SecurityConfig sc = (SecurityConfig) obj;
+ assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
+ }
+ */
+ }
+
public void testGetAttributesClass() {
Collection attrs = this.attributes.getAttributes(BusinessService.class);
@@ -134,59 +197,4 @@ public class SecurityAnnotationAttributesTests extends TestCase {
fail("Unsupported method should have thrown an exception!");
} catch (UnsupportedOperationException expected) {}
}
-
- public void testGenericsSuperclassDeclarationsAreIncludedWhenSubclassesOverride() {
-
- Method method = null;
- try {
- method = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[]{Department.class});
- } catch (NoSuchMethodException unexpected) {
- fail("Should be a superMethod called 'someUserMethod3' on class!");
- }
- Collection attrs = this.attributes.getAttributes(method);
-
- if (logger.isDebugEnabled()) {
- logger.debug("attrs: ");
- logger.debug(attrs);
- }
- assertNotNull(attrs);
-
- // expect 1 attribute
- assertTrue("Did not find 1 attribute", attrs.size() == 1);
-
- // should have 1 SecurityConfig
- for (Object obj : attrs) {
- assertTrue(obj instanceof SecurityConfig);
- SecurityConfig sc = (SecurityConfig) obj;
- assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
- }
-
- Method superMethod = null;
- try {
- superMethod = DepartmentServiceImpl.class.getMethod("someUserMethod3", new Class[]{Entity.class});
- } catch (NoSuchMethodException unexpected) {
- fail("Should be a superMethod called 'someUserMethod3' on class!");
- }
- System.out.println(superMethod);
- Collection superAttrs = this.attributes.getAttributes(superMethod);
-
- if (logger.isDebugEnabled()) {
- logger.debug("superAttrs: ");
- logger.debug(superAttrs);
- }
- assertNotNull(superAttrs);
-
- // TODO: Resolve bridge method bug as reported in SEC-274
- /*
- // expect 1 attribute
- assertTrue("Did not find 1 attribute", superAttrs.size() == 1);
-
- // should have 1 SecurityConfig
- for (Object obj : superAttrs) {
- assertTrue(obj instanceof SecurityConfig);
- SecurityConfig sc = (SecurityConfig) obj;
- assertEquals("Found an incorrect role", "ROLE_ADMIN", sc.getAttribute());
- }
- */
- }
}