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()); - } - */ - } }