|
@@ -15,6 +15,7 @@
|
|
|
|
|
|
package net.sf.acegisecurity.intercept.method;
|
|
|
|
|
|
+import net.sf.acegisecurity.ConfigAttribute;
|
|
|
import net.sf.acegisecurity.ConfigAttributeDefinition;
|
|
|
|
|
|
import org.aopalliance.intercept.MethodInvocation;
|
|
@@ -34,6 +35,32 @@ import java.util.Map;
|
|
|
/**
|
|
|
* Stores a {@link ConfigAttributeDefinition} for each method signature defined
|
|
|
* in a bean context.
|
|
|
+ *
|
|
|
+ * <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:
|
|
|
+ *
|
|
|
+ * <ul>
|
|
|
+ * <li>
|
|
|
+ * The method-specific attributes defined for the intercepted method of the
|
|
|
+ * intercepted class.
|
|
|
+ * </li>
|
|
|
+ * <li>
|
|
|
+ * The method-specific attributes defined by any explicitly implemented
|
|
|
+ * interface if that interface contains a method signature matching that of
|
|
|
+ * the intercepted method.
|
|
|
+ * </li>
|
|
|
+ * </ul>
|
|
|
+ * </p>
|
|
|
+ *
|
|
|
+ * <p>
|
|
|
+ * In general you should therefore define the <b>interface method</b>s of your
|
|
|
+ * secure objects, not the implementations. For example, define
|
|
|
+ * <code>com.company.Foo.findAll=ROLE_TEST</code> but not
|
|
|
+ * <code>com.company.FooImpl.findAll=ROLE_TEST</code>.
|
|
|
+ * </p>
|
|
|
*
|
|
|
* @author Ben Alex
|
|
|
* @version $Id$
|
|
@@ -53,10 +80,28 @@ public class MethodDefinitionMap extends AbstractMethodDefinitionSource {
|
|
|
|
|
|
//~ Methods ================================================================
|
|
|
|
|
|
+ /**
|
|
|
+ * 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.
|
|
|
+ *
|
|
|
+ * @return the attributes explicitly defined against this bean
|
|
|
+ */
|
|
|
public Iterator getConfigAttributeDefinitions() {
|
|
|
return methodMap.values().iterator();
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 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.
|
|
|
+ *
|
|
|
+ * @return the number of configuration attributes explicitly defined
|
|
|
+ * against this bean
|
|
|
+ */
|
|
|
public int getMethodMapSize() {
|
|
|
return this.methodMap.size();
|
|
|
}
|
|
@@ -165,7 +210,38 @@ public class MethodDefinitionMap extends AbstractMethodDefinitionSource {
|
|
|
}
|
|
|
|
|
|
protected ConfigAttributeDefinition lookupAttributes(MethodInvocation mi) {
|
|
|
- return (ConfigAttributeDefinition) this.methodMap.get(mi.getMethod());
|
|
|
+ ConfigAttributeDefinition definition = new ConfigAttributeDefinition();
|
|
|
+
|
|
|
+ // Add attributes explictly defined for this method invocation
|
|
|
+ ConfigAttributeDefinition directlyAssigned = (ConfigAttributeDefinition) this.methodMap
|
|
|
+ .get(mi.getMethod());
|
|
|
+ merge(definition, directlyAssigned);
|
|
|
+
|
|
|
+ // Add attributes explicitly defined for this method invocation's interfaces
|
|
|
+ Class[] interfaces = mi.getMethod().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());
|
|
|
+ ConfigAttributeDefinition interfaceAssigned = (ConfigAttributeDefinition) this.methodMap
|
|
|
+ .get(interfaceMethod);
|
|
|
+ merge(definition, interfaceAssigned);
|
|
|
+ } catch (Exception e) {
|
|
|
+ // skip this interface
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Return null if empty, as per abstract superclass contract
|
|
|
+ if (definition.size() == 0) {
|
|
|
+ return null;
|
|
|
+ } else {
|
|
|
+ return definition;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -184,4 +260,17 @@ public class MethodDefinitionMap extends AbstractMethodDefinitionSource {
|
|
|
|| (mappedName.startsWith("*")
|
|
|
&& methodName.endsWith(mappedName.substring(1, mappedName.length())));
|
|
|
}
|
|
|
+
|
|
|
+ private void merge(ConfigAttributeDefinition definition,
|
|
|
+ ConfigAttributeDefinition toMerge) {
|
|
|
+ if (toMerge == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Iterator attribs = toMerge.getConfigAttributes();
|
|
|
+
|
|
|
+ while (attribs.hasNext()) {
|
|
|
+ definition.addConfigAttribute((ConfigAttribute) attribs.next());
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|