diff --git a/core/src/test/java/org/acegisecurity/MockFilterChain.java b/core/src/test/java/org/acegisecurity/MockFilterChain.java
new file mode 100644
index 0000000000..b2139bc19c
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockFilterChain.java
@@ -0,0 +1,39 @@
+/* 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;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+
+/**
+ * Mocks a FilterChain
but with no behaviour.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockFilterChain implements FilterChain {
+ //~ Methods ================================================================
+
+ public void doFilter(ServletRequest arg0, ServletResponse arg1)
+ throws IOException, ServletException {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/MockFilterConfig.java b/core/src/test/java/org/acegisecurity/MockFilterConfig.java
new file mode 100644
index 0000000000..ea36eb5644
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockFilterConfig.java
@@ -0,0 +1,64 @@
+/* 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;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockFilterConfig implements FilterConfig {
+ //~ Instance fields ========================================================
+
+ private Map map = new HashMap();
+
+ //~ Methods ================================================================
+
+ public String getFilterName() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String getInitParameter(String arg0) {
+ Object result = map.get(arg0);
+
+ if (result != null) {
+ return (String) result;
+ } else {
+ return null;
+ }
+ }
+
+ public Enumeration getInitParameterNames() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void setInitParmeter(String parameter, String value) {
+ map.put(parameter, value);
+ }
+
+ public ServletContext getServletContext() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/MockHttpServletRequest.java b/core/src/test/java/org/acegisecurity/MockHttpServletRequest.java
new file mode 100644
index 0000000000..c5a9acb684
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockHttpServletRequest.java
@@ -0,0 +1,291 @@
+/* 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;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+
+import java.security.Principal;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+
+/**
+ * Mocks a HttpServletRequest
and provides the
+ * getUserPrincipal()
, getContextPath()
,
+ * getServletPath()
and getSession()
methods.
+ *
+ *
+ * Also provides a convenience Map
for storing request parameters.
+ *
HttpServletResponse
, recording the
+ * sendRedirect
URL and sendError
code.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockHttpServletResponse implements HttpServletResponse {
+ //~ Instance fields ========================================================
+
+ private String redirect;
+ private int error;
+
+ //~ Methods ================================================================
+
+ public void setBufferSize(int arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public int getBufferSize() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String getCharacterEncoding() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public boolean isCommitted() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void setContentLength(int arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void setContentType(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void setDateHeader(String arg0, long arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public int getError() {
+ return this.error;
+ }
+
+ public void setHeader(String arg0, String arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void setIntHeader(String arg0, int arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void setLocale(Locale arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public Locale getLocale() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public ServletOutputStream getOutputStream() throws IOException {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String getRedirect() {
+ return redirect;
+ }
+
+ public void setStatus(int arg0, String arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void setStatus(int arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public PrintWriter getWriter() throws IOException {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void addCookie(Cookie arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void addDateHeader(String arg0, long arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void addHeader(String arg0, String arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void addIntHeader(String arg0, int arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public boolean containsHeader(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String encodeRedirectURL(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String encodeRedirectUrl(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String encodeURL(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String encodeUrl(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void flushBuffer() throws IOException {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void reset() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void resetBuffer() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void sendError(int arg0, String arg1) throws IOException {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void sendError(int arg0) throws IOException {
+ this.error = arg0;
+ }
+
+ public void sendRedirect(String arg0) throws IOException {
+ this.redirect = arg0;
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/MockHttpSession.java b/core/src/test/java/org/acegisecurity/MockHttpSession.java
new file mode 100644
index 0000000000..8c55108ce9
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockHttpSession.java
@@ -0,0 +1,108 @@
+/* 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;
+
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionContext;
+
+
+/**
+ * Mocks a HttpSession
and provides the
+ * getAttribute()
and setAttribute()
methods.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockHttpSession implements HttpSession {
+ //~ Instance fields ========================================================
+
+ private Map map = new HashMap();
+
+ //~ Methods ================================================================
+
+ public void setAttribute(String arg0, Object arg1) {
+ map.put(arg0, arg1);
+ }
+
+ public Object getAttribute(String arg0) {
+ return map.get(arg0);
+ }
+
+ public Enumeration getAttributeNames() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public long getCreationTime() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String getId() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public long getLastAccessedTime() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void setMaxInactiveInterval(int arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public int getMaxInactiveInterval() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public boolean isNew() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public ServletContext getServletContext() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public HttpSessionContext getSessionContext() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public Object getValue(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public String[] getValueNames() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void invalidate() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void putValue(String arg0, Object arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void removeAttribute(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public void removeValue(String arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/MockMethodInvocation.java b/core/src/test/java/org/acegisecurity/MockMethodInvocation.java
new file mode 100644
index 0000000000..0c74e72898
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockMethodInvocation.java
@@ -0,0 +1,52 @@
+/* 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;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockMethodInvocation implements MethodInvocation {
+ //~ Methods ================================================================
+
+ public Object[] getArguments() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public Method getMethod() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public AccessibleObject getStaticPart() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public Object getThis() {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public Object proceed() throws Throwable {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSourceTests.java b/core/src/test/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSourceTests.java
new file mode 100644
index 0000000000..ad2f387217
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/method/AbstractMethodDefinitionSourceTests.java
@@ -0,0 +1,100 @@
+/* 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.method;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.MockMethodInvocation;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+
+/**
+ * Tests {@link AbstractMethodDefinitionSource} and associated {@link
+ * ConfigAttributeDefinition}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class AbstractMethodDefinitionSourceTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public AbstractMethodDefinitionSourceTests() {
+ super();
+ }
+
+ public AbstractMethodDefinitionSourceTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AbstractMethodDefinitionSourceTests.class);
+ }
+
+ public void testDoesNotSupportAnotherObject() {
+ MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false,
+ true);
+ assertFalse(mds.supports(String.class));
+ }
+
+ public void testGetAttributesForANonMethodInvocation() {
+ MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false,
+ true);
+
+ try {
+ mds.getAttributes(new String());
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testGetAttributesForANullObject() {
+ MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false,
+ true);
+
+ try {
+ mds.getAttributes(null);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testGetAttributesForMethodInvocation() {
+ MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false,
+ true);
+
+ try {
+ mds.getAttributes(new MockMethodInvocation());
+ fail("Should have thrown UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testSupportsMethodInvocation() {
+ MockMethodDefinitionSource mds = new MockMethodDefinitionSource(false,
+ true);
+ assertTrue(mds.supports(MethodInvocation.class));
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.java b/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.java
new file mode 100644
index 0000000000..c436bae86b
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionAttributesTests.java
@@ -0,0 +1,283 @@
+/* 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.method;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.ConfigAttribute;
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+import net.sf.acegisecurity.ITargetObject;
+import net.sf.acegisecurity.MockMethodInvocation;
+import net.sf.acegisecurity.OtherTargetObject;
+import net.sf.acegisecurity.SecurityConfig;
+import net.sf.acegisecurity.TargetObject;
+import net.sf.acegisecurity.context.ContextHolder;
+import net.sf.acegisecurity.context.SecureContext;
+import net.sf.acegisecurity.context.SecureContextImpl;
+import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.lang.reflect.Method;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+
+/**
+ * Tests {@link MethodDefinitionAttributes}.
+ *
+ * @author Cameron Braid
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MethodDefinitionAttributesTests extends TestCase {
+ //~ Instance fields ========================================================
+
+ ClassPathXmlApplicationContext applicationContext;
+
+ //~ Constructors ===========================================================
+
+ public MethodDefinitionAttributesTests(String a) {
+ super(a);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(MethodDefinitionAttributesTests.class);
+ }
+
+ public void testAttributesForInterfaceTargetObject()
+ throws Exception {
+ ConfigAttributeDefinition def1 = getConfigAttributeDefinition(ITargetObject.class,
+ "countLength", new Class[] {String.class});
+ Set set1 = toSet(def1);
+ assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set1.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH")));
+
+ ConfigAttributeDefinition def2 = getConfigAttributeDefinition(ITargetObject.class,
+ "makeLowerCase", new Class[] {String.class});
+ Set set2 = toSet(def2);
+ assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set2.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")));
+
+ ConfigAttributeDefinition def3 = getConfigAttributeDefinition(ITargetObject.class,
+ "makeUpperCase", new Class[] {String.class});
+ Set set3 = toSet(def3);
+ assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set3.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")));
+ }
+
+ public void testAttributesForOtherTargetObject() throws Exception {
+ ConfigAttributeDefinition def1 = getConfigAttributeDefinition(OtherTargetObject.class,
+ "countLength", new Class[] {String.class});
+ Set set1 = toSet(def1);
+ assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set1.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH")));
+
+ // Confirm MOCK_CLASS_METHOD_COUNT_LENGTH not added, as it's a String (not a ConfigAttribute)
+ // Confirm also MOCK_CLASS not added, as we return null for class
+ assertEquals(2, set1.size());
+
+ ConfigAttributeDefinition def2 = getConfigAttributeDefinition(OtherTargetObject.class,
+ "makeLowerCase", new Class[] {String.class});
+ Set set2 = toSet(def2);
+ assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set2.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")));
+ assertTrue(set2.contains(
+ new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE")));
+
+ // Confirm MOCK_CLASS not added, as we return null for class
+ assertEquals(3, set2.size());
+
+ ConfigAttributeDefinition def3 = getConfigAttributeDefinition(OtherTargetObject.class,
+ "makeUpperCase", new Class[] {String.class});
+ Set set3 = toSet(def3);
+ assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set3.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")));
+ assertTrue(set3.contains(new SecurityConfig("RUN_AS"))); // defined against interface
+
+ assertEquals(3, set3.size());
+ }
+
+ public void testAttributesForTargetObject() throws Exception {
+ ConfigAttributeDefinition def1 = getConfigAttributeDefinition(TargetObject.class,
+ "countLength", new Class[] {String.class});
+ Set set1 = toSet(def1);
+ assertTrue(set1.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set1.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_COUNT_LENGTH")));
+
+ assertTrue(set1.contains(new SecurityConfig("MOCK_CLASS")));
+
+ // Confirm the MOCK_CLASS_METHOD_COUNT_LENGTH was not added, as it's not a ConfigAttribute
+ assertEquals(3, set1.size());
+
+ ConfigAttributeDefinition def2 = getConfigAttributeDefinition(TargetObject.class,
+ "makeLowerCase", new Class[] {String.class});
+ Set set2 = toSet(def2);
+ assertTrue(set2.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set2.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")));
+ assertTrue(set2.contains(new SecurityConfig("MOCK_CLASS")));
+ assertTrue(set2.contains(
+ new SecurityConfig("MOCK_CLASS_METHOD_MAKE_LOWER_CASE")));
+ assertEquals(4, set2.size());
+
+ ConfigAttributeDefinition def3 = getConfigAttributeDefinition(TargetObject.class,
+ "makeUpperCase", new Class[] {String.class});
+ Set set3 = toSet(def3);
+ assertTrue(set3.contains(new SecurityConfig("MOCK_INTERFACE")));
+ assertTrue(set3.contains(
+ new SecurityConfig("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")));
+ assertTrue(set3.contains(new SecurityConfig("MOCK_CLASS")));
+ assertTrue(set3.contains(
+ new SecurityConfig("MOCK_CLASS_METHOD_MAKE_UPPER_CASE")));
+ assertTrue(set3.contains(new SecurityConfig("RUN_AS")));
+ assertEquals(5, set3.size());
+ }
+
+ public void testMethodCallWithRunAsReplacement() throws Exception {
+ SecureContext context = new SecureContextImpl();
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
+ "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE")});
+ context.setAuthentication(token);
+ ContextHolder.setContext(context);
+
+ ITargetObject target = makeInterceptedTarget();
+ String result = target.makeUpperCase("hello");
+ assertEquals("HELLO net.sf.acegisecurity.MockRunAsAuthenticationToken true",
+ result);
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testMethodCallWithoutRunAsReplacement()
+ throws Exception {
+ SecureContext context = new SecureContextImpl();
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
+ "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")});
+ context.setAuthentication(token);
+ ContextHolder.setContext(context);
+
+ ITargetObject target = makeInterceptedTarget();
+ String result = target.makeLowerCase("HELLO");
+
+ assertEquals("hello net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken true",
+ result);
+
+ ContextHolder.setContext(null);
+ }
+
+ private ConfigAttributeDefinition getConfigAttributeDefinition(
+ Class clazz, String methodName, Class[] args) throws Exception {
+ final Method method = clazz.getMethod(methodName, args);
+ MethodDefinitionAttributes source = new MethodDefinitionAttributes();
+ source.setAttributes(new MockAttributes());
+
+ ConfigAttributeDefinition config = source.getAttributes(new MockMethodInvocation() {
+ public Method getMethod() {
+ return method;
+ }
+ });
+
+ return config;
+ }
+
+ private ITargetObject makeInterceptedTarget() {
+ String PREFIX = "beans.";
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty(PREFIX + "authentication.class",
+ "net.sf.acegisecurity.MockAuthenticationManager");
+ p.setProperty(PREFIX + "accessDecision.class",
+ "net.sf.acegisecurity.MockAccessDecisionManager");
+ p.setProperty(PREFIX + "runAs.class",
+ "net.sf.acegisecurity.MockRunAsManager");
+ p.setProperty(PREFIX + "attributes.class",
+ "net.sf.acegisecurity.intercept.method.MockAttributes");
+
+ p.setProperty(PREFIX + "objectDefinitionSource.class",
+ "net.sf.acegisecurity.intercept.method.MethodDefinitionAttributes");
+ p.setProperty(PREFIX + "objectDefinitionSource.attributes(ref)",
+ "attributes");
+
+ p.setProperty(PREFIX + "securityInterceptor.class",
+ "net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor");
+ p.setProperty(PREFIX + "securityInterceptor.authenticationManager(ref)",
+ "authentication");
+ p.setProperty(PREFIX + "securityInterceptor.accessDecisionManager(ref)",
+ "accessDecision");
+ p.setProperty(PREFIX + "securityInterceptor.runAsManager(ref)", "runAs");
+ p.setProperty(PREFIX
+ + "securityInterceptor.objectDefinitionSource(ref)",
+ "objectDefinitionSource");
+
+ p.setProperty(PREFIX + "targetObject.class",
+ "net.sf.acegisecurity.TargetObject");
+ p.setProperty(PREFIX + "target.class",
+ "org.springframework.aop.framework.ProxyFactoryBean");
+ p.setProperty(PREFIX + "target.proxyInterfaces",
+ "net.sf.acegisecurity.ITargetObject");
+ p.setProperty(PREFIX + "target.interceptorNames",
+ "securityInterceptor,targetObject");
+
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p,
+ PREFIX);
+
+ return (ITargetObject) lbf.getBean("target");
+ }
+
+ /**
+ * convert a ConfigAttributeDefinition
into a set of
+ * ConfigAttribute
(s)
+ *
+ * @param def the ConfigAttributeDefinition
to cover
+ *
+ * @return a Set of ConfigAttributes
+ */
+ private Set toSet(ConfigAttributeDefinition def) {
+ Set set = new HashSet();
+ Iterator i = def.getConfigAttributes();
+
+ while (i.hasNext()) {
+ ConfigAttribute a = (ConfigAttribute) i.next();
+ set.add(a);
+ }
+
+ return set;
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEditorTests.java b/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEditorTests.java
new file mode 100644
index 0000000000..4c950b9dc0
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/method/MethodDefinitionSourceEditorTests.java
@@ -0,0 +1,220 @@
+/* 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.method;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.SecurityConfig;
+import net.sf.acegisecurity.TargetObject;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+
+import java.util.Iterator;
+
+
+/**
+ * Tests {@link MethodDefinitionSourceEditor} and its asociated {@link
+ * MethodDefinitionMap}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MethodDefinitionSourceEditorTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public MethodDefinitionSourceEditorTests() {
+ super();
+ }
+
+ public MethodDefinitionSourceEditorTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(MethodDefinitionSourceEditorTests.class);
+ }
+
+ public void testClassNameNotFoundResultsInException() {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+
+ try {
+ editor.setAsText("net.sf.acegisecurity.DOES_NOT_EXIST_NAME=FOO,BAR");
+ fail("Should have given IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testClassNameNotInProperFormatResultsInException() {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+
+ try {
+ editor.setAsText("DOES_NOT_EXIST_NAME=FOO,BAR");
+ fail("Should have given IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testClassNameValidButMethodNameInvalidResultsInException() {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+
+ try {
+ editor.setAsText(
+ "net.sf.acegisecurity.TargetObject.INVALID_METHOD=FOO,BAR");
+ fail("Should have given IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testEmptyStringReturnsEmptyMap() {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+ editor.setAsText("");
+
+ MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue();
+ assertEquals(0, map.getMethodMapSize());
+ }
+
+ public void testIterator() {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+ editor.setAsText(
+ "net.sf.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY\r\nnet.sf.acegisecurity.TargetObject.make*=ROLE_NINE,ROLE_SUPERVISOR");
+
+ MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue();
+ Iterator iter = map.getConfigAttributeDefinitions();
+ int counter = 0;
+
+ while (iter.hasNext()) {
+ iter.next();
+ counter++;
+ }
+
+ assertEquals(3, counter);
+ }
+
+ public void testMultiMethodParsing() {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+ editor.setAsText(
+ "net.sf.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY\r\nnet.sf.acegisecurity.TargetObject.make*=ROLE_NINE,ROLE_SUPERVISOR");
+
+ MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue();
+ assertEquals(3, map.getMethodMapSize());
+ }
+
+ public void testMultiMethodParsingWhereLaterMethodsOverrideEarlierMethods()
+ throws Exception {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+ editor.setAsText(
+ "net.sf.acegisecurity.TargetObject.*=ROLE_GENERAL\r\nnet.sf.acegisecurity.TargetObject.makeLower*=ROLE_LOWER\r\nnet.sf.acegisecurity.TargetObject.make*=ROLE_MAKE\r\nnet.sf.acegisecurity.TargetObject.makeUpper*=ROLE_UPPER");
+
+ MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue();
+ assertEquals(4, map.getMethodMapSize());
+
+ ConfigAttributeDefinition returnedMakeLower = map.getAttributes(new MockMethodInvocation(
+ TargetObject.class, "makeLowerCase",
+ new Class[] {String.class}));
+ ConfigAttributeDefinition expectedMakeLower = new ConfigAttributeDefinition();
+ expectedMakeLower.addConfigAttribute(new SecurityConfig("ROLE_LOWER"));
+ assertEquals(expectedMakeLower, returnedMakeLower);
+
+ ConfigAttributeDefinition returnedMakeUpper = map.getAttributes(new MockMethodInvocation(
+ TargetObject.class, "makeUpperCase",
+ new Class[] {String.class}));
+ ConfigAttributeDefinition expectedMakeUpper = new ConfigAttributeDefinition();
+ expectedMakeUpper.addConfigAttribute(new SecurityConfig("ROLE_UPPER"));
+ assertEquals(expectedMakeUpper, returnedMakeUpper);
+
+ ConfigAttributeDefinition returnedCountLength = map.getAttributes(new MockMethodInvocation(
+ TargetObject.class, "countLength",
+ new Class[] {String.class}));
+ ConfigAttributeDefinition expectedCountLength = new ConfigAttributeDefinition();
+ expectedCountLength.addConfigAttribute(new SecurityConfig(
+ "ROLE_GENERAL"));
+ assertEquals(expectedCountLength, returnedCountLength);
+ }
+
+ public void testNullReturnsEmptyMap() {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+ editor.setAsText(null);
+
+ MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue();
+ assertEquals(0, map.getMethodMapSize());
+ }
+
+ public void testSingleMethodParsing() throws Exception {
+ MethodDefinitionSourceEditor editor = new MethodDefinitionSourceEditor();
+ editor.setAsText(
+ "net.sf.acegisecurity.TargetObject.countLength=ROLE_ONE,ROLE_TWO,RUN_AS_ENTRY");
+
+ MethodDefinitionMap map = (MethodDefinitionMap) editor.getValue();
+
+ ConfigAttributeDefinition returnedCountLength = map.getAttributes(new MockMethodInvocation(
+ TargetObject.class, "countLength",
+ new Class[] {String.class}));
+ ConfigAttributeDefinition expectedCountLength = new ConfigAttributeDefinition();
+ expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
+ expectedCountLength.addConfigAttribute(new SecurityConfig("ROLE_TWO"));
+ expectedCountLength.addConfigAttribute(new SecurityConfig(
+ "RUN_AS_ENTRY"));
+ assertEquals(expectedCountLength, returnedCountLength);
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockMethodInvocation implements MethodInvocation {
+ Method method;
+
+ public MockMethodInvocation(Class clazz, String methodName,
+ Class[] parameterTypes) throws NoSuchMethodException {
+ method = clazz.getMethod(methodName, parameterTypes);
+ }
+
+ private MockMethodInvocation() {
+ super();
+ }
+
+ public Object[] getArguments() {
+ return null;
+ }
+
+ public Method getMethod() {
+ return method;
+ }
+
+ public AccessibleObject getStaticPart() {
+ return null;
+ }
+
+ public Object getThis() {
+ return null;
+ }
+
+ public Object proceed() throws Throwable {
+ return null;
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MethodSecurityInterceptorTests.java b/core/src/test/java/org/acegisecurity/intercept/method/MethodSecurityInterceptorTests.java
new file mode 100644
index 0000000000..79a9984f59
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/method/MethodSecurityInterceptorTests.java
@@ -0,0 +1,521 @@
+/* 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.method;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.AccessDecisionManager;
+import net.sf.acegisecurity.AccessDeniedException;
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.AuthenticationCredentialsNotFoundException;
+import net.sf.acegisecurity.ConfigAttribute;
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+import net.sf.acegisecurity.ITargetObject;
+import net.sf.acegisecurity.MockAccessDecisionManager;
+import net.sf.acegisecurity.MockAuthenticationManager;
+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.providers.UsernamePasswordAuthenticationToken;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
+
+import java.util.Iterator;
+import java.util.Properties;
+
+
+/**
+ * Tests {@link MethodSecurityInterceptor}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MethodSecurityInterceptorTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public MethodSecurityInterceptorTests() {
+ super();
+ }
+
+ public MethodSecurityInterceptorTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(MethodSecurityInterceptorTests.class);
+ }
+
+ public void testCallingAPublicMethodFacadeWillNotRepeatSecurityChecksWhenPassedToTheSecuredMethodItFronts()
+ throws Exception {
+ ITargetObject target = makeInterceptedTarget();
+ String result = target.publicMakeLowerCase("HELLO");
+ assertEquals("hello ContextHolder Not Security Aware", result);
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testCallingAPublicMethodWhenPresentingASecureContextButWithoutAnyAuthenticationObject()
+ throws Exception {
+ SecureContext context = new SecureContextImpl();
+ ContextHolder.setContext(context);
+
+ ITargetObject target = makeInterceptedTarget();
+ String result = target.publicMakeLowerCase("HELLO");
+ assertEquals("hello Authentication empty", result);
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testCallingAPublicMethodWhenPresentingAnAuthenticationObjectWillProperlySetItsIsAuthenticatedProperty()
+ throws Exception {
+ SecureContext context = new SecureContextImpl();
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
+ "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_THIS_IS_NOT_REQUIRED_AS_IT_IS_PUBLIC")});
+ assertTrue(!token.isAuthenticated());
+ context.setAuthentication(token);
+ ContextHolder.setContext(context);
+
+ ITargetObject target = makeInterceptedTarget();
+ String result = target.publicMakeLowerCase("HELLO");
+ assertEquals("hello net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken false",
+ result);
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testDeniesWhenAppropriate() throws Exception {
+ SecureContext context = new SecureContextImpl();
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
+ "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_NO_BENEFIT_TO_THIS_GRANTED_AUTHORITY")});
+ context.setAuthentication(token);
+ ContextHolder.setContext(context);
+
+ ITargetObject target = makeInterceptedTarget();
+
+ try {
+ target.makeUpperCase("HELLO");
+ fail("Should have thrown AccessDeniedException");
+ } catch (AccessDeniedException expected) {
+ assertTrue(true);
+ }
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testGetters() {
+ MockAccessDecisionManager accessDecision = new MockAccessDecisionManager();
+ MockRunAsManager runAs = new MockRunAsManager();
+ MockAuthenticationManager authManager = new MockAuthenticationManager();
+ MockMethodDefinitionSource methodSource = new MockMethodDefinitionSource(false,
+ true);
+
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(accessDecision);
+ si.setRunAsManager(runAs);
+ si.setAuthenticationManager(authManager);
+ si.setObjectDefinitionSource(methodSource);
+
+ assertEquals(accessDecision, si.getAccessDecisionManager());
+ assertEquals(runAs, si.getRunAsManager());
+ assertEquals(authManager, si.getAuthenticationManager());
+ assertEquals(methodSource, si.getObjectDefinitionSource());
+ }
+
+ public void testMethodCallWithRunAsReplacement() throws Exception {
+ SecureContext context = new SecureContextImpl();
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
+ "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_UPPER")});
+ context.setAuthentication(token);
+ ContextHolder.setContext(context);
+
+ ITargetObject target = makeInterceptedTarget();
+ String result = target.makeUpperCase("hello");
+ assertEquals("HELLO net.sf.acegisecurity.MockRunAsAuthenticationToken true",
+ result);
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testMethodCallWithoutRunAsReplacement()
+ throws Exception {
+ SecureContext context = new SecureContextImpl();
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
+ "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_LOWER")});
+ assertTrue(!token.isAuthenticated());
+ context.setAuthentication(token);
+ ContextHolder.setContext(context);
+
+ ITargetObject target = makeInterceptedTarget();
+ String result = target.makeLowerCase("HELLO");
+
+ // Note we check the isAuthenticated becomes true in following line
+ assertEquals("hello net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken true",
+ result);
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testRejectionOfEmptyContextHolder() throws Exception {
+ ITargetObject target = makeInterceptedTarget();
+
+ try {
+ target.makeUpperCase("hello");
+ fail(
+ "Should have thrown AuthenticationCredentialsNotFoundException");
+ } catch (AuthenticationCredentialsNotFoundException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testRejectionOfNonSecureContextOnContextHolder()
+ throws Exception {
+ ContextHolder.setContext(new ContextImpl());
+
+ ITargetObject target = makeInterceptedTarget();
+
+ try {
+ target.makeUpperCase("hello");
+ fail(
+ "Should have thrown AuthenticationCredentialsNotFoundException");
+ } catch (AuthenticationCredentialsNotFoundException expected) {
+ assertTrue(true);
+ }
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testRejectionOfSecureContextThatContainsNoAuthenticationObject()
+ throws Exception {
+ ContextHolder.setContext(new SecureContextImpl());
+
+ ITargetObject target = makeInterceptedTarget();
+
+ try {
+ target.makeUpperCase("hello");
+ fail(
+ "Should have thrown AuthenticationCredentialsNotFoundException");
+ } catch (AuthenticationCredentialsNotFoundException expected) {
+ assertTrue(true);
+ }
+
+ ContextHolder.setContext(null);
+ }
+
+ public void testRejectsAccessDecisionManagersThatDoNotSupportMethodInvocation() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(new MockAccessDecisionManagerWhichOnlySupportsStrings());
+ si.setAuthenticationManager(new MockAuthenticationManager());
+ si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true));
+ si.setRunAsManager(new MockRunAsManager());
+
+ try {
+ si.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("AccessDecisionManager does not support MethodInvocation",
+ expected.getMessage());
+ }
+ }
+
+ 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());
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().startsWith("ObjectDefinitionSource does not support objects of type"));
+ }
+ }
+
+ public void testRejectsCallsWhenObjectIsNull() throws Throwable {
+ MethodSecurityInterceptor interceptor = new MethodSecurityInterceptor();
+
+ try {
+ interceptor.interceptor(null, new MockSecurityInterceptorCallback());
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("Object was null", expected.getMessage());
+ }
+ }
+
+ public void testRejectsRunAsManagersThatDoNotSupportMethodInvocation() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(new MockAccessDecisionManager());
+ si.setAuthenticationManager(new MockAuthenticationManager());
+ si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true));
+ si.setRunAsManager(new MockRunAsManagerWhichOnlySupportsStrings());
+
+ try {
+ si.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("RunAsManager does not support MethodInvocation",
+ expected.getMessage());
+ }
+ }
+
+ public void testStartupCheckForAccessDecisionManager() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setRunAsManager(new MockRunAsManager());
+ si.setAuthenticationManager(new MockAuthenticationManager());
+
+ si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true));
+
+ try {
+ si.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("An AccessDecisionManager is required",
+ expected.getMessage());
+ }
+ }
+
+ public void testStartupCheckForAuthenticationManager() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(new MockAccessDecisionManager());
+ si.setRunAsManager(new MockRunAsManager());
+
+ si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true));
+
+ try {
+ si.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("An AuthenticationManager is required",
+ expected.getMessage());
+ }
+ }
+
+ public void testStartupCheckForMethodDefinitionSource() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(new MockAccessDecisionManager());
+ si.setRunAsManager(new MockRunAsManager());
+ si.setAuthenticationManager(new MockAuthenticationManager());
+
+ try {
+ si.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("An ObjectDefinitionSource is required",
+ expected.getMessage());
+ }
+ }
+
+ public void testStartupCheckForRunAsManager() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(new MockAccessDecisionManager());
+ si.setAuthenticationManager(new MockAuthenticationManager());
+
+ si.setObjectDefinitionSource(new MockMethodDefinitionSource(false, true));
+
+ try {
+ si.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("A RunAsManager is required", expected.getMessage());
+ }
+ }
+
+ public void testValidationFailsIfInvalidAttributePresented() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(new MockAccessDecisionManager());
+ si.setRunAsManager(new MockRunAsManager());
+ si.setAuthenticationManager(new MockAuthenticationManager());
+
+ assertTrue(si.isValidateConfigAttributes()); // check default
+ si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, true));
+
+ try {
+ si.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("Unsupported configuration attributes: [ANOTHER_INVALID, INVALID_ATTRIBUTE]",
+ expected.getMessage());
+ }
+ }
+
+ public void testValidationNotAttemptedIfIsValidateConfigAttributesSetToFalse() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(new MockAccessDecisionManager());
+ si.setRunAsManager(new MockRunAsManager());
+ si.setAuthenticationManager(new MockAuthenticationManager());
+
+ assertTrue(si.isValidateConfigAttributes()); // check default
+ si.setValidateConfigAttributes(false);
+ assertTrue(!si.isValidateConfigAttributes()); // check changed
+
+ si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, true));
+ si.afterPropertiesSet();
+ assertTrue(true);
+ }
+
+ public void testValidationNotAttemptedIfMethodDefinitionSourceCannotReturnIterator() {
+ MethodSecurityInterceptor si = new MethodSecurityInterceptor();
+ si.setAccessDecisionManager(new MockAccessDecisionManager());
+ si.setRunAsManager(new MockRunAsManager());
+ si.setAuthenticationManager(new MockAuthenticationManager());
+
+ assertTrue(si.isValidateConfigAttributes()); // check default
+ si.setObjectDefinitionSource(new MockMethodDefinitionSource(true, false));
+ si.afterPropertiesSet();
+ assertTrue(true);
+ }
+
+ private ITargetObject makeInterceptedTarget() {
+ String PREFIX = "beans.";
+ DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
+ Properties p = new Properties();
+ p.setProperty(PREFIX + "authentication.class",
+ "net.sf.acegisecurity.MockAuthenticationManager");
+ p.setProperty(PREFIX + "accessDecision.class",
+ "net.sf.acegisecurity.MockAccessDecisionManager");
+ p.setProperty(PREFIX + "runAs.class",
+ "net.sf.acegisecurity.MockRunAsManager");
+
+ p.setProperty(PREFIX + "securityInterceptor.class",
+ "net.sf.acegisecurity.intercept.method.MethodSecurityInterceptor");
+ p.setProperty(PREFIX + "securityInterceptor.authenticationManager(ref)",
+ "authentication");
+ p.setProperty(PREFIX + "securityInterceptor.accessDecisionManager(ref)",
+ "accessDecision");
+ p.setProperty(PREFIX + "securityInterceptor.runAsManager(ref)", "runAs");
+ p.setProperty(PREFIX + "securityInterceptor.objectDefinitionSource",
+ "net.sf.acegisecurity.ITargetObject.makeLower*=MOCK_LOWER\r\nnet.sf.acegisecurity.ITargetObject.makeUpper*=MOCK_UPPER,RUN_AS");
+
+ p.setProperty(PREFIX + "targetObject.class",
+ "net.sf.acegisecurity.TargetObject");
+ p.setProperty(PREFIX + "target.class",
+ "org.springframework.aop.framework.ProxyFactoryBean");
+ p.setProperty(PREFIX + "target.proxyInterfaces",
+ "net.sf.acegisecurity.ITargetObject");
+ p.setProperty(PREFIX + "target.interceptorNames",
+ "securityInterceptor,targetObject");
+
+ (new PropertiesBeanDefinitionReader(lbf)).registerBeanDefinitions(p,
+ PREFIX);
+
+ return (ITargetObject) lbf.getBean("target");
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockAccessDecisionManagerWhichOnlySupportsStrings
+ implements AccessDecisionManager {
+ public void decide(Authentication authentication, Object object,
+ ConfigAttributeDefinition config) throws AccessDeniedException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public boolean supports(Class clazz) {
+ if (String.class.isAssignableFrom(clazz)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ return true;
+ }
+ }
+
+ private class MockObjectDefinitionSourceWhichOnlySupportsStrings
+ extends AbstractMethodDefinitionSource {
+ public Iterator getConfigAttributeDefinitions() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public boolean supports(Class clazz) {
+ if (String.class.isAssignableFrom(clazz)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected ConfigAttributeDefinition lookupAttributes(
+ MethodInvocation mi) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ }
+
+ private class MockRunAsManagerWhichOnlySupportsStrings
+ implements RunAsManager {
+ public Authentication buildRunAs(Authentication authentication,
+ Object object, ConfigAttributeDefinition config) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public boolean supports(Class clazz) {
+ if (String.class.isAssignableFrom(clazz)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ return true;
+ }
+ }
+
+ private class MockSecurityInterceptorCallback
+ implements SecurityInterceptorCallback {
+ public Object proceedWithObject(Object object)
+ throws Throwable {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MockAttributes.java b/core/src/test/java/org/acegisecurity/intercept/method/MockAttributes.java
new file mode 100644
index 0000000000..e3b3664bca
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/method/MockAttributes.java
@@ -0,0 +1,160 @@
+/* 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.method;
+
+import net.sf.acegisecurity.ITargetObject;
+import net.sf.acegisecurity.OtherTargetObject;
+import net.sf.acegisecurity.SecurityConfig;
+import net.sf.acegisecurity.TargetObject;
+
+import org.springframework.metadata.Attributes;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+
+
+/**
+ * Used by the {@link MethodDefinitionAttributesTests}.
+ *
+ * @author Cameron Braid
+ * @author Ben Alex
+ */
+public class MockAttributes implements Attributes {
+ //~ Instance fields ========================================================
+
+ List classAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
+ "MOCK_CLASS")});
+ List classMethodAttributesCountLength = Arrays.asList(new String[] {new String(
+ "MOCK_CLASS_METHOD_COUNT_LENGTH")});
+ List classMethodAttributesMakeLowerCase = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
+ "MOCK_CLASS_METHOD_MAKE_LOWER_CASE")});
+ List classMethodAttributesMakeUpperCase = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
+ "MOCK_CLASS_METHOD_MAKE_UPPER_CASE")});
+ List interfaceAttributes = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
+ "MOCK_INTERFACE")});
+ List interfaceMethodAttributesCountLength = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
+ "MOCK_INTERFACE_METHOD_COUNT_LENGTH")});
+ List interfaceMethodAttributesMakeLowerCase = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
+ "MOCK_INTERFACE_METHOD_MAKE_LOWER_CASE")});
+ List interfaceMethodAttributesMakeUpperCase = Arrays.asList(new SecurityConfig[] {new SecurityConfig(
+ "MOCK_INTERFACE_METHOD_MAKE_UPPER_CASE"), new SecurityConfig(
+ "RUN_AS")});
+
+ //~ Methods ================================================================
+
+ public Collection getAttributes(Class clazz) {
+ // Emphasise we return null for OtherTargetObject
+ if (clazz.equals(OtherTargetObject.class)) {
+ return null;
+ }
+
+ // interface
+ if (clazz.equals(ITargetObject.class)) {
+ return interfaceAttributes;
+ }
+
+ // class
+ if (clazz.equals(TargetObject.class)) {
+ return classAttributes;
+ }
+
+ return null;
+ }
+
+ public Collection getAttributes(Method method) {
+ // interface
+ if (method.getDeclaringClass().equals(ITargetObject.class)) {
+ if (method.getName().equals("countLength")) {
+ return interfaceMethodAttributesCountLength;
+ }
+
+ if (method.getName().equals("makeLowerCase")) {
+ return interfaceMethodAttributesMakeLowerCase;
+ }
+
+ if (method.getName().equals("makeUpperCase")) {
+ return interfaceMethodAttributesMakeUpperCase;
+ }
+
+ if (method.getName().equals("publicMakeLowerCase")) {
+ throw new UnsupportedOperationException(
+ "mock support not implemented");
+ }
+ }
+
+ // class
+ if (method.getDeclaringClass().equals(TargetObject.class)) {
+ if (method.getName().equals("countLength")) {
+ return classMethodAttributesCountLength;
+ }
+
+ if (method.getName().equals("makeLowerCase")) {
+ return classMethodAttributesMakeLowerCase;
+ }
+
+ if (method.getName().equals("makeUpperCase")) {
+ return classMethodAttributesMakeUpperCase;
+ }
+
+ if (method.getName().equals("publicMakeLowerCase")) {
+ throw new UnsupportedOperationException(
+ "mock support not implemented");
+ }
+ }
+
+ // other target object
+ if (method.getDeclaringClass().equals(OtherTargetObject.class)) {
+ if (method.getName().equals("countLength")) {
+ return classMethodAttributesCountLength;
+ }
+
+ if (method.getName().equals("makeLowerCase")) {
+ return classMethodAttributesMakeLowerCase;
+ }
+
+ if (method.getName().equals("makeUpperCase")) {
+ return null; // NB
+ }
+
+ if (method.getName().equals("publicMakeLowerCase")) {
+ throw new UnsupportedOperationException(
+ "mock support not implemented");
+ }
+ }
+
+ return null;
+ }
+
+ public Collection getAttributes(Class arg0, Class arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public Collection getAttributes(Field arg0, Class arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public Collection getAttributes(Field arg0) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+
+ public Collection getAttributes(Method arg0, Class arg1) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.java b/core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.java
new file mode 100644
index 0000000000..52990386cd
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/method/MockMethodDefinitionSource.java
@@ -0,0 +1,88 @@
+/* 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.method;
+
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.SecurityConfig;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockMethodDefinitionSource extends AbstractMethodDefinitionSource {
+ //~ Instance fields ========================================================
+
+ private List list;
+ private boolean returnAnIterator;
+
+ //~ Constructors ===========================================================
+
+ public MockMethodDefinitionSource(boolean includeInvalidAttributes,
+ boolean returnAnIteratorWhenRequested) {
+ returnAnIterator = returnAnIteratorWhenRequested;
+ list = new Vector();
+
+ ConfigAttributeDefinition def1 = new ConfigAttributeDefinition();
+ def1.addConfigAttribute(new SecurityConfig("MOCK_LOWER"));
+ list.add(def1);
+
+ if (includeInvalidAttributes) {
+ ConfigAttributeDefinition def2 = new ConfigAttributeDefinition();
+ def2.addConfigAttribute(new SecurityConfig("MOCK_LOWER"));
+ def2.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE"));
+ list.add(def2);
+ }
+
+ ConfigAttributeDefinition def3 = new ConfigAttributeDefinition();
+ def3.addConfigAttribute(new SecurityConfig("MOCK_UPPER"));
+ def3.addConfigAttribute(new SecurityConfig("RUN_AS"));
+ list.add(def3);
+
+ if (includeInvalidAttributes) {
+ ConfigAttributeDefinition def4 = new ConfigAttributeDefinition();
+ def4.addConfigAttribute(new SecurityConfig("MOCK_SOMETHING"));
+ def4.addConfigAttribute(new SecurityConfig("ANOTHER_INVALID"));
+ list.add(def4);
+ }
+ }
+
+ private MockMethodDefinitionSource() {
+ super();
+ }
+
+ //~ Methods ================================================================
+
+ public Iterator getConfigAttributeDefinitions() {
+ if (returnAnIterator) {
+ return list.iterator();
+ } else {
+ return null;
+ }
+ }
+
+ protected ConfigAttributeDefinition lookupAttributes(MethodInvocation mi) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefinitionSourceTests.java b/core/src/test/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefinitionSourceTests.java
new file mode 100644
index 0000000000..c829f7b3b2
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/web/AbstractFilterInvocationDefinitionSourceTests.java
@@ -0,0 +1,117 @@
+/* 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.web;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.MockHttpServletRequest;
+import net.sf.acegisecurity.MockHttpServletResponse;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+
+/**
+ * Tests {@link AbstractFilterInvocationDefinitionSource}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class AbstractFilterInvocationDefinitionSourceTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public AbstractFilterInvocationDefinitionSourceTests() {
+ super();
+ }
+
+ public AbstractFilterInvocationDefinitionSourceTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AbstractFilterInvocationDefinitionSourceTests.class);
+ }
+
+ public void testDoesNotSupportAnotherObject() {
+ MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false,
+ true);
+ assertFalse(mfis.supports(String.class));
+ }
+
+ public void testGetAttributesForANonFilterInvocation() {
+ MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false,
+ true);
+
+ try {
+ mfis.getAttributes(new String());
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testGetAttributesForANullObject() {
+ MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false,
+ true);
+
+ try {
+ mfis.getAttributes(null);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testGetAttributesForFilterInvocationSuccess() {
+ MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false,
+ true);
+
+ try {
+ mfis.getAttributes(new FilterInvocation(
+ new MockHttpServletRequest(null, null),
+ new MockHttpServletResponse(), new MockFilterChain()));
+ fail("Should have thrown UnsupportedOperationException");
+ } catch (UnsupportedOperationException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testSupportsFilterInvocation() {
+ MockFilterInvocationDefinitionSource mfis = new MockFilterInvocationDefinitionSource(false,
+ true);
+ assertTrue(mfis.supports(FilterInvocation.class));
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockFilterChain implements FilterChain {
+ public void doFilter(ServletRequest arg0, ServletResponse arg1)
+ throws IOException, ServletException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapTests.java
new file mode 100644
index 0000000000..4d561fa140
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionMapTests.java
@@ -0,0 +1,123 @@
+/* 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.web;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.MockFilterChain;
+import net.sf.acegisecurity.MockHttpServletRequest;
+import net.sf.acegisecurity.MockHttpServletResponse;
+import net.sf.acegisecurity.SecurityConfig;
+
+
+/**
+ * Tests parts of {@link FilterInvocationDefinitionMap} not tested by {@link
+ * FilterInvocationDefinitionSourceEditorTests}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class FilterInvocationDefinitionMapTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public FilterInvocationDefinitionMapTests() {
+ super();
+ }
+
+ public FilterInvocationDefinitionMapTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(FilterInvocationDefinitionMapTests.class);
+ }
+
+ public void testConvertUrlToLowercaseIsFalseByDefault() {
+ FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap();
+ assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
+ }
+
+ public void testConvertUrlToLowercaseSetterRespected() {
+ FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap();
+ map.setConvertUrlToLowercaseBeforeComparison(true);
+ assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
+ }
+
+ public void testLookupNotRequiringExactMatchSuccessIfNotMatching() {
+ FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap();
+ map.setConvertUrlToLowercaseBeforeComparison(true);
+ assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
+
+ ConfigAttributeDefinition def = new ConfigAttributeDefinition();
+ def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
+ map.addSecureUrl("\\A/secure/super.*\\Z", def);
+
+ // Build a HTTP request
+ MockHttpServletRequest req = new MockHttpServletRequest(null);
+ req.setServletPath("/SeCuRE/super/somefile.html");
+
+ FilterInvocation fi = new FilterInvocation(req,
+ new MockHttpServletResponse(), new MockFilterChain());
+
+ ConfigAttributeDefinition response = map.lookupAttributes(fi);
+ assertEquals(def, response);
+ }
+
+ public void testLookupRequiringExactMatchFailsIfNotMatching() {
+ FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap();
+ assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
+
+ ConfigAttributeDefinition def = new ConfigAttributeDefinition();
+ def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
+ map.addSecureUrl("\\A/secure/super.*\\Z", def);
+
+ // Build a HTTP request
+ MockHttpServletRequest req = new MockHttpServletRequest(null);
+ req.setServletPath("/SeCuRE/super/somefile.html");
+
+ FilterInvocation fi = new FilterInvocation(req,
+ new MockHttpServletResponse(), new MockFilterChain());
+
+ ConfigAttributeDefinition response = map.lookupAttributes(fi);
+ assertEquals(null, response);
+ }
+
+ public void testLookupRequiringExactMatchIsSuccessful() {
+ FilterInvocationDefinitionMap map = new FilterInvocationDefinitionMap();
+ assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
+
+ ConfigAttributeDefinition def = new ConfigAttributeDefinition();
+ def.addConfigAttribute(new SecurityConfig("ROLE_ONE"));
+ map.addSecureUrl("\\A/secure/super.*\\Z", def);
+
+ // Build a HTTP request
+ MockHttpServletRequest req = new MockHttpServletRequest(null);
+ req.setServletPath("/secure/super/somefile.html");
+
+ FilterInvocation fi = new FilterInvocation(req,
+ new MockHttpServletResponse(), new MockFilterChain());
+
+ ConfigAttributeDefinition response = map.lookupAttributes(fi);
+ assertEquals(def, response);
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditorTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditorTests.java
new file mode 100644
index 0000000000..e4a4d27697
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationDefinitionSourceEditorTests.java
@@ -0,0 +1,240 @@
+/* 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.web;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.MockFilterChain;
+import net.sf.acegisecurity.MockHttpServletRequest;
+import net.sf.acegisecurity.MockHttpServletResponse;
+import net.sf.acegisecurity.SecurityConfig;
+
+import java.util.Iterator;
+
+
+/**
+ * Tests {@link FilterInvocationDefinitionSourceEditor} and its associated
+ * {@link FilterInvocationDefinitionMap}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class FilterInvocationDefinitionSourceEditorTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public FilterInvocationDefinitionSourceEditorTests() {
+ super();
+ }
+
+ public FilterInvocationDefinitionSourceEditorTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(FilterInvocationDefinitionSourceEditorTests.class);
+ }
+
+ public void testConvertUrlToLowercaseDefaultSettingUnchangedByEditor() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText(
+ "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+ assertFalse(map.isConvertUrlToLowercaseBeforeComparison());
+ }
+
+ public void testConvertUrlToLowercaseSettingApplied() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText(
+ "CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON\r\n\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+ assertTrue(map.isConvertUrlToLowercaseBeforeComparison());
+ }
+
+ public void testEmptyStringReturnsEmptyMap() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText("");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+ assertEquals(0, map.getMapSize());
+ }
+
+ public void testInvalidRegularExpressionsDetected()
+ throws Exception {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+
+ try {
+ editor.setAsText("*=SOME_ROLE");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("Malformed regular expression: *",
+ expected.getMessage());
+ }
+ }
+
+ public void testIterator() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText(
+ "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+ Iterator iter = map.getConfigAttributeDefinitions();
+ int counter = 0;
+
+ while (iter.hasNext()) {
+ iter.next();
+ counter++;
+ }
+
+ assertEquals(2, counter);
+ }
+
+ public void testMapReturnsNullWhenNoMatchFound() throws Exception {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+
+ MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
+ null);
+ httpRequest.setServletPath("/totally/different/path/index.html");
+
+ ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(
+ httpRequest, new MockHttpServletResponse(),
+ new MockFilterChain()));
+
+ assertEquals(null, returned);
+ }
+
+ public void testMultiUrlParsing() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText(
+ "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+ assertEquals(2, map.getMapSize());
+ }
+
+ public void testNoArgsConstructor() {
+ try {
+ new FilterInvocationDefinitionMap().new EntryHolder();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testNullReturnsEmptyMap() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText(null);
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+ assertEquals(0, map.getMapSize());
+ }
+
+ public void testOrderOfEntriesIsPreservedOrderA() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText(
+ "\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE\r\n\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+
+ // Test ensures we match the first entry, not the second
+ MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
+ null);
+ httpRequest.setServletPath("/secure/super/very_secret.html");
+
+ ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(
+ httpRequest, new MockHttpServletResponse(),
+ new MockFilterChain()));
+
+ ConfigAttributeDefinition expected = new ConfigAttributeDefinition();
+ expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE"));
+ expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE"));
+
+ assertEquals(expected, returned);
+ }
+
+ public void testOrderOfEntriesIsPreservedOrderB() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText(
+ "\\A/secure/.*\\Z=ROLE_SUPERVISOR,ROLE_TELLER\r\n\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+
+ MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
+ null);
+ httpRequest.setServletPath("/secure/super/very_secret.html");
+
+ ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(
+ httpRequest, new MockHttpServletResponse(),
+ new MockFilterChain()));
+
+ ConfigAttributeDefinition expected = new ConfigAttributeDefinition();
+ expected.addConfigAttribute(new SecurityConfig("ROLE_SUPERVISOR"));
+ expected.addConfigAttribute(new SecurityConfig("ROLE_TELLER"));
+
+ assertEquals(expected, returned);
+ }
+
+ public void testSingleUrlParsing() throws Exception {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText("\\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+
+ MockHttpServletRequest httpRequest = new MockHttpServletRequest(null,
+ null);
+ httpRequest.setServletPath("/secure/super/very_secret.html");
+
+ ConfigAttributeDefinition returned = map.getAttributes(new FilterInvocation(
+ httpRequest, new MockHttpServletResponse(),
+ new MockFilterChain()));
+
+ ConfigAttributeDefinition expected = new ConfigAttributeDefinition();
+ expected.addConfigAttribute(new SecurityConfig("ROLE_WE_DONT_HAVE"));
+ expected.addConfigAttribute(new SecurityConfig("ANOTHER_ROLE"));
+
+ assertEquals(expected, returned);
+ }
+
+ public void testWhitespaceAndCommentsAndLinesWithoutEqualsSignsAreIgnored() {
+ FilterInvocationDefinitionSourceEditor editor = new FilterInvocationDefinitionSourceEditor();
+ editor.setAsText(
+ " \\A/secure/super.*\\Z=ROLE_WE_DONT_HAVE,ANOTHER_ROLE \r\n \r\n \r\n // comment line \r\n \\A/testing.*\\Z=ROLE_TEST \r\n");
+
+ FilterInvocationDefinitionMap map = (FilterInvocationDefinitionMap) editor
+ .getValue();
+ assertEquals(2, map.getMapSize());
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationTests.java
new file mode 100644
index 0000000000..591945e68e
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterInvocationTests.java
@@ -0,0 +1,374 @@
+/* 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.web;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.MockFilterChain;
+import net.sf.acegisecurity.MockHttpServletRequest;
+import net.sf.acegisecurity.MockHttpServletResponse;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
+
+import java.util.Enumeration;
+import java.util.Locale;
+import java.util.Map;
+
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+
+/**
+ * Tests {@link FilterInvocation}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class FilterInvocationTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public FilterInvocationTests() {
+ super();
+ }
+
+ public FilterInvocationTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(FilterInvocationTests.class);
+ }
+
+ public void testGettersAndStringMethods() {
+ MockHttpServletRequest request = new MockHttpServletRequest(null, null);
+ request.setServletPath("/HelloWorld");
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterChain chain = new MockFilterChain();
+ FilterInvocation fi = new FilterInvocation(request, response, chain);
+ assertEquals(request, fi.getRequest());
+ assertEquals(request, fi.getHttpRequest());
+ assertEquals(response, fi.getResponse());
+ assertEquals(response, fi.getHttpResponse());
+ assertEquals(chain, fi.getChain());
+ assertEquals("/HelloWorld", fi.getRequestUrl());
+ assertEquals("FilterInvocation: URL: /HelloWorld", fi.toString());
+ }
+
+ public void testNoArgsConstructor() {
+ try {
+ new FilterInvocation();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testRejectsNullFilterChain() {
+ MockHttpServletRequest request = new MockHttpServletRequest(null, null);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+
+ try {
+ new FilterInvocation(request, response, null);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testRejectsNullServletRequest() {
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterChain chain = new MockFilterChain();
+
+ try {
+ new FilterInvocation(null, response, chain);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testRejectsNullServletResponse() {
+ MockHttpServletRequest request = new MockHttpServletRequest(null, null);
+ MockFilterChain chain = new MockFilterChain();
+
+ try {
+ new FilterInvocation(request, null, chain);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testRejectsServletRequestWhichIsNotHttpServletRequest() {
+ MockServletRequest request = new MockServletRequest();
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterChain chain = new MockFilterChain();
+
+ try {
+ new FilterInvocation(request, response, chain);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("Can only process HttpServletRequest",
+ expected.getMessage());
+ }
+ }
+
+ public void testRejectsServletResponseWhichIsNotHttpServletResponse() {
+ MockHttpServletRequest request = new MockHttpServletRequest(null, null);
+ MockServletResponse response = new MockServletResponse();
+ MockFilterChain chain = new MockFilterChain();
+
+ try {
+ new FilterInvocation(request, response, chain);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("Can only process HttpServletResponse",
+ expected.getMessage());
+ }
+ }
+
+ public void testStringMethodsWithAQueryString() {
+ MockHttpServletRequest request = new MockHttpServletRequest("foo=bar");
+ request.setServletPath("/HelloWorld");
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterChain chain = new MockFilterChain();
+ FilterInvocation fi = new FilterInvocation(request, response, chain);
+ assertEquals("/HelloWorld?foo=bar", fi.getRequestUrl());
+ assertEquals("FilterInvocation: URL: /HelloWorld?foo=bar", fi.toString());
+ }
+
+ public void testStringMethodsWithoutAnyQueryString() {
+ MockHttpServletRequest request = new MockHttpServletRequest(null, null);
+ request.setServletPath("/HelloWorld");
+
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockFilterChain chain = new MockFilterChain();
+ FilterInvocation fi = new FilterInvocation(request, response, chain);
+ assertEquals("/HelloWorld", fi.getRequestUrl());
+ assertEquals("FilterInvocation: URL: /HelloWorld", fi.toString());
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockServletRequest implements ServletRequest {
+ public void setAttribute(String arg0, Object arg1) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public Object getAttribute(String arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public Enumeration getAttributeNames() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public void setCharacterEncoding(String arg0)
+ throws UnsupportedEncodingException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getCharacterEncoding() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public int getContentLength() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getContentType() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public ServletInputStream getInputStream() throws IOException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public Locale getLocale() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public Enumeration getLocales() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getParameter(String arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public Map getParameterMap() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public Enumeration getParameterNames() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String[] getParameterValues(String arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getProtocol() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public BufferedReader getReader() throws IOException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getRealPath(String arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getRemoteAddr() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getRemoteHost() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public RequestDispatcher getRequestDispatcher(String arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getScheme() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public boolean isSecure() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getServerName() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public int getServerPort() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public void removeAttribute(String arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ }
+
+ private class MockServletResponse implements ServletResponse {
+ public void setBufferSize(int arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public int getBufferSize() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getCharacterEncoding() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public boolean isCommitted() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public void setContentLength(int arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public void setContentType(String arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public void setLocale(Locale arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public Locale getLocale() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public ServletOutputStream getOutputStream() throws IOException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public PrintWriter getWriter() throws IOException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public void flushBuffer() throws IOException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public void reset() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public void resetBuffer() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java b/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java
new file mode 100644
index 0000000000..420aa10a8f
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/web/FilterSecurityInterceptorTests.java
@@ -0,0 +1,258 @@
+/* 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.web;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.AccessDecisionManager;
+import net.sf.acegisecurity.AccessDeniedException;
+import net.sf.acegisecurity.Authentication;
+import net.sf.acegisecurity.ConfigAttribute;
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+import net.sf.acegisecurity.MockAccessDecisionManager;
+import net.sf.acegisecurity.MockAuthenticationManager;
+import net.sf.acegisecurity.MockHttpServletRequest;
+import net.sf.acegisecurity.MockHttpServletResponse;
+import net.sf.acegisecurity.MockHttpSession;
+import net.sf.acegisecurity.MockRunAsManager;
+import net.sf.acegisecurity.RunAsManager;
+import net.sf.acegisecurity.SecurityConfig;
+import net.sf.acegisecurity.context.ContextHolder;
+import net.sf.acegisecurity.context.SecureContext;
+import net.sf.acegisecurity.context.SecureContextImpl;
+import net.sf.acegisecurity.providers.UsernamePasswordAuthenticationToken;
+
+import java.io.IOException;
+
+import java.util.Iterator;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+
+/**
+ * Tests {@link FiltSecurityInterceptor}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class FilterSecurityInterceptorTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public FilterSecurityInterceptorTests() {
+ super();
+ }
+
+ public FilterSecurityInterceptorTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(FilterSecurityInterceptorTests.class);
+ }
+
+ public void testEnsuresAccessDecisionManagerSupportsFilterInvocationClass() {
+ FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
+ interceptor.setAuthenticationManager(new MockAuthenticationManager());
+ interceptor.setObjectDefinitionSource(new FilterInvocationDefinitionMap());
+ interceptor.setRunAsManager(new MockRunAsManager());
+
+ interceptor.setAccessDecisionManager(new AccessDecisionManager() {
+ public boolean supports(Class clazz) {
+ return false;
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ return true;
+ }
+
+ public void decide(Authentication authentication,
+ Object object, ConfigAttributeDefinition config)
+ throws AccessDeniedException {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ });
+
+ try {
+ interceptor.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("AccessDecisionManager does not support FilterInvocation",
+ expected.getMessage());
+ }
+ }
+
+ public void testEnsuresRunAsManagerSupportsFilterInvocationClass() {
+ FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
+ interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
+ interceptor.setAuthenticationManager(new MockAuthenticationManager());
+ interceptor.setObjectDefinitionSource(new FilterInvocationDefinitionMap());
+
+ interceptor.setRunAsManager(new RunAsManager() {
+ public boolean supports(Class clazz) {
+ return false;
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ return true;
+ }
+
+ public Authentication buildRunAs(
+ Authentication authentication, Object object,
+ ConfigAttributeDefinition config) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ });
+
+ try {
+ interceptor.afterPropertiesSet();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("RunAsManager does not support FilterInvocation",
+ expected.getMessage());
+ }
+ }
+
+ public void testNormalStartupAndGetter() {
+ FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
+ interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
+ interceptor.setAuthenticationManager(new MockAuthenticationManager());
+
+ FilterInvocationDefinitionMap fidp = new FilterInvocationDefinitionMap();
+ interceptor.setObjectDefinitionSource(fidp);
+ interceptor.setRunAsManager(new MockRunAsManager());
+ interceptor.afterPropertiesSet();
+ assertTrue(true);
+ assertEquals(fidp, interceptor.getObjectDefinitionSource());
+ }
+
+ /**
+ * We just test invocation works in a success event. There is no need to
+ * test access denied events as the abstract parent enforces that logic,
+ * which is extensively tested separately.
+ *
+ * @throws Throwable DOCUMENT ME!
+ */
+ public void testSuccessfulInvocation() throws Throwable {
+ // Setup the FilterSecurityInterceptor
+ FilterSecurityInterceptor interceptor = new FilterSecurityInterceptor();
+ interceptor.setAccessDecisionManager(new MockAccessDecisionManager());
+ interceptor.setAuthenticationManager(new MockAuthenticationManager());
+ interceptor.setRunAsManager(new MockRunAsManager());
+
+ // Setup a mock config attribute definition
+ ConfigAttributeDefinition def = new ConfigAttributeDefinition();
+ def.addConfigAttribute(new SecurityConfig("MOCK_OK"));
+
+ MockFilterInvocationDefinitionMap mockSource = new MockFilterInvocationDefinitionMap("/secure/page.html",
+ def);
+ interceptor.setObjectDefinitionSource(mockSource);
+
+ // Setup our expectation that the filter chain will be invoked, as access is granted
+ MockFilterChain chain = new MockFilterChain(true);
+
+ // Setup our HTTP request and response
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ MockHttpServletRequest request = new MockHttpServletRequest(null,
+ new MockHttpSession());
+ request.setServletPath("/secure/page.html");
+
+ // Setup a Context
+ SecureContext context = new SecureContextImpl();
+ UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken("Test",
+ "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("MOCK_OK")});
+ context.setAuthentication(token);
+ ContextHolder.setContext(context);
+
+ // Create and test our secure object
+ FilterInvocation fi = new FilterInvocation(request, response, chain);
+ interceptor.invoke(fi);
+
+ // Destroy the Context
+ ContextHolder.setContext(null);
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockFilterChain implements FilterChain {
+ private boolean expectToProceed;
+
+ public MockFilterChain(boolean expectToProceed) {
+ this.expectToProceed = expectToProceed;
+ }
+
+ private MockFilterChain() {
+ super();
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response)
+ throws IOException, ServletException {
+ if (expectToProceed) {
+ assertTrue(true);
+ } else {
+ fail("Did not expect filter chain to proceed");
+ }
+ }
+ }
+
+ private class MockFilterInvocationDefinitionMap
+ implements FilterInvocationDefinitionSource {
+ private ConfigAttributeDefinition toReturn;
+ private String servletPath;
+
+ public MockFilterInvocationDefinitionMap(String servletPath,
+ ConfigAttributeDefinition toReturn) {
+ this.servletPath = servletPath;
+ this.toReturn = toReturn;
+ }
+
+ private MockFilterInvocationDefinitionMap() {
+ super();
+ }
+
+ public ConfigAttributeDefinition getAttributes(Object object)
+ throws IllegalArgumentException {
+ FilterInvocation fi = (FilterInvocation) object;
+
+ if (servletPath.equals(fi.getHttpRequest().getServletPath())) {
+ return toReturn;
+ } else {
+ return null;
+ }
+ }
+
+ public Iterator getConfigAttributeDefinitions() {
+ return null;
+ }
+
+ public boolean supports(Class clazz) {
+ return true;
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinitionSource.java b/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinitionSource.java
new file mode 100644
index 0000000000..2d0372eea7
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/web/MockFilterInvocationDefinitionSource.java
@@ -0,0 +1,88 @@
+/* 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.web;
+
+import net.sf.acegisecurity.ConfigAttributeDefinition;
+import net.sf.acegisecurity.SecurityConfig;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+
+/**
+ * DOCUMENT ME!
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockFilterInvocationDefinitionSource
+ extends AbstractFilterInvocationDefinitionSource {
+ //~ Instance fields ========================================================
+
+ private List list;
+ private boolean returnAnIterator;
+
+ //~ Constructors ===========================================================
+
+ public MockFilterInvocationDefinitionSource(
+ boolean includeInvalidAttributes, boolean returnAnIteratorWhenRequested) {
+ returnAnIterator = returnAnIteratorWhenRequested;
+ list = new Vector();
+
+ ConfigAttributeDefinition def1 = new ConfigAttributeDefinition();
+ def1.addConfigAttribute(new SecurityConfig("MOCK_LOWER"));
+ list.add(def1);
+
+ if (includeInvalidAttributes) {
+ ConfigAttributeDefinition def2 = new ConfigAttributeDefinition();
+ def2.addConfigAttribute(new SecurityConfig("MOCK_LOWER"));
+ def2.addConfigAttribute(new SecurityConfig("INVALID_ATTRIBUTE"));
+ list.add(def2);
+ }
+
+ ConfigAttributeDefinition def3 = new ConfigAttributeDefinition();
+ def3.addConfigAttribute(new SecurityConfig("MOCK_UPPER"));
+ def3.addConfigAttribute(new SecurityConfig("RUN_AS"));
+ list.add(def3);
+
+ if (includeInvalidAttributes) {
+ ConfigAttributeDefinition def4 = new ConfigAttributeDefinition();
+ def4.addConfigAttribute(new SecurityConfig("MOCK_SOMETHING"));
+ def4.addConfigAttribute(new SecurityConfig("ANOTHER_INVALID"));
+ list.add(def4);
+ }
+ }
+
+ private MockFilterInvocationDefinitionSource() {
+ super();
+ }
+
+ //~ Methods ================================================================
+
+ public Iterator getConfigAttributeDefinitions() {
+ if (returnAnIterator) {
+ return list.iterator();
+ } else {
+ return null;
+ }
+ }
+
+ protected ConfigAttributeDefinition lookupAttributes(
+ FilterInvocation filterInvocation) {
+ throw new UnsupportedOperationException("mock method not implemented");
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java b/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java
new file mode 100644
index 0000000000..a32dcd3700
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/web/SecurityEnforcementFilterTests.java
@@ -0,0 +1,317 @@
+/* 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.web;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.AccessDeniedException;
+import net.sf.acegisecurity.BadCredentialsException;
+import net.sf.acegisecurity.MockFilterConfig;
+import net.sf.acegisecurity.MockHttpServletRequest;
+import net.sf.acegisecurity.MockHttpServletResponse;
+import net.sf.acegisecurity.MockHttpSession;
+import net.sf.acegisecurity.ui.webapp.AuthenticationProcessingFilter;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+
+/**
+ * Tests {@link SecurityEnforcementFilter}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class SecurityEnforcementFilterTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public SecurityEnforcementFilterTests() {
+ super();
+ }
+
+ public SecurityEnforcementFilterTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(SecurityEnforcementFilterTests.class);
+ }
+
+ public void testAccessDeniedWhenAccessDeniedException()
+ throws Exception {
+ // Setup our HTTP request
+ MockHttpServletRequest request = new MockHttpServletRequest(null,
+ new MockHttpSession());
+ request.setServletPath("/secure/page.html");
+
+ // Setup our expectation that the filter chain will not be invoked, as access is denied
+ MockFilterChain chain = new MockFilterChain(false);
+
+ // Setup the FilterSecurityInterceptor thrown an access denied exception
+ MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(true,
+ false);
+
+ // Test
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor,
+ "/login.jsp");
+ filter.doFilter(request, response, chain);
+ assertEquals(403, response.getError());
+ }
+
+ public void testDoFilterWithNonHttpServletRequestDetected()
+ throws Exception {
+ SecurityEnforcementFilter filter = new SecurityEnforcementFilter();
+
+ try {
+ filter.doFilter(null, new MockHttpServletResponse(),
+ new MockFilterChain());
+ fail("Should have thrown ServletException");
+ } catch (ServletException expected) {
+ assertEquals("HttpServletRequest required", expected.getMessage());
+ }
+ }
+
+ public void testDoFilterWithNonHttpServletResponseDetected()
+ throws Exception {
+ SecurityEnforcementFilter filter = new SecurityEnforcementFilter();
+
+ try {
+ filter.doFilter(new MockHttpServletRequest(null, null), null,
+ new MockFilterChain());
+ fail("Should have thrown ServletException");
+ } catch (ServletException expected) {
+ assertEquals("HttpServletResponse required", expected.getMessage());
+ }
+ }
+
+ public void testRedirectedToLoginFormAndSessionShowsOriginalTargetWhenAuthenticationException()
+ throws Exception {
+ // Setup our HTTP request
+ MockHttpServletRequest request = new MockHttpServletRequest(null,
+ new MockHttpSession());
+ request.setServletPath("/secure/page.html");
+
+ // Setup our expectation that the filter chain will not be invoked, as access is denied
+ MockFilterChain chain = new MockFilterChain(false);
+
+ // Setup the FilterSecurityInterceptor thrown an authentication failure exceptions
+ MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(false,
+ true);
+
+ // Test
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor,
+ "/login.jsp");
+ filter.doFilter(request, response, chain);
+ assertEquals("/login.jsp", response.getRedirect());
+ assertEquals("/secure/page.html",
+ request.getSession().getAttribute(AuthenticationProcessingFilter.ACEGI_SECURITY_TARGET_URL_KEY));
+ }
+
+ public void testStartupDetectsInvalidAppContextLocation()
+ throws Exception {
+ MockFilterConfig config = new MockFilterConfig();
+ config.setInitParmeter("loginFormUrl", "/login.jsp");
+ config.setInitParmeter("appContextLocation",
+ "net/sf/acegisecurity/intercept/web/securityfiltertest-invalid.xml");
+
+ SecurityEnforcementFilter filter = new SecurityEnforcementFilter();
+
+ try {
+ filter.init(config);
+ fail("Should have thrown ServletException");
+ } catch (ServletException expected) {
+ assertEquals("Bean context must contain at least one bean of type FilterSecurityInterceptor",
+ expected.getMessage());
+ }
+ }
+
+ public void testStartupDetectsMissingAppContextLocation()
+ throws Exception {
+ MockFilterConfig config = new MockFilterConfig();
+ config.setInitParmeter("loginFormUrl", "/login.jsp");
+
+ SecurityEnforcementFilter filter = new SecurityEnforcementFilter();
+
+ try {
+ filter.init(config);
+ fail("Should have thrown ServletException");
+ } catch (ServletException expected) {
+ assertEquals("appContextLocation must be specified",
+ expected.getMessage());
+ }
+
+ config.setInitParmeter("appContextLocation", "");
+
+ try {
+ filter.init(config);
+ fail("Should have thrown ServletException");
+ } catch (ServletException expected) {
+ assertEquals("appContextLocation must be specified",
+ expected.getMessage());
+ }
+ }
+
+ public void testStartupDetectsMissingInvalidAppContextLocation()
+ throws Exception {
+ MockFilterConfig config = new MockFilterConfig();
+ config.setInitParmeter("loginFormUrl", "/login.jsp");
+ config.setInitParmeter("appContextLocation", "DOES_NOT_EXIST");
+
+ SecurityEnforcementFilter filter = new SecurityEnforcementFilter();
+
+ try {
+ filter.init(config);
+ fail("Should have thrown ServletException");
+ } catch (ServletException expected) {
+ assertTrue(expected.getMessage().startsWith("Cannot locate"));
+ }
+ }
+
+ public void testStartupDetectsMissingLoginFormUrl()
+ throws Exception {
+ MockFilterConfig config = new MockFilterConfig();
+ config.setInitParmeter("appContextLocation",
+ "net/sf/acegisecurity/intercept/web/securityfiltertest-valid.xml");
+
+ SecurityEnforcementFilter filter = new SecurityEnforcementFilter();
+
+ try {
+ filter.init(config);
+ fail("Should have thrown ServletException");
+ } catch (ServletException expected) {
+ assertEquals("loginFormUrl must be specified", expected.getMessage());
+ }
+
+ config.setInitParmeter("loginFormUrl", "");
+
+ try {
+ filter.init(config);
+ fail("Should have thrown ServletException");
+ } catch (ServletException expected) {
+ assertEquals("loginFormUrl must be specified", expected.getMessage());
+ }
+ }
+
+ public void testSuccessfulAccessGrant() throws Exception {
+ // Setup our HTTP request
+ MockHttpServletRequest request = new MockHttpServletRequest(null,
+ new MockHttpSession());
+ request.setServletPath("/secure/page.html");
+
+ // Setup our expectation that the filter chain will be invoked, as access is granted
+ MockFilterChain chain = new MockFilterChain(true);
+
+ // Setup the FilterSecurityInterceptor to not thrown any exceptions
+ MockFilterSecurityInterceptor interceptor = new MockFilterSecurityInterceptor(false,
+ false);
+
+ // Test
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ SecurityEnforcementFilter filter = new MockSecurityEnforcementFilter(interceptor,
+ "/login.jsp");
+ filter.doFilter(request, response, chain);
+ }
+
+ public void testSuccessfulStartupAndShutdownDown()
+ throws Exception {
+ MockFilterConfig config = new MockFilterConfig();
+ config.setInitParmeter("appContextLocation",
+ "net/sf/acegisecurity/intercept/web/securityfiltertest-valid.xml");
+ config.setInitParmeter("loginFormUrl", "/login.jsp");
+
+ SecurityEnforcementFilter filter = new SecurityEnforcementFilter();
+
+ filter.init(config);
+ filter.destroy();
+ assertTrue(true);
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockFilterChain implements FilterChain {
+ private boolean expectToProceed;
+
+ public MockFilterChain(boolean expectToProceed) {
+ this.expectToProceed = expectToProceed;
+ }
+
+ private MockFilterChain() {
+ super();
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response)
+ throws IOException, ServletException {
+ if (expectToProceed) {
+ assertTrue(true);
+ } else {
+ fail("Did not expect filter chain to proceed");
+ }
+ }
+ }
+
+ private class MockFilterSecurityInterceptor
+ extends FilterSecurityInterceptor {
+ private boolean throwAccessDenied;
+ private boolean throwAuthenticationFailure;
+
+ public MockFilterSecurityInterceptor(boolean throwAccessDenied,
+ boolean throwAuthenticationFailure) {
+ this.throwAccessDenied = throwAccessDenied;
+ this.throwAuthenticationFailure = throwAuthenticationFailure;
+ }
+
+ private MockFilterSecurityInterceptor() {
+ super();
+ }
+
+ public void invoke(FilterInvocation fi) throws Throwable {
+ if (throwAccessDenied) {
+ throw new AccessDeniedException("As requested");
+ }
+
+ if (throwAuthenticationFailure) {
+ throw new BadCredentialsException("As requested");
+ }
+
+ fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
+ }
+ }
+
+ private class MockSecurityEnforcementFilter
+ extends SecurityEnforcementFilter {
+ public MockSecurityEnforcementFilter(
+ FilterSecurityInterceptor securityInterceptor, String loginFormUrl) {
+ super.securityInterceptor = securityInterceptor;
+ super.loginFormUrl = loginFormUrl;
+ }
+
+ private MockSecurityEnforcementFilter() {
+ super();
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml b/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml
new file mode 100644
index 0000000000..6409f0e4d0
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/intercept/web/securityfiltertest-invalid.xml
@@ -0,0 +1,37 @@
+
+
+
+
+