diff --git a/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodDefinitionSourceTests.java b/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodDefinitionSourceTests.java index 0621399dbb..3e0781583d 100644 --- a/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodDefinitionSourceTests.java +++ b/core/src/test/java/org/springframework/security/access/annotation/Jsr250MethodDefinitionSourceTests.java @@ -1,5 +1,6 @@ package org.springframework.security.access.annotation; +import static org.fest.assertions.Assertions.assertThat; import static org.junit.Assert.assertEquals; import java.util.Collection; @@ -11,6 +12,7 @@ import junit.framework.Assert; import org.junit.Test; import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.access.intercept.method.MockMethodInvocation; /** * @author Luke Taylor @@ -58,7 +60,87 @@ public class Jsr250MethodDefinitionSourceTests { assertEquals("ADMIN", accessAttributes.toArray()[0].toString()); } -//~ Inner Classes ====================================================================================================== + // JSR-250 Spec Tests + + /** + * Class-level annotations only affect the class they annotate and their members, that + * is, its methods and fields. They never affect a member declared by a superclass, + * even if it is not hidden or overridden by the class in question. + * @throws Exception + */ + @Test + public void classLevelAnnotationsOnlyAffectTheClassTheyAnnotateAndTheirMembers() throws Exception { + Child target = new Child(); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "notOverriden"); + + Collection accessAttributes = mds.getAttributes(mi); + assertThat(accessAttributes).isNull(); + } + + @Test + public void classLevelAnnotationsOnlyAffectTheClassTheyAnnotateAndTheirMembersOverriden() throws Exception { + Child target = new Child(); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "overriden"); + + Collection accessAttributes = mds.getAttributes(mi); + assertEquals(1, accessAttributes.size()); + assertEquals("DERIVED", accessAttributes.toArray()[0].toString()); + } + + @Test + public void classLevelAnnotationsImpactMemberLevel() throws Exception { + Child target = new Child(); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "defaults"); + + Collection accessAttributes = mds.getAttributes(mi); + assertEquals(1, accessAttributes.size()); + assertEquals("DERIVED", accessAttributes.toArray()[0].toString()); + } + + @Test + public void classLevelAnnotationsIgnoredByExplicitMemberAnnotation() throws Exception { + Child target = new Child(); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "explicitMethod"); + + Collection accessAttributes = mds.getAttributes(mi); + assertEquals(1, accessAttributes.size()); + assertEquals("EXPLICIT", accessAttributes.toArray()[0].toString()); + } + + /** + * The interfaces implemented by a class never contribute annotations to the class + * itself or any of its members. + * @throws Exception + */ + @Test + public void interfacesNeverContributeAnnotationsMethodLevel() throws Exception { + Parent target = new Parent(); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "interfaceMethod"); + + Collection accessAttributes = mds.getAttributes(mi); + assertThat(accessAttributes).isEmpty(); + } + + @Test + public void interfacesNeverContributeAnnotationsClassLevel() throws Exception { + Parent target = new Parent(); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "notOverriden"); + + Collection accessAttributes = mds.getAttributes(mi); + assertThat(accessAttributes).isEmpty(); + } + + @Test + public void annotationsOnOverriddenMemberIgnored() throws Exception { + Child target = new Child(); + MockMethodInvocation mi = new MockMethodInvocation(target, target.getClass(), "overridenIgnored"); + + Collection accessAttributes = mds.getAttributes(mi); + assertEquals(1, accessAttributes.size()); + assertEquals("DERIVED", accessAttributes.toArray()[0].toString()); + } + + //~ Inner Classes ====================================================================================================== public static class A { @@ -78,4 +160,29 @@ public class Jsr250MethodDefinitionSourceTests { @RolesAllowed("ADMIN") public void adminMethod() {} } + + // JSR-250 Spec + + @RolesAllowed("IPARENT") + interface IParent { + @RolesAllowed("INTERFACEMETHOD") + void interfaceMethod(); + } + + static class Parent implements IParent { + public void interfaceMethod() {} + public void notOverriden() {} + public void overriden() {} + @RolesAllowed("OVERRIDENIGNORED") + public void overridenIgnored() {} + } + + @RolesAllowed("DERIVED") + class Child extends Parent { + public void overriden() {} + public void overridenIgnored() {} + public void defaults() {} + @RolesAllowed("EXPLICIT") + public void explicitMethod() {} + } }