Ver Fonte

Refactor MethodDefinitionMap to use Method, not MethodInvocation. Refactor AbstractSecurityInterceptor to not force use of Throwable. Move AOP Alliance based MethodSecurityInterceptor to separate package.

Ben Alex há 21 anos atrás
pai
commit
992cf44b36
20 ficheiros alterados com 229 adições e 211 exclusões
  1. 47 56
      core/src/main/java/org/acegisecurity/intercept/AbstractSecurityInterceptor.java
  2. 53 0
      core/src/main/java/org/acegisecurity/intercept/InterceptorStatusToken.java
  3. 0 50
      core/src/main/java/org/acegisecurity/intercept/SecurityInterceptorCallback.java
  4. 49 16
      core/src/main/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSource.java
  5. 4 7
      core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionAttributes.java
  6. 12 14
      core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionMap.java
  7. 1 2
      core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSource.java
  8. 4 2
      core/src/main/java/org/acegisecurity/intercept/method/aopalliance/MethodDefinitionSourceAdvisor.java
  9. 19 10
      core/src/main/java/org/acegisecurity/intercept/method/aopalliance/MethodSecurityInterceptor.java
  10. 6 0
      core/src/main/java/org/acegisecurity/intercept/method/aopalliance/package.html
  11. 2 2
      core/src/main/java/org/acegisecurity/intercept/method/package.html
  12. 9 11
      core/src/main/java/org/acegisecurity/intercept/web/FilterSecurityInterceptor.java
  13. 1 1
      core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.java
  14. 2 2
      core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.java
  15. 3 1
      core/src/test/java/org/acegisecurity/intercept/method/aopalliance/MethodDefinitionSourceAdvisorTests.java
  16. 10 30
      core/src/test/java/org/acegisecurity/intercept/method/aopalliance/MethodSecurityInterceptorTests.java
  17. 1 1
      samples/attributes/src/applicationContext.xml
  18. 2 2
      samples/contacts/etc/ca/applicationContext.xml
  19. 2 2
      samples/contacts/etc/cas/applicationContext.xml
  20. 2 2
      samples/contacts/etc/filter/applicationContext.xml

+ 47 - 56
core/src/main/java/org/acegisecurity/intercept/AbstractSecurityInterceptor.java

@@ -76,8 +76,16 @@ import java.util.Set;
  * Perform any run-as replacement via the configured {@link RunAsManager}.
  * </li>
  * <li>
- * Perform a callback to the {@link SecurityInterceptorCallback}, which will
- * actually proceed with executing the object.
+ * Pass control back to the concrete subclass, which will actually proceed with
+ * executing the object. A {@link InterceptorStatusToken} is returned so that
+ * after the subclass has finished proceeding with  execution of the object,
+ * its finally clause can ensure the <code>AbstractSecurityInterceptor</code>
+ * is re-called and tidies up correctly.
+ * </li>
+ * <li>
+ * The concrete subclass will re-call the
+ * <code>AbstractSecurityInterceptor</code> via the {@link
+ * #afterInvocation(InterceptorStatusToken)} method.
  * </li>
  * <li>
  * If the <code>RunAsManager</code> replaced the <code>Authentication</code>
@@ -98,17 +106,20 @@ import java.util.Set;
  * object to false.
  * </li>
  * <li>
- * Perform a callback to the {@link SecurityInterceptorCallback}, which will
- * actually proceed with the invocation.
+ * As described above, the concrete subclass will be returned an
+ * <code>InterceptorStatusToken</code> which is subsequently re-presented to
+ * the <code>AbstractSecurityInterceptor</code> after the secure object has
+ * been executed. The <code>AbstractSecurityInterceptor</code> will take no
+ * further action when its {@link #afterInvocation(InterceptorStatusToken)} is
+ * called.
  * </li>
  * </ol>
  * 
  * </li>
  * <li>
- * Return the result from the <code>SecurityInterceptorCallback</code> to the
- * method that called {@link AbstractSecurityInterceptor#interceptor(Object,
- * SecurityInterceptorCallback)}. This is almost always a concrete subclass of
- * the <code>AbstractSecurityInterceptor</code>.
+ * Control again returns to the concrete subclass, which will return to the
+ * caller any result or exception that occurred when it proceeded with the
+ * execution of the secure object.
  * </li>
  * </ol>
  * </p>
@@ -226,37 +237,24 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean {
         }
     }
 
-    /**
-     * Does the work of authenticating and authorizing the request.
-     * 
-     * <P>
-     * Throws {@link net.sf.acegisecurity.AcegiSecurityException} and its
-     * subclasses.
-     * </p>
-     *
-     * @param object details of a secure object invocation
-     * @param callback the object that will complete the target secure object
-     *        invocation
-     *
-     * @return The value that was returned by the
-     *         <code>SecurityInterceptorCallback</code>
-     *
-     * @throws Throwable if any error occurs during the
-     *         <code>SecurityInterceptorCallback</code>
-     * @throws IllegalArgumentException if a required argument was missing or
-     *         invalid
-     * @throws AuthenticationCredentialsNotFoundException if the
-     *         <code>ContextHolder</code> is not populated with a valid
-     *         <code>SecureContext</code>
-     */
-    public Object interceptor(Object object,
-        SecurityInterceptorCallback callback) throws Throwable {
-        if (object == null) {
-            throw new IllegalArgumentException("Object was null");
+    protected void afterInvocation(InterceptorStatusToken token) {
+        if (token == null) {
+            return;
+        }
+
+        if (logger.isDebugEnabled()) {
+            logger.debug("Reverting to original Authentication: "
+                + token.getAuthenticated().toString());
         }
 
-        if (callback == null) {
-            throw new IllegalArgumentException("Callback was null");
+        SecureContext secureContext = (SecureContext) ContextHolder.getContext();
+        secureContext.setAuthentication(token.getAuthenticated());
+        ContextHolder.setContext(secureContext);
+    }
+
+    protected InterceptorStatusToken beforeInvocation(Object object) {
+        if (object == null) {
+            throw new IllegalArgumentException("Object was null");
         }
 
         if (!this.obtainObjectDefinitionSource().supports(object.getClass())) {
@@ -294,7 +292,11 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean {
             Authentication authenticated = this.authenticationManager
                 .authenticate(context.getAuthentication());
             authenticated.setAuthenticated(true);
-            logger.debug("Authenticated: " + authenticated.toString());
+
+            if (logger.isDebugEnabled()) {
+                logger.debug("Authenticated: " + authenticated.toString());
+            }
+
             context.setAuthentication(authenticated);
             ContextHolder.setContext((Context) context);
 
@@ -315,31 +317,20 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean {
                         "RunAsManager did not change Authentication object");
                 }
 
-                return callback.proceedWithObject(object);
+                return null; // no further work post-invocation
             } else {
                 if (logger.isDebugEnabled()) {
                     logger.debug("Switching to RunAs Authentication: "
                         + runAs.toString());
                 }
 
-                SecureContext origSecureContext = null;
+                context.setAuthentication(runAs);
+                ContextHolder.setContext((Context) context);
 
-                try {
-                    origSecureContext = (SecureContext) ContextHolder
-                        .getContext();
-                    context.setAuthentication(runAs);
-                    ContextHolder.setContext((Context) context);
+                InterceptorStatusToken token = new InterceptorStatusToken();
+                token.setAuthenticated(authenticated);
 
-                    return callback.proceedWithObject(object);
-                } finally {
-                    if (logger.isDebugEnabled()) {
-                        logger.debug("Reverting to original Authentication: "
-                            + authenticated.toString());
-                    }
-
-                    origSecureContext.setAuthentication(authenticated);
-                    ContextHolder.setContext(origSecureContext);
-                }
+                return token; // revert to token.Authenticated post-invocation
             }
         } else {
             if (logger.isDebugEnabled()) {
@@ -365,7 +356,7 @@ public abstract class AbstractSecurityInterceptor implements InitializingBean {
                 }
             }
 
-            return callback.proceedWithObject(object);
+            return null; // no further work post-invocation
         }
     }
 }

+ 53 - 0
core/src/main/java/org/acegisecurity/intercept/InterceptorStatusToken.java

@@ -0,0 +1,53 @@
+/* Copyright 2004 Acegi Technology Pty Limited
+ *
+ * Licensed 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 net.sf.acegisecurity.intercept;
+
+import net.sf.acegisecurity.Authentication;
+
+
+/**
+ * A return object received by {@link AbstractSecurityInterceptor} subclasses.
+ * 
+ * <P>
+ * This class reflects the status of the security interception, so that the
+ * final call to <code>AbstractSecurityInterceptor</code> can tidy up
+ * correctly.
+ * </p>
+ * 
+ * <P>
+ * Whilst this class currently only wraps a single object, it has been modelled
+ * as a class so that future changes to the operation of
+ * <code>AbstractSecurityInterceptor</code> are abstracted from subclasses.
+ * </p>
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class InterceptorStatusToken {
+    //~ Instance fields ========================================================
+
+    private Authentication authenticated;
+
+    //~ Methods ================================================================
+
+    public void setAuthenticated(Authentication authenticated) {
+        this.authenticated = authenticated;
+    }
+
+    public Authentication getAuthenticated() {
+        return authenticated;
+    }
+}

+ 0 - 50
core/src/main/java/org/acegisecurity/intercept/SecurityInterceptorCallback.java

@@ -1,50 +0,0 @@
-/* Copyright 2004 Acegi Technology Pty Limited
- *
- * Licensed 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 net.sf.acegisecurity.intercept;
-
-/**
- * Allows the {@link AbstractSecurityInterceptor} to continue the secure object
- * invocation at the appropriate time.
- * 
- * <P>
- * Concrete <code>AbstractSecurityInterceptor</code> subclasses are required to
- * provide a <code>SecurityInterceptorCallback</code>. This is called by the
- * <code>AbstractSecurityInterceptor</code> at the exact time the secure
- * object should have its processing continued. The exact way processing is
- * continued is specific to the type of secure object. For example, it may
- * involve proceeding with a method invocation, servicing a request, or
- * continuing a filter chain.
- * </p>
- * 
- * <P>
- * The result from processing the secure object should be returned to the
- * <code>AbstractSecurityInterceptor</code>, which in turn will ultimately
- * return it to the calling class.
- * </p>
- *
- * @author Ben Alex
- * @version $Id$
- */
-public interface SecurityInterceptorCallback {
-    //~ Methods ================================================================
-
-    /**
-     * Continues to process the secured object.
-     *
-     * @return the result (if any) from calling the secured object
-     */
-    public Object proceedWithObject(Object object) throws Throwable;
-}

+ 49 - 16
core/src/main/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSource.java

@@ -22,6 +22,11 @@ import org.aopalliance.intercept.MethodInvocation;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.reflect.CodeSignature;
+
+import java.lang.reflect.Method;
+
 
 /**
  * Abstract implementation of <Code>MethodDefinitionSource</code>.
@@ -39,26 +44,55 @@ public abstract class AbstractMethodDefinitionSource
 
     public ConfigAttributeDefinition getAttributes(Object object)
         throws IllegalArgumentException {
-        if ((object == null) || !this.supports(object.getClass())) {
-            throw new IllegalArgumentException(
-                "Object must be a MethodInvocation");
+        if (object == null) {
+            throw new IllegalArgumentException("Object cannot be null");
+        }
+
+        if (object instanceof MethodInvocation) {
+            return this.lookupAttributes(((MethodInvocation) object).getMethod());
+        }
+
+        if (object instanceof JoinPoint) {
+            JoinPoint jp = (JoinPoint) object;
+            Class targetClazz = jp.getTarget().getClass();
+            String targetMethodName = jp.getStaticPart().getSignature().getName();
+            Class[] types = ((CodeSignature) jp.getStaticPart().getSignature())
+                .getParameterTypes();
+
+            if (logger.isDebugEnabled()) {
+                logger.debug("Target Class: " + targetClazz);
+                logger.debug("Target Method Name: " + targetMethodName);
+
+                for (int i = 0; i < types.length; i++) {
+                    if (logger.isDebugEnabled()) {
+                        logger.debug("Target Method Arg #" + i + ": "
+                            + types[i]);
+                    }
+                }
+            }
+
+            try {
+                return this.lookupAttributes(targetClazz.getMethod(
+                        targetMethodName, types));
+            } catch (NoSuchMethodException nsme) {
+                throw new IllegalArgumentException(
+                    "Could not obtain target method from JoinPoint: " + jp);
+            }
         }
 
-        return this.lookupAttributes((MethodInvocation) object);
+        throw new IllegalArgumentException(
+            "Object must be a MethodInvocation or JoinPoint");
     }
 
     public boolean supports(Class clazz) {
-        if (MethodInvocation.class.isAssignableFrom(clazz)) {
-            return true;
-        } else {
-            return false;
-        }
+        return (MethodInvocation.class.isAssignableFrom(clazz)
+        || JoinPoint.class.isAssignableFrom(clazz));
     }
 
     /**
      * Performs the actual lookup of the relevant
      * <code>ConfigAttributeDefinition</code> for the specified
-     * <code>MethodInvocation</code>.
+     * <code>Method</code> which is subject of the method invocation.
      * 
      * <P>
      * Provided so subclasses need only to provide one basic method to properly
@@ -67,15 +101,14 @@ public abstract class AbstractMethodDefinitionSource
      * 
      * <p>
      * Returns <code>null</code> if there are no matching attributes for the
-     * method invocation.
+     * method.
      * </p>
      *
-     * @param mi the method being invoked for which configuration attributes
-     *        should be looked up
+     * @param method the method being invoked for which configuration
+     *        attributes should be looked up
      *
      * @return the <code>ConfigAttributeDefinition</code> that applies to the
-     *         specified <code>MethodInvocation</code>
+     *         specified <code>Method</code>
      */
-    protected abstract ConfigAttributeDefinition lookupAttributes(
-        MethodInvocation mi);
+    protected abstract ConfigAttributeDefinition lookupAttributes(Method method);
 }

+ 4 - 7
core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionAttributes.java

@@ -18,8 +18,6 @@ package net.sf.acegisecurity.intercept.method;
 import net.sf.acegisecurity.ConfigAttribute;
 import net.sf.acegisecurity.ConfigAttributeDefinition;
 
-import org.aopalliance.intercept.MethodInvocation;
-
 import org.springframework.metadata.Attributes;
 
 import java.lang.reflect.Method;
@@ -85,11 +83,10 @@ public class MethodDefinitionAttributes extends AbstractMethodDefinitionSource {
         return null;
     }
 
-    protected ConfigAttributeDefinition lookupAttributes(
-        MethodInvocation invocation) {
+    protected ConfigAttributeDefinition lookupAttributes(Method method) {
         ConfigAttributeDefinition definition = new ConfigAttributeDefinition();
 
-        Class interceptedClass = invocation.getMethod().getDeclaringClass();
+        Class interceptedClass = method.getDeclaringClass();
 
         // add the class level attributes for the implementing class
         addClassAttributes(definition, interceptedClass);
@@ -98,10 +95,10 @@ public class MethodDefinitionAttributes extends AbstractMethodDefinitionSource {
         addClassAttributes(definition, interceptedClass.getInterfaces());
 
         // add the method level attributes for the implemented method
-        addMethodAttributes(definition, invocation.getMethod());
+        addMethodAttributes(definition, method);
 
         // add the method level attributes for the implemented intreface methods
-        addInterfaceMethodAttributes(definition, invocation.getMethod());
+        addInterfaceMethodAttributes(definition, method);
 
         if (definition.size() == 0) {
             return null;

+ 12 - 14
core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionMap.java

@@ -38,9 +38,9 @@ import java.util.Map;
  * 
  * <p>
  * For consistency with {@link MethodDefinitionAttributes} as well as support
- * for {@link MethodDefinitionSourceAdvisor}, this implementation will return
- * a <code>ConfigAttributeDefinition</code> containing all configuration
- * attributes defined against:
+ * for <code>MethodDefinitionSourceAdvisor</code>, this implementation will
+ * return a <code>ConfigAttributeDefinition</code> containing all
+ * configuration attributes defined against:
  * 
  * <ul>
  * <li>
@@ -83,8 +83,8 @@ public class MethodDefinitionMap extends AbstractMethodDefinitionSource {
     /**
      * Obtains the configuration attributes explicitly defined against this
      * bean. This method will not return implicit configuration attributes
-     * that may be returned by {@link #lookupAttributes(MethodInvocation)} as
-     * it does not have access to a method invocation at this time.
+     * that may be returned by {@link #lookupAttributes(Method)} as it does
+     * not have access to a method invocation at this time.
      *
      * @return the attributes explicitly defined against this bean
      */
@@ -95,9 +95,8 @@ public class MethodDefinitionMap extends AbstractMethodDefinitionSource {
     /**
      * Obtains the number of configuration attributes explicitly defined
      * against this bean. This method will not return implicit configuration
-     * attributes that may be returned by {@link
-     * #lookupAttributes(MethodInvocation)} as it does not have access to a
-     * method invocation at this time.
+     * attributes that may be returned by {@link #lookupAttributes(Method)} as
+     * it does not have access to a method invocation at this time.
      *
      * @return the number of configuration attributes explicitly defined
      *         against this bean
@@ -209,25 +208,24 @@ public class MethodDefinitionMap extends AbstractMethodDefinitionSource {
         }
     }
 
-    protected ConfigAttributeDefinition lookupAttributes(MethodInvocation mi) {
+    protected ConfigAttributeDefinition lookupAttributes(Method method) {
         ConfigAttributeDefinition definition = new ConfigAttributeDefinition();
 
         // Add attributes explictly defined for this method invocation
         ConfigAttributeDefinition directlyAssigned = (ConfigAttributeDefinition) this.methodMap
-            .get(mi.getMethod());
+            .get(method);
         merge(definition, directlyAssigned);
 
         // Add attributes explicitly defined for this method invocation's interfaces
-        Class[] interfaces = mi.getMethod().getDeclaringClass().getInterfaces();
+        Class[] interfaces = method.getDeclaringClass().getInterfaces();
 
         for (int i = 0; i < interfaces.length; i++) {
             Class clazz = interfaces[i];
 
             try {
                 // Look for the method on the current interface
-                Method interfaceMethod = clazz.getDeclaredMethod(mi.getMethod()
-                                                                   .getName(),
-                        mi.getMethod().getParameterTypes());
+                Method interfaceMethod = clazz.getDeclaredMethod(method.getName(),
+                        method.getParameterTypes());
                 ConfigAttributeDefinition interfaceAssigned = (ConfigAttributeDefinition) this.methodMap
                     .get(interfaceMethod);
                 merge(definition, interfaceAssigned);

+ 1 - 2
core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSource.java

@@ -20,8 +20,7 @@ import net.sf.acegisecurity.intercept.ObjectDefinitionSource;
 
 /**
  * Marker interface for <code>ObjectDefinitionSource</code> implementations
- * that are designed to perform lookups keyed on
- * <code>MethodInvocation</code>s.
+ * that are designed to perform lookups keyed on <code>Method</code>s.
  *
  * @author Ben Alex
  * @version $Id$

+ 4 - 2
core/src/main/java/org/acegisecurity/intercept/method/MethodDefinitionSourceAdvisor.java → core/src/main/java/org/acegisecurity/intercept/method/aopalliance/MethodDefinitionSourceAdvisor.java

@@ -13,7 +13,9 @@
  * limitations under the License.
  */
 
-package net.sf.acegisecurity.intercept.method;
+package net.sf.acegisecurity.intercept.method.aopalliance;
+
+import net.sf.acegisecurity.intercept.method.MethodDefinitionSource;
 
 import org.aopalliance.intercept.MethodInvocation;
 
@@ -46,7 +48,7 @@ import java.lang.reflect.Method;
  * <p>
  * Based on Spring's TransactionAttributeSourceAdvisor.
  * </p>
- * 
+ *
  * @author Ben Alex
  * @version $Id$
  */

+ 19 - 10
core/src/main/java/org/acegisecurity/intercept/method/MethodSecurityInterceptor.java → core/src/main/java/org/acegisecurity/intercept/method/aopalliance/MethodSecurityInterceptor.java

@@ -13,22 +13,26 @@
  * limitations under the License.
  */
 
-package net.sf.acegisecurity.intercept.method;
+package net.sf.acegisecurity.intercept.method.aopalliance;
 
 import net.sf.acegisecurity.intercept.AbstractSecurityInterceptor;
+import net.sf.acegisecurity.intercept.InterceptorStatusToken;
 import net.sf.acegisecurity.intercept.ObjectDefinitionSource;
-import net.sf.acegisecurity.intercept.SecurityInterceptorCallback;
+import net.sf.acegisecurity.intercept.method.MethodDefinitionSource;
 
 import org.aopalliance.intercept.MethodInterceptor;
 import org.aopalliance.intercept.MethodInvocation;
 
 
 /**
- * Provides security interception of method invocations.
+ * Provides security interception of AOP Alliance based method invocations.
  * 
  * <p>
  * The <code>ObjectDefinitionSource</code> required by this security
- * interceptor is of type {@link MethodDefinitionSource}.
+ * interceptor is of type {@link MethodDefinitionSource}. This is shared with
+ * the AspectJ based security interceptor
+ * (<code>AspectJSecurityInterceptor</code>), since both work with Java
+ * <code>Method</code>s.
  * </p>
  * 
  * <P>
@@ -39,7 +43,7 @@ import org.aopalliance.intercept.MethodInvocation;
  * @version $Id$
  */
 public class MethodSecurityInterceptor extends AbstractSecurityInterceptor
-    implements MethodInterceptor, SecurityInterceptorCallback {
+    implements MethodInterceptor {
     //~ Instance fields ========================================================
 
     private MethodDefinitionSource objectDefinitionSource;
@@ -79,14 +83,19 @@ public class MethodSecurityInterceptor extends AbstractSecurityInterceptor
      * @throws Throwable if any error occurs
      */
     public Object invoke(MethodInvocation mi) throws Throwable {
-        return super.interceptor(mi, this);
+        Object result;
+        InterceptorStatusToken token = super.beforeInvocation(mi);
+
+        try {
+            result = mi.proceed();
+        } finally {
+            super.afterInvocation(token);
+        }
+
+        return result;
     }
 
     public ObjectDefinitionSource obtainObjectDefinitionSource() {
         return this.objectDefinitionSource;
     }
-
-    public Object proceedWithObject(Object object) throws Throwable {
-        return ((MethodInvocation) object).proceed();
-    }
 }

+ 6 - 0
core/src/main/java/org/acegisecurity/intercept/method/aopalliance/package.html

@@ -0,0 +1,6 @@
+<html>
+<body>
+Enforces security for AOP Alliance <code>MethodInvocation</code>s, such as via
+Spring AOP.
+</body>
+</html>

+ 2 - 2
core/src/main/java/org/acegisecurity/intercept/method/package.html

@@ -1,6 +1,6 @@
 <html>
 <body>
-Enforces security for <code>MethodInvocation</code>s, such as via
-Spring AOP.
+Provides support objects for securing Java method invocations
+via different AOP libraries.
 </body>
 </html>

+ 9 - 11
core/src/main/java/org/acegisecurity/intercept/web/FilterSecurityInterceptor.java

@@ -16,8 +16,8 @@
 package net.sf.acegisecurity.intercept.web;
 
 import net.sf.acegisecurity.intercept.AbstractSecurityInterceptor;
+import net.sf.acegisecurity.intercept.InterceptorStatusToken;
 import net.sf.acegisecurity.intercept.ObjectDefinitionSource;
-import net.sf.acegisecurity.intercept.SecurityInterceptorCallback;
 
 
 /**
@@ -43,8 +43,7 @@ import net.sf.acegisecurity.intercept.SecurityInterceptorCallback;
  * @author Ben Alex
  * @version $Id$
  */
-public class FilterSecurityInterceptor extends AbstractSecurityInterceptor
-    implements SecurityInterceptorCallback {
+public class FilterSecurityInterceptor extends AbstractSecurityInterceptor {
     //~ Instance fields ========================================================
 
     private FilterInvocationDefinitionSource objectDefinitionSource;
@@ -75,17 +74,16 @@ public class FilterSecurityInterceptor extends AbstractSecurityInterceptor
     }
 
     public void invoke(FilterInvocation fi) throws Throwable {
-        super.interceptor(fi, this);
+        InterceptorStatusToken token = super.beforeInvocation(fi);
+
+        try {
+            fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+        } finally {
+            super.afterInvocation(token);
+        }
     }
 
     public ObjectDefinitionSource obtainObjectDefinitionSource() {
         return this.objectDefinitionSource;
     }
-
-    public Object proceedWithObject(Object object) throws Throwable {
-        FilterInvocation fi = (FilterInvocation) object;
-        fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
-
-        return null;
-    }
 }

+ 1 - 1
core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.java

@@ -246,7 +246,7 @@ public class MethodDefinitionAttributesTests extends TestCase {
             "attributes");
 
         p.setProperty(PREFIX + "securityInterceptor.class",
-            "net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor");
+            "net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor");
         p.setProperty(PREFIX + "securityInterceptor.authenticationManager(ref)",
             "authentication");
         p.setProperty(PREFIX + "securityInterceptor.accessDecisionManager(ref)",

+ 2 - 2
core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.java

@@ -18,7 +18,7 @@ package net.sf.acegisecurity.intercept.method;
 import net.sf.acegisecurity.ConfigAttributeDefinition;
 import net.sf.acegisecurity.SecurityConfig;
 
-import org.aopalliance.intercept.MethodInvocation;
+import java.lang.reflect.Method;
 
 import java.util.Iterator;
 import java.util.List;
@@ -82,7 +82,7 @@ public class MockMethodDefinitionSource extends AbstractMethodDefinitionSource {
         }
     }
 
-    protected ConfigAttributeDefinition lookupAttributes(MethodInvocation mi) {
+    protected ConfigAttributeDefinition lookupAttributes(Method method) {
         throw new UnsupportedOperationException("mock method not implemented");
     }
 }

+ 3 - 1
core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceAdvisorTests.java → core/src/test/java/org/acegisecurity/intercept/method/aopalliance/MethodDefinitionSourceAdvisorTests.java

@@ -13,11 +13,13 @@
  * limitations under the License.
  */
 
-package net.sf.acegisecurity.intercept.method;
+package net.sf.acegisecurity.intercept.method.aopalliance;
 
 import junit.framework.TestCase;
 
 import net.sf.acegisecurity.TargetObject;
+import net.sf.acegisecurity.intercept.method.MethodDefinitionMap;
+import net.sf.acegisecurity.intercept.method.MethodDefinitionSourceEditor;
 
 import org.springframework.aop.framework.AopConfigException;
 

+ 10 - 30
core/src/test/java/org/acegisecurity/intercept/method/MethodSecurityInterceptorTests.java → core/src/test/java/org/acegisecurity/intercept/method/aopalliance/MethodSecurityInterceptorTests.java

@@ -13,7 +13,7 @@
  * limitations under the License.
  */
 
-package net.sf.acegisecurity.intercept.method;
+package net.sf.acegisecurity.intercept.method.aopalliance;
 
 import junit.framework.TestCase;
 
@@ -28,21 +28,23 @@ import net.sf.acegisecurity.GrantedAuthorityImpl;
 import net.sf.acegisecurity.ITargetObject;
 import net.sf.acegisecurity.MockAccessDecisionManager;
 import net.sf.acegisecurity.MockAuthenticationManager;
+import net.sf.acegisecurity.MockMethodInvocation;
 import net.sf.acegisecurity.MockRunAsManager;
 import net.sf.acegisecurity.RunAsManager;
 import net.sf.acegisecurity.context.ContextHolder;
 import net.sf.acegisecurity.context.ContextImpl;
 import net.sf.acegisecurity.context.SecureContext;
 import net.sf.acegisecurity.context.SecureContextImpl;
-import net.sf.acegisecurity.intercept.SecurityInterceptorCallback;
+import net.sf.acegisecurity.intercept.method.AbstractMethodDefinitionSource;
+import net.sf.acegisecurity.intercept.method.MockMethodDefinitionSource;
 import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
 import net.sf.acegisecurity.runas.RunAsManagerImpl;
 
-import org.aopalliance.intercept.MethodInvocation;
-
 import org.springframework.beans.factory.support.DefaultListableBeanFactory;
 import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
 
+import java.lang.reflect.Method;
+
 import java.util.Iterator;
 import java.util.Properties;
 
@@ -250,25 +252,13 @@ public class MethodSecurityInterceptorTests extends TestCase {
         }
     }
 
-    public void testRejectsCallsWhenCallbackIsNull() throws Throwable {
-        MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor();
-
-        try {
-            interceptor.interceptor(new Object(), null);
-            fail("Should have thrown IllegalArgumentException");
-        } catch (IllegalArgumentException expected) {
-            assertEquals("Callback was null", expected.getMessage());
-        }
-    }
-
     public void testRejectsCallsWhenObjectDefinitionSourceDoesNotSupportObject()
         throws Throwable {
         MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor();
         interceptor.setObjectDefinitionSource(new MockObjectDefinitionSourceWhichOnlySupportsStrings());
 
         try {
-            interceptor.interceptor(new Integer(1),
-                new MockSecurityInterceptorCallback());
+            interceptor.invoke(new MockMethodInvocation());
             fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException expected) {
             assertTrue(expected.getMessage().startsWith("ObjectDefinitionSource does not support objects of type"));
@@ -279,7 +269,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
         MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor();
 
         try {
-            interceptor.interceptor(null, new MockSecurityInterceptorCallback());
+            interceptor.invoke(null);
             fail("Should have thrown IllegalArgumentException");
         } catch (IllegalArgumentException expected) {
             assertEquals("Object was null", expected.getMessage());
@@ -420,7 +410,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
             "net.sf.acegisecurity.MockRunAsManager");
 
         p.setProperty(PREFIX + "securityInterceptor.class",
-            "net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor");
+            "net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor");
         p.setProperty(PREFIX + "securityInterceptor.authenticationManager(ref)",
             "authentication");
         p.setProperty(PREFIX + "securityInterceptor.accessDecisionManager(ref)",
@@ -482,8 +472,7 @@ public class MethodSecurityInterceptorTests extends TestCase {
             }
         }
 
-        protected ConfigAttributeDefinition lookupAttributes(
-            MethodInvocation mi) {
+        protected ConfigAttributeDefinition lookupAttributes(Method method) {
             throw new UnsupportedOperationException(
                 "mock method not implemented");
         }
@@ -509,13 +498,4 @@ public class MethodSecurityInterceptorTests extends TestCase {
             return true;
         }
     }
-
-    private class MockSecurityInterceptorCallback
-        implements SecurityInterceptorCallback {
-        public Object proceedWithObject(Object object)
-            throws Throwable {
-            throw new UnsupportedOperationException(
-                "mock method not implemented");
-        }
-    }
 }

+ 1 - 1
samples/attributes/src/applicationContext.xml

@@ -65,7 +65,7 @@
 	</bean>
 
 	<!-- We don't validate config attributes, as it's unsupported by MethodDefinitionAttributes -->
-	<bean id="securityInterceptor" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
+	<bean id="securityInterceptor" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
     	<property name="validateConfigAttributes"><value>false</value></property>
     	<property name="authenticationManager"><ref local="authenticationManager"/></property>
     	<property name="accessDecisionManager"><ref local="accessDecisionManager"/></property>

+ 2 - 2
samples/contacts/etc/ca/applicationContext.xml

@@ -82,7 +82,7 @@
 
 	<!-- ===================== SECURITY DEFINITIONS ======================= -->
 	
-	<bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
+	<bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
     	<property name="authenticationManager"><ref local="authenticationManager"/></property>
     	<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
     	<property name="runAsManager"><ref local="runAsManager"/></property>
@@ -97,7 +97,7 @@
 	</bean>
 
 	<!-- We expect all callers of the backend object to hold the role ROLE_RUN_AS_SERVER -->
-	<bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
+	<bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
     	<property name="authenticationManager"><ref local="authenticationManager"/></property>
     	<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
     	<property name="runAsManager"><ref local="runAsManager"/></property>

+ 2 - 2
samples/contacts/etc/cas/applicationContext.xml

@@ -104,7 +104,7 @@
 
 	<!-- ===================== SECURITY DEFINITIONS ======================= -->
 	
-	<bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
+	<bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
     	<property name="authenticationManager"><ref local="authenticationManager"/></property>
     	<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
     	<property name="runAsManager"><ref local="runAsManager"/></property>
@@ -119,7 +119,7 @@
 	</bean>
 
 	<!-- We expect all callers of the backend object to hold the role ROLE_RUN_AS_SERVER -->
-	<bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
+	<bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
     	<property name="authenticationManager"><ref local="authenticationManager"/></property>
     	<property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
     	<property name="runAsManager"><ref local="runAsManager"/></property>

+ 2 - 2
samples/contacts/etc/filter/applicationContext.xml

@@ -93,7 +93,7 @@
 
    <!-- ===================== SECURITY DEFINITIONS ======================= -->
 
-   <bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
+   <bean id="publicContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
       <property name="authenticationManager"><ref local="authenticationManager"/></property>
       <property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
       <property name="runAsManager"><ref local="runAsManager"/></property>
@@ -108,7 +108,7 @@
    </bean>
 
    <!-- We expect all callers of the backend object to hold the role ROLE_RUN_AS_SERVER -->
-   <bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor">
+   <bean id="backendContactManagerSecurity" class="net.sf.acegisecurity.intercept.method.aopalliance.MethodSecurityInterceptor">
       <property name="authenticationManager"><ref local="authenticationManager"/></property>
       <property name="accessDecisionManager"><ref local="businessAccessDecisionManager"/></property>
       <property name="runAsManager"><ref local="runAsManager"/></property>