Browse Source

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

Ben Alex 21 năm trước cách đây
mục cha
commit
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