Переглянути джерело

Relaxed requirement so targetClass OR targetBean can be used (targetBean no longer requires targetClass to be specified as well).

Ben Alex 21 роки тому
батько
коміт
7e85bbc054

+ 37 - 40
core/src/main/java/org/acegisecurity/util/FilterToBeanProxy.java

@@ -49,8 +49,8 @@ import javax.servlet.ServletResponse;
  * </p>
  * 
  * <p>
- * To use this filter, it is necessary to specify the following filter
- * initialization parameters:
+ * To use this filter, it is necessary to specify <b>one</b> of the following
+ * filter initialization parameters:
  * </p>
  * 
  * <ul>
@@ -62,13 +62,12 @@ import javax.servlet.ServletResponse;
  * <code>ApplicationContext</code>.
  * </li>
  * <li>
- * <code>targetBean</code> (optional) indicates the bean name of the target
- * class. This parameter should be specified if there is more than one bean in
- * the <code>ApplicationContext</code> of the same type as defined by the
- * <code>targetClass</code> parameter.
+ * <code>targetBean</code> indicates the bean name of the target class.
  * </li>
  * </ul>
  * 
+ * If both initialization parameters are specified, <code>targetBean</code>
+ * takes priority.
  *
  * @author Ben Alex
  * @version $Id$
@@ -90,22 +89,6 @@ public class FilterToBeanProxy implements Filter {
     }
 
     public void init(FilterConfig filterConfig) throws ServletException {
-        String targetClassString = filterConfig.getInitParameter("targetClass");
-
-        if ((targetClassString == null) || "".equals(targetClassString)) {
-            throw new ServletException("targetClass must be specified");
-        }
-
-        Class targetClass;
-
-        try {
-            targetClass = Thread.currentThread().getContextClassLoader()
-                                .loadClass(targetClassString);
-        } catch (ClassNotFoundException ex) {
-            throw new ServletException("Class of type " + targetClassString
-                + " not found in classloader");
-        }
-
         String targetBean = filterConfig.getInitParameter("targetBean");
 
         if ("".equals(targetBean)) {
@@ -114,30 +97,44 @@ public class FilterToBeanProxy implements Filter {
 
         ApplicationContext ctx = this.getContext(filterConfig);
 
-        Map beans = ctx.getBeansOfType(targetClass, true, true);
-
-        if (beans.size() == 0) {
-            throw new ServletException(
-                "Bean context must contain at least one bean of type "
-                + targetClassString);
-        }
-
         String beanName = null;
 
-        if (targetBean == null) {
-            // Use first bean found
-            beanName = (String) beans.keySet().iterator().next();
+        if ((targetBean != null) && ctx.containsBean(targetBean)) {
+            beanName = targetBean;
+        } else if (targetBean != null) {
+            throw new ServletException("targetBean '" + targetBean
+                + "' not found in context");
         } else {
-            // Use the requested bean, providing it can be found
-            if (beans.containsKey(targetBean)) {
-                beanName = targetBean;
-            } else {
-                throw new ServletException("Bean with name '" + targetBean
-                    + "' cannot be found in bean context");
+            String targetClassString = filterConfig.getInitParameter(
+                    "targetClass");
+
+            if ((targetClassString == null) || "".equals(targetClassString)) {
+                throw new ServletException(
+                    "targetClass or targetBean must be specified");
             }
+
+            Class targetClass;
+
+            try {
+                targetClass = Thread.currentThread().getContextClassLoader()
+                                    .loadClass(targetClassString);
+            } catch (ClassNotFoundException ex) {
+                throw new ServletException("Class of type " + targetClassString
+                    + " not found in classloader");
+            }
+
+            Map beans = ctx.getBeansOfType(targetClass, true, true);
+
+            if (beans.size() == 0) {
+                throw new ServletException(
+                    "Bean context must contain at least one bean of type "
+                    + targetClassString);
+            }
+
+            beanName = (String) beans.keySet().iterator().next();
         }
 
-        Object object = beans.get(beanName);
+        Object object = ctx.getBean(beanName);
 
         if (!(object instanceof Filter)) {
             throw new ServletException("Bean '" + beanName

+ 8 - 12
core/src/test/java/org/acegisecurity/util/FilterToBeanProxyTests.java

@@ -78,10 +78,9 @@ public class FilterToBeanProxyTests extends TestCase {
         }
     }
 
-    public void testDetectsMissingTargetClass() throws Exception {
+    public void testDetectsNeitherPropertyBeingSet() throws Exception {
         // Setup our filter
         MockFilterConfig config = new MockFilterConfig();
-        config.setInitParmeter("targetBean", "mockFilter");
 
         FilterToBeanProxy filter = new MockFilterToBeanProxy(
                 "net/sf/acegisecurity/util/filtertest-valid.xml");
@@ -90,7 +89,8 @@ public class FilterToBeanProxyTests extends TestCase {
             filter.init(config);
             fail("Should have thrown ServletException");
         } catch (ServletException expected) {
-            assertEquals("targetClass must be specified", expected.getMessage());
+            assertEquals("targetClass or targetBean must be specified",
+                expected.getMessage());
         }
     }
 
@@ -116,8 +116,6 @@ public class FilterToBeanProxyTests extends TestCase {
         throws Exception {
         // Setup our filter
         MockFilterConfig config = new MockFilterConfig();
-        config.setInitParmeter("targetClass",
-            "net.sf.acegisecurity.util.MockFilter");
         config.setInitParmeter("targetBean", "WRONG_NAME");
 
         FilterToBeanProxy filter = new MockFilterToBeanProxy(
@@ -127,7 +125,7 @@ public class FilterToBeanProxyTests extends TestCase {
             filter.init(config);
             fail("Should have thrown ServletException");
         } catch (ServletException expected) {
-            assertEquals("Bean with name 'WRONG_NAME' cannot be found in bean context",
+            assertEquals("targetBean 'WRONG_NAME' not found in context",
                 expected.getMessage());
         }
     }
@@ -171,11 +169,11 @@ public class FilterToBeanProxyTests extends TestCase {
             chain);
     }
 
-    public void testNormalOperationWithDefault() throws Exception {
+    public void testNormalOperationWithSpecificBeanName()
+        throws Exception {
         // Setup our filter
         MockFilterConfig config = new MockFilterConfig();
-        config.setInitParmeter("targetClass",
-            "net.sf.acegisecurity.util.MockFilter");
+        config.setInitParmeter("targetBean", "mockFilter");
 
         // Setup our expectation that the filter chain will be invoked
         MockFilterChain chain = new MockFilterChain(true);
@@ -190,13 +188,11 @@ public class FilterToBeanProxyTests extends TestCase {
             chain);
     }
 
-    public void testNormalOperationWithSpecificBeanName()
-        throws Exception {
+    public void testNormalOperationWithTargetClass() throws Exception {
         // Setup our filter
         MockFilterConfig config = new MockFilterConfig();
         config.setInitParmeter("targetClass",
             "net.sf.acegisecurity.util.MockFilter");
-        config.setInitParmeter("targetBean", "mockFilter");
 
         // Setup our expectation that the filter chain will be invoked
         MockFilterChain chain = new MockFilterChain(true);

+ 8 - 10
docs/reference/src/index.xml

@@ -525,15 +525,13 @@
         delegate the <literal>Filter</literal>'s methods through to a bean
         which is obtained from the Spring application context. This enables
         the bean to benefit from the Spring application context lifecycle
-        support and configuration flexibility. The
+        support and configuration flexibility.
         <literal>FilterToBeanProxy</literal> only requires a single
-        initialization parameter, <literal>targetClass</literal>, which will
-        be used to identify the bean in the application context. In the
-        unlikely event there is more than one bean in the application context
-        that matches this class, the <literal>targetBean</literal>
-        initialization parameter should be used. This parameter simply
-        represents the name of the bean in the application context. Like
-        standard Spring web applications, the
+        initialization parameter, <literal>targetClass</literal> or
+        <literal>targetBean</literal>. The <literal>targetClass</literal>
+        parameter locates the first object in the application context of the
+        specified class, whilst <literal>targetBean</literal> locates the
+        object by bean name. Like standard Spring web applications, the
         <literal>FilterToBeanProxy</literal> accesses the application context
         via<literal>
         WebApplicationContextUtils.getWebApplicationContext(ServletContext)</literal>,
@@ -1569,8 +1567,8 @@ public boolean supports(Class clazz);</programlisting></para>
         standard authentication of web browser users, we recommend HTTP
         Session Authentication). The standard governing HTTP Basic
         Authentication is defined by RFC 1945, Section 11, and the
-        <literal>BasicProcessingFilter</literal> conforms with this RFC.
-        </para>
+        <literal>BasicProcessingFilter</literal> conforms with this
+        RFC.</para>
 
         <para>To implement HTTP Basic Authentication, it is necessary to add
         the following filter to <literal>web.xml</literal>, behind a