diff --git a/adapters/catalina/src/test/java/org/acegisecurity/adapters/catalina/CatalinaAcegiUserRealmTests.java b/adapters/catalina/src/test/java/org/acegisecurity/adapters/catalina/CatalinaAcegiUserRealmTests.java
new file mode 100644
index 0000000000..0876beff96
--- /dev/null
+++ b/adapters/catalina/src/test/java/org/acegisecurity/adapters/catalina/CatalinaAcegiUserRealmTests.java
@@ -0,0 +1,292 @@
+/* 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.adapters.catalina;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken;
+
+import org.apache.catalina.LifecycleException;
+
+import java.io.File;
+
+import java.net.URL;
+
+import java.security.Principal;
+
+
+/**
+ * Tests {@link CatalinaAcegiUserRealm}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class CatalinaAcegiUserRealmTests extends TestCase {
+ //~ Instance fields ========================================================
+
+ private final String ADAPTER_KEY = "my_key";
+
+ //~ Constructors ===========================================================
+
+ public CatalinaAcegiUserRealmTests() {
+ super();
+ }
+
+ public CatalinaAcegiUserRealmTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(CatalinaAcegiUserRealmTests.class);
+ }
+
+ public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean()
+ throws Exception {
+ try {
+ CatalinaAcegiUserRealm adapter = makeAdapter(
+ "adaptertest-invalid.xml");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAdapterAbortsIfNoAppContextSpecified()
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+
+ adapter.setKey("KEY");
+
+ try {
+ adapter.startForTest();
+ fail("Should have thrown LifecycleException");
+ } catch (LifecycleException expected) {
+ assertEquals("appContextLocation must be defined",
+ expected.getMessage());
+ }
+
+ adapter.setAppContextLocation("");
+
+ try {
+ adapter.startForTest();
+ fail("Should have thrown LifecycleException");
+ } catch (LifecycleException expected) {
+ assertEquals("appContextLocation must be defined",
+ expected.getMessage());
+ }
+ }
+
+ public void testAdapterAbortsIfNoKeySpecified() throws Exception {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+
+ adapter.setAppContextLocation("SOMETHING");
+
+ try {
+ adapter.startForTest();
+ fail("Should have thrown LifecycleException");
+ } catch (LifecycleException expected) {
+ assertEquals("key must be defined", expected.getMessage());
+ }
+
+ adapter.setKey("");
+
+ try {
+ adapter.startForTest();
+ fail("Should have thrown LifecycleException");
+ } catch (LifecycleException expected) {
+ assertEquals("key must be defined", expected.getMessage());
+ }
+ }
+
+ public void testAdapterAbortsWithIncorrectApplicationContextLocation()
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ adapter.setAppContextLocation("SOME_INVALID_PATH");
+ adapter.setKey("KEY");
+
+ try {
+ adapter.startForTest();
+ fail("Should have thrown LifecycleException");
+ } catch (LifecycleException expected) {
+ assertTrue(expected.getMessage().startsWith("appContextLocation does not seem to exist in"));
+ }
+ }
+
+ public void testAdapterIdentifiesItself() throws Exception {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ assertTrue(adapter.getName().lastIndexOf("CatalinaSpringUserRealm") != -1);
+ }
+
+ public void testAdapterStartsUpSuccess() throws Exception {
+ CatalinaAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertTrue(true);
+ }
+
+ public void testAuthenticateManyParamsReturnsNull() {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ assertEquals(null,
+ adapter.authenticate(null, null, null, null, null, null, null, null));
+ }
+
+ public void testAuthenticateX509ReturnsNull() {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ assertEquals(null, adapter.authenticate(null));
+ }
+
+ public void testAuthenticationFailsForIncorrectPassword()
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(null, adapter.authenticate("marissa", "kangaroo"));
+ }
+
+ public void testAuthenticationFailsForIncorrectUserName()
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(null, adapter.authenticate("melissa", "koala"));
+ }
+
+ public void testAuthenticationUsingByteArrayForCredentials()
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ byte[] credentials = {'k', 'o', 'a', 'l', 'a'};
+ Principal result = adapter.authenticate("marissa", credentials);
+
+ if (!(result instanceof PrincipalAcegiUserToken)) {
+ fail("Should have returned PrincipalAcegiUserToken");
+ }
+
+ PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
+ assertEquals("marissa", castResult.getPrincipal());
+ assertEquals("koala", castResult.getCredentials());
+ assertEquals("ROLE_TELLER",
+ castResult.getAuthorities()[0].getAuthority());
+ assertEquals("ROLE_SUPERVISOR",
+ castResult.getAuthorities()[1].getAuthority());
+ assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
+ }
+
+ public void testAuthenticationUsingStringForCredentials()
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ Principal result = adapter.authenticate("marissa", "koala");
+
+ if (!(result instanceof PrincipalAcegiUserToken)) {
+ fail("Should have returned PrincipalAcegiUserToken");
+ }
+
+ PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
+ assertEquals("marissa", castResult.getPrincipal());
+ assertEquals("koala", castResult.getCredentials());
+ assertEquals("ROLE_TELLER",
+ castResult.getAuthorities()[0].getAuthority());
+ assertEquals("ROLE_SUPERVISOR",
+ castResult.getAuthorities()[1].getAuthority());
+ assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
+ }
+
+ public void testAuthenticationWithNullPasswordHandledGracefully()
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(null, adapter.authenticate("marissa", (String) null));
+ }
+
+ public void testAuthenticationWithNullUserNameHandledGracefully()
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(null, adapter.authenticate(null, "koala"));
+ }
+
+ public void testGetPasswordReturnsNull() {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ assertEquals(null, adapter.getPassword(null));
+ }
+
+ public void testGetPrincipalReturnsNull() {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ assertEquals(null, adapter.getPrincipal(null));
+ }
+
+ public void testGetters() {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ adapter.setKey("KEY");
+ assertEquals("KEY", adapter.getKey());
+ adapter.setAppContextLocation("SOME_LOCATION");
+ assertEquals("SOME_LOCATION", adapter.getAppContextLocation());
+ }
+
+ public void testHasRoleWithANullPrincipalFails() {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ assertTrue(!adapter.hasRole(null, "ROLE_ONE"));
+ }
+
+ public void testHasRoleWithAPrincipalTheAdapterDidNotCreateFails() {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ assertTrue(!adapter.hasRole(new MockPrincipal(), "ROLE_ONE"));
+ }
+
+ public void testHasRoleWithPrincipalAcegiUserToken() {
+ PrincipalAcegiUserToken token = new PrincipalAcegiUserToken("KEY",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+ assertTrue(adapter.hasRole(token, "ROLE_ONE"));
+ assertTrue(adapter.hasRole(token, "ROLE_TWO"));
+ assertTrue(!adapter.hasRole(token, "ROLE_WE_DO_NOT_HAVE"));
+ }
+
+ private CatalinaAcegiUserRealm makeAdapter(String fileName)
+ throws Exception {
+ CatalinaAcegiUserRealm adapter = new CatalinaAcegiUserRealm();
+
+ URL url = ClassLoader.getSystemResource(
+ "net/sf/acegisecurity/adapters/" + fileName);
+
+ if (url == null) {
+ throw new Exception("Could not find " + fileName
+ + " - cannot continue");
+ }
+
+ File file = new File(url.getFile());
+
+ System.setProperty("catalina.base",
+ file.getParentFile().getAbsolutePath());
+ System.out.println("catalina.base set to: "
+ + System.getProperty("catalina.base"));
+ adapter.setAppContextLocation(fileName);
+ adapter.setKey(ADAPTER_KEY);
+ adapter.startForTest();
+
+ return adapter;
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockPrincipal implements Principal {
+ public String getName() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ }
+}
diff --git a/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/JbossAcegiLoginModuleTests.java b/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/JbossAcegiLoginModuleTests.java
new file mode 100644
index 0000000000..46a3fd4d51
--- /dev/null
+++ b/adapters/jboss/src/test/java/org/acegisecurity/adapters/jboss/JbossAcegiLoginModuleTests.java
@@ -0,0 +1,378 @@
+/* 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.adapters.jboss;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.adapters.PrincipalAcegiUserToken;
+
+import org.jboss.security.SimplePrincipal;
+
+import java.io.IOException;
+
+import java.security.Principal;
+import java.security.acl.Group;
+
+import java.util.Properties;
+
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.FailedLoginException;
+import javax.security.auth.login.LoginException;
+
+
+/**
+ * Tests {@link JbossAcegiLoginModule}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class JbossAcegiLoginModuleTests extends TestCase {
+ //~ Instance fields ========================================================
+
+ private final String ADAPTER_KEY = "my_key";
+
+ //~ Constructors ===========================================================
+
+ public JbossAcegiLoginModuleTests() {
+ super();
+ }
+
+ public JbossAcegiLoginModuleTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(JbossAcegiLoginModuleTests.class);
+ }
+
+ public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-invalid.xml");
+
+ try {
+ adapter.initialize(null, null, null, props);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAdapterAbortsIfNoAppContextSpecified()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+
+ try {
+ adapter.initialize(null, null, null, props);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("appContextLocation must be defined",
+ expected.getMessage());
+ }
+
+ props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation", "");
+
+ try {
+ adapter.initialize(null, null, null, props);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("appContextLocation must be defined",
+ expected.getMessage());
+ }
+ }
+
+ public void testAdapterAbortsIfNoKeySpecified() throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+
+ Properties props = new Properties();
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ try {
+ adapter.initialize(null, null, null, props);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("key must be defined", expected.getMessage());
+ }
+
+ props = new Properties();
+ props.put("key", "");
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ try {
+ adapter.initialize(null, null, null, props);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("key must be defined", expected.getMessage());
+ }
+ }
+
+ public void testAdapterAbortsWithIncorrectApplicationContextLocation()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation", "INVALID_PATH");
+
+ try {
+ adapter.initialize(null, null, null, props);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue("Cannot locate INVALID_PATH".equals(
+ expected.getMessage()));
+ }
+ }
+
+ public void testAdapterFailsToAuthenticateIfNoCallbackHandlerAvailable()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ Subject subject = new Subject();
+
+ adapter.initialize(subject, null, null, props);
+
+ try {
+ adapter.login();
+ } catch (LoginException loginException) {
+ assertEquals("Error: no CallbackHandler available to collect authentication information",
+ loginException.getMessage());
+ }
+ }
+
+ public void testAdapterStartsUpSuccess() throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+ adapter.initialize(null, null, null, props);
+ assertTrue(true);
+ }
+
+ public void testAuthenticationFailsForIncorrectPassword()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ Subject subject = new Subject();
+ CallbackHandler callback = new MockCallbackHandler("marissa", "kangaroo");
+
+ adapter.initialize(subject, callback, null, props);
+
+ try {
+ adapter.login();
+ fail("Should have thrown FailedLoginException");
+ } catch (FailedLoginException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticationFailsForIncorrectUserName()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ Subject subject = new Subject();
+ CallbackHandler callback = new MockCallbackHandler("melissa", "koala");
+
+ adapter.initialize(subject, callback, null, props);
+
+ try {
+ adapter.login();
+ fail("Should have thrown FailedLoginException");
+ } catch (FailedLoginException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticationSuccess() throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ Subject subject = new Subject();
+ CallbackHandler callback = new MockCallbackHandler("marissa", "koala");
+
+ adapter.initialize(subject, callback, null, props);
+ assertTrue(adapter.login());
+
+ Principal result = adapter.getIdentity();
+
+ if (!(result instanceof PrincipalAcegiUserToken)) {
+ fail("Should have returned PrincipalAcegiUserToken");
+ }
+
+ PrincipalAcegiUserToken castResult = (PrincipalAcegiUserToken) result;
+ assertEquals("marissa", castResult.getPrincipal());
+ assertEquals("koala", castResult.getCredentials());
+ assertEquals("ROLE_TELLER",
+ castResult.getAuthorities()[0].getAuthority());
+ assertEquals("ROLE_SUPERVISOR",
+ castResult.getAuthorities()[1].getAuthority());
+ assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
+ }
+
+ public void testAuthenticationWithNullPasswordHandledGracefully()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ Subject subject = new Subject();
+ CallbackHandler callback = new MockCallbackHandler("marissa", null);
+
+ adapter.initialize(subject, callback, null, props);
+
+ try {
+ adapter.login();
+ fail("Should have thrown FailedLoginException");
+ } catch (FailedLoginException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticationWithNullUserNameAndNullPasswordHandledGracefully()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ Subject subject = new Subject();
+ CallbackHandler callback = new MockCallbackHandler(null, null);
+
+ adapter.initialize(subject, callback, null, props);
+
+ try {
+ adapter.login();
+ fail("Should have thrown FailedLoginException");
+ } catch (FailedLoginException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testAuthenticationWithNullUserNameHandledGracefully()
+ throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ Subject subject = new Subject();
+ CallbackHandler callback = new MockCallbackHandler(null, "kangaroo");
+
+ adapter.initialize(subject, callback, null, props);
+
+ try {
+ adapter.login();
+ fail("Should have thrown FailedLoginException");
+ } catch (FailedLoginException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testGetRoleSets() throws Exception {
+ JbossAcegiLoginModule adapter = new JbossAcegiLoginModule();
+ Properties props = new Properties();
+ props.put("key", ADAPTER_KEY);
+ props.put("appContextLocation",
+ "net/sf/acegisecurity/adapters/adaptertest-valid.xml");
+
+ Subject subject = new Subject();
+ CallbackHandler callback = new MockCallbackHandler("marissa", "koala");
+
+ adapter.initialize(subject, callback, null, props);
+ assertTrue(adapter.login());
+
+ Group[] result = adapter.getRoleSets();
+ assertEquals(1, result.length); // SimpleGroup called "Roles"
+
+ Group roles = result[0];
+ assertTrue(roles.isMember(new SimplePrincipal("ROLE_TELLER")));
+ assertTrue(roles.isMember(new SimplePrincipal("ROLE_SUPERVISOR")));
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockCallbackHandler implements CallbackHandler {
+ private String password;
+ private String username;
+
+ public MockCallbackHandler(String username, String password) {
+ this.username = username;
+ this.password = password;
+ }
+
+ private MockCallbackHandler() {
+ super();
+ }
+
+ public void handle(Callback[] callbacks)
+ throws IOException, UnsupportedCallbackException {
+ for (int i = 0; i < callbacks.length; i++) {
+ if (callbacks[i] instanceof NameCallback) {
+ ((NameCallback) callbacks[i]).setName(username);
+ } else if (callbacks[i] instanceof PasswordCallback) {
+ if (this.password == null) {
+ ((PasswordCallback) callbacks[i]).setPassword(null);
+ } else {
+ ((PasswordCallback) callbacks[i]).setPassword(password
+ .toCharArray());
+ }
+ } else {
+ throw new UnsupportedCallbackException(callbacks[i]);
+ }
+ }
+ }
+ }
+}
diff --git a/adapters/jetty/src/test/java/org/acegisecurity/adapters/jetty/JettyAcegiUserRealmTests.java b/adapters/jetty/src/test/java/org/acegisecurity/adapters/jetty/JettyAcegiUserRealmTests.java
new file mode 100644
index 0000000000..16e89b354f
--- /dev/null
+++ b/adapters/jetty/src/test/java/org/acegisecurity/adapters/jetty/JettyAcegiUserRealmTests.java
@@ -0,0 +1,245 @@
+/* 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.adapters.jetty;
+
+import junit.framework.TestCase;
+
+import org.mortbay.http.UserPrincipal;
+
+
+/**
+ * Tests {@link JettyAcegiUserRealm}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class JettyAcegiUserRealmTests extends TestCase {
+ //~ Instance fields ========================================================
+
+ private final String ADAPTER_KEY = "my_key";
+ private final String REALM_NAME = "Acegi Powered Realm";
+
+ //~ Constructors ===========================================================
+
+ public JettyAcegiUserRealmTests() {
+ super();
+ }
+
+ public JettyAcegiUserRealmTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(JettyAcegiUserRealmTests.class);
+ }
+
+ public void testAdapterAbortsIfAppContextDoesNotContainAnAuthenticationBean()
+ throws Exception {
+ try {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-invalid.xml");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("Bean context must contain at least one bean of type AuthenticationManager",
+ expected.getMessage());
+ }
+ }
+
+ public void testAdapterAbortsIfNoAppContextSpecified()
+ throws Exception {
+ try {
+ new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, null);
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("appContextLocation must be specified",
+ expected.getMessage());
+ }
+
+ try {
+ new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, "");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("appContextLocation must be specified",
+ expected.getMessage());
+ }
+ }
+
+ public void testAdapterAbortsIfNoKeySpecified() throws Exception {
+ try {
+ new JettyAcegiUserRealm(REALM_NAME, null, "SOME_PATH");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("key must be specified", expected.getMessage());
+ }
+
+ try {
+ new JettyAcegiUserRealm(REALM_NAME, "", "SOME_PATH");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("key must be specified", expected.getMessage());
+ }
+ }
+
+ public void testAdapterAbortsIfNoRealmNameSpecified()
+ throws Exception {
+ try {
+ new JettyAcegiUserRealm(null, ADAPTER_KEY, "SOME_PATH");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("realm must be specified", expected.getMessage());
+ }
+
+ try {
+ new JettyAcegiUserRealm(null, ADAPTER_KEY, "SOME_PATH");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertEquals("realm must be specified", expected.getMessage());
+ }
+ }
+
+ public void testAdapterAbortsWithIncorrectApplicationContextLocation()
+ throws Exception {
+ try {
+ new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY,
+ "SOME_INVALID_LOCATION");
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(expected.getMessage().startsWith("Cannot locate"));
+ }
+ }
+
+ public void testAdapterIdentifiesTheRealmItManages()
+ throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(REALM_NAME, adapter.getName());
+ }
+
+ public void testAdapterStartsUpSuccess() throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertTrue(true);
+ }
+
+ public void testAuthenticationFailsForIncorrectPassword()
+ throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(null, adapter.authenticate("marissa", "kangaroo", null));
+ }
+
+ public void testAuthenticationFailsForIncorrectUserName()
+ throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(null, adapter.authenticate("melissa", "koala", null));
+ }
+
+ public void testAuthenticationSuccess() throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ UserPrincipal result = adapter.authenticate("marissa", "koala", null);
+
+ if (!(result instanceof JettyAcegiUserToken)) {
+ fail("Should have returned JettyAcegiUserToken");
+ }
+
+ JettyAcegiUserToken castResult = (JettyAcegiUserToken) result;
+ assertEquals("marissa", castResult.getPrincipal());
+ assertEquals("koala", castResult.getCredentials());
+ assertEquals("ROLE_TELLER",
+ castResult.getAuthorities()[0].getAuthority());
+ assertEquals("ROLE_SUPERVISOR",
+ castResult.getAuthorities()[1].getAuthority());
+ assertEquals(ADAPTER_KEY.hashCode(), castResult.getKeyHash());
+ }
+
+ public void testAuthenticationWithNullPasswordHandledGracefully()
+ throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(null, adapter.authenticate("marissa", null, null));
+ }
+
+ public void testAuthenticationWithNullUserNameHandledGracefully()
+ throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertEquals(null, adapter.authenticate(null, "koala", null));
+ }
+
+ public void testDisassociateImplemented() throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ adapter.disassociate(new MockUserPrincipal());
+ assertTrue(true);
+ }
+
+ public void testGetAuthenticationManager() throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ assertTrue(adapter.getAuthenticationManager() != null);
+ }
+
+ public void testLogoutImplemented() throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ adapter.logout(new MockUserPrincipal());
+ assertTrue(true);
+ }
+
+ public void testNoArgsConstructor() {
+ try {
+ new JettyAcegiUserRealm();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testPopRoleImplemented() throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ MockUserPrincipal user = new MockUserPrincipal();
+ assertEquals(user, adapter.popRole(user));
+ }
+
+ public void testPushRoleImplemented() throws Exception {
+ JettyAcegiUserRealm adapter = makeAdapter("adaptertest-valid.xml");
+ MockUserPrincipal user = new MockUserPrincipal();
+ assertEquals(user, adapter.pushRole(user, "SOME_ROLE"));
+ }
+
+ private JettyAcegiUserRealm makeAdapter(String fileName)
+ throws Exception {
+ String useFile = "net/sf/acegisecurity/adapters/" + fileName;
+
+ return new JettyAcegiUserRealm(REALM_NAME, ADAPTER_KEY, useFile);
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockUserPrincipal implements UserPrincipal {
+ public boolean isAuthenticated() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public String getName() {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+
+ public boolean isUserInRole(String arg0) {
+ throw new UnsupportedOperationException(
+ "mock method not implemented");
+ }
+ }
+}
diff --git a/ant.bat b/ant.bat
new file mode 100644
index 0000000000..4bcbeeb144
--- /dev/null
+++ b/ant.bat
@@ -0,0 +1,2 @@
+%JAVA_HOME%/bin/java -cp lib/ant/ant.jar;lib/ant/ant-launcher.jar;lib/ant/ant-junit.jar;lib/junit/junit.jar;lib/clover/clover.jar;%JAVA_HOME%/lib/tools.jar org.apache.tools.ant.Main %1 %2 %3 %4 %5 %6 %7 %8
+
diff --git a/core/src/main/resources/log4j.properties b/core/src/main/resources/log4j.properties
new file mode 100644
index 0000000000..6f21872912
--- /dev/null
+++ b/core/src/main/resources/log4j.properties
@@ -0,0 +1,11 @@
+# Logging
+#
+# $Id$
+
+log4j.rootCategory=WARN, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d %p %c - %m%n
+
+log4j.category.net.sf.acegisecurity=DEBUG
diff --git a/core/src/test/java/org/acegisecurity/ConfigAttributeEditorTests.java b/core/src/test/java/org/acegisecurity/ConfigAttributeEditorTests.java
new file mode 100644
index 0000000000..5f3c89a492
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/ConfigAttributeEditorTests.java
@@ -0,0 +1,137 @@
+/* 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 junit.framework.TestCase;
+
+import java.util.Iterator;
+
+
+/**
+ * Tests {@link ConfigAttributeEditor} and associated {@link
+ * ConfigAttributeDefinition}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class ConfigAttributeEditorTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public ConfigAttributeEditorTests() {
+ super();
+ }
+
+ public ConfigAttributeEditorTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(ConfigAttributeEditorTests.class);
+ }
+
+ public void testCorrectOperation() {
+ ConfigAttributeEditor editor = new ConfigAttributeEditor();
+ editor.setAsText("HELLO,DOCTOR,NAME,YESTERDAY,TOMORROW");
+
+ ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor
+ .getValue();
+ Iterator iter = result.getConfigAttributes();
+ int position = 0;
+
+ while (iter.hasNext()) {
+ position++;
+ iter.next();
+ }
+
+ assertEquals(5, position);
+ }
+
+ public void testEmptyStringReturnsNull() {
+ ConfigAttributeEditor editor = new ConfigAttributeEditor();
+ editor.setAsText("");
+
+ ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor
+ .getValue();
+ assertTrue(result == null);
+ }
+
+ public void testEqualsHandlingWhenDifferentObjectTypes() {
+ ConfigAttributeDefinition def1 = new ConfigAttributeDefinition();
+ def1.addConfigAttribute(new SecurityConfig("A"));
+ def1.addConfigAttribute(new SecurityConfig("B"));
+
+ assertTrue(!def1.equals("A_STRING"));
+ }
+
+ public void testEqualsHandlingWhenExactlyEqual() {
+ ConfigAttributeDefinition def1 = new ConfigAttributeDefinition();
+ def1.addConfigAttribute(new SecurityConfig("A"));
+ def1.addConfigAttribute(new SecurityConfig("B"));
+
+ ConfigAttributeDefinition def2 = new ConfigAttributeDefinition();
+ def2.addConfigAttribute(new SecurityConfig("A"));
+ def2.addConfigAttribute(new SecurityConfig("B"));
+
+ assertEquals(def1, def2);
+ }
+
+ public void testEqualsHandlingWhenOrderingNotEqual() {
+ ConfigAttributeDefinition def1 = new ConfigAttributeDefinition();
+ def1.addConfigAttribute(new SecurityConfig("A"));
+ def1.addConfigAttribute(new SecurityConfig("B"));
+
+ ConfigAttributeDefinition def2 = new ConfigAttributeDefinition();
+ def2.addConfigAttribute(new SecurityConfig("B"));
+ def2.addConfigAttribute(new SecurityConfig("A"));
+
+ assertTrue(!def1.equals(def2));
+ }
+
+ public void testEqualsHandlingWhenTestObjectHasNoAttributes() {
+ ConfigAttributeDefinition def1 = new ConfigAttributeDefinition();
+ def1.addConfigAttribute(new SecurityConfig("A"));
+ def1.addConfigAttribute(new SecurityConfig("B"));
+
+ ConfigAttributeDefinition def2 = new ConfigAttributeDefinition();
+
+ assertTrue(!def1.equals(def2));
+ assertTrue(!def2.equals(def1));
+ }
+
+ public void testNullReturnsNull() {
+ ConfigAttributeEditor editor = new ConfigAttributeEditor();
+ editor.setAsText(null);
+
+ ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor
+ .getValue();
+ assertTrue(result == null);
+ }
+
+ public void testToString() {
+ ConfigAttributeEditor editor = new ConfigAttributeEditor();
+ editor.setAsText("KOALA,KANGAROO,EMU,WOMBAT");
+
+ ConfigAttributeDefinition result = (ConfigAttributeDefinition) editor
+ .getValue();
+ assertEquals("[KOALA, KANGAROO, EMU, WOMBAT]", result.toString());
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/ITargetObject.java b/core/src/test/java/org/acegisecurity/ITargetObject.java
new file mode 100644
index 0000000000..a58ff0b71c
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/ITargetObject.java
@@ -0,0 +1,34 @@
+/* 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;
+
+/**
+ * Represents the interface of a secured object.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public interface ITargetObject {
+ //~ Methods ================================================================
+
+ public int countLength(String input);
+
+ public String makeLowerCase(String input);
+
+ public String makeUpperCase(String input);
+
+ public String publicMakeLowerCase(String input);
+}
diff --git a/core/src/test/java/org/acegisecurity/MethodDefinitionAttributesTests.java b/core/src/test/java/org/acegisecurity/MethodDefinitionAttributesTests.java
new file mode 100644
index 0000000000..0e8efdef43
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MethodDefinitionAttributesTests.java
@@ -0,0 +1,305 @@
+/* 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 junit.framework.TestCase;
+
+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.aopalliance.intercept.MethodInvocation;
+
+import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.beans.factory.support.PropertiesBeanDefinitionReader;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+import java.lang.reflect.AccessibleObject;
+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
+ */
+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.MockAttributes");
+
+ p.setProperty(PREFIX + "methodDefinitionSource.class",
+ "net.sf.acegisecurity.MethodDefinitionAttributes");
+ p.setProperty(PREFIX + "methodDefinitionSource.attributes(ref)",
+ "attributes");
+
+ p.setProperty(PREFIX + "securityInterceptor.class",
+ "net.sf.acegisecurity.SecurityInterceptor");
+ 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.methodDefinitionSource(ref)",
+ "methodDefinitionSource");
+
+ 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;
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockMethodInvocation implements MethodInvocation {
+ 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/MethodDefinitionSourceEditorTests.java b/core/src/test/java/org/acegisecurity/MethodDefinitionSourceEditorTests.java
new file mode 100644
index 0000000000..474cf59202
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MethodDefinitionSourceEditorTests.java
@@ -0,0 +1,215 @@
+/* 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 junit.framework.TestCase;
+
+import org.aopalliance.intercept.MethodInvocation;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Method;
+
+import java.util.Iterator;
+
+
+/**
+ * Tests {@link MethodDefinitionSourceEditor}.
+ *
+ * @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/MockAccessDecisionManager.java b/core/src/test/java/org/acegisecurity/MockAccessDecisionManager.java
new file mode 100644
index 0000000000..1e082dcd20
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockAccessDecisionManager.java
@@ -0,0 +1,62 @@
+/* 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.util.Iterator;
+
+
+/**
+ * Grants access if the user holds any of the authorities listed in the
+ * configuration attributes starting with "MOCK_".
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockAccessDecisionManager implements AccessDecisionManager {
+ //~ Methods ================================================================
+
+ public void decide(Authentication authentication,
+ MethodInvocation invocation, ConfigAttributeDefinition config)
+ throws AccessDeniedException {
+ Iterator iter = config.getConfigAttributes();
+
+ while (iter.hasNext()) {
+ ConfigAttribute attr = (ConfigAttribute) iter.next();
+
+ if (this.supports(attr)) {
+ for (int i = 0; i < authentication.getAuthorities().length;
+ i++) {
+ if (attr.getAttribute().equals(authentication
+ .getAuthorities()[i].getAuthority())) {
+ return;
+ }
+ }
+ }
+ }
+
+ throw new AccessDeniedException("Didn't hold required authority");
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ if (attribute.getAttribute().startsWith("MOCK_")) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/MockAttributes.java b/core/src/test/java/org/acegisecurity/MockAttributes.java
new file mode 100644
index 0000000000..5db4e10ea4
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockAttributes.java
@@ -0,0 +1,155 @@
+/* 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.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/MockAuthenticationManager.java b/core/src/test/java/org/acegisecurity/MockAuthenticationManager.java
new file mode 100644
index 0000000000..33fa59d2ca
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockAuthenticationManager.java
@@ -0,0 +1,31 @@
+/* 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;
+
+/**
+ * Simply accepts as valid whatever is passed to it.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockAuthenticationManager implements AuthenticationManager {
+ //~ Methods ================================================================
+
+ public Authentication authenticate(Authentication authentication)
+ throws AuthenticationException {
+ return authentication;
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/MockRunAsAuthenticationToken.java b/core/src/test/java/org/acegisecurity/MockRunAsAuthenticationToken.java
new file mode 100644
index 0000000000..9424150ffa
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockRunAsAuthenticationToken.java
@@ -0,0 +1,54 @@
+/* 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 net.sf.acegisecurity.providers.AbstractAuthenticationToken;
+
+
+/**
+ * Simple holder that indicates the {@link MockRunAsManager} returned a
+ * different Authentication
object.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockRunAsAuthenticationToken extends AbstractAuthenticationToken {
+ //~ Instance fields ========================================================
+
+ private boolean authenticated = false;
+
+ //~ Methods ================================================================
+
+ public void setAuthenticated(boolean isAuthenticated) {
+ authenticated = isAuthenticated;
+ }
+
+ public boolean isAuthenticated() {
+ return authenticated;
+ }
+
+ public GrantedAuthority[] getAuthorities() {
+ return null;
+ }
+
+ public Object getCredentials() {
+ return null;
+ }
+
+ public Object getPrincipal() {
+ return null;
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/MockRunAsManager.java b/core/src/test/java/org/acegisecurity/MockRunAsManager.java
new file mode 100644
index 0000000000..6c432e9f7e
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/MockRunAsManager.java
@@ -0,0 +1,58 @@
+/* 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.util.Iterator;
+
+
+/**
+ * Returns a new run-as identity if configuration attribute RUN_AS is found.
+ * The new identity is simply an empty {@link MockRunAsAuthenticationToken}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class MockRunAsManager implements RunAsManager {
+ //~ Methods ================================================================
+
+ public Authentication buildRunAs(Authentication authentication,
+ MethodInvocation invocation, ConfigAttributeDefinition config) {
+ Iterator iter = config.getConfigAttributes();
+
+ while (iter.hasNext()) {
+ ConfigAttribute attr = (ConfigAttribute) iter.next();
+
+ if (this.supports(attr)) {
+ Authentication response = new MockRunAsAuthenticationToken();
+ response.setAuthenticated(true);
+
+ return response;
+ }
+ }
+
+ return null;
+ }
+
+ public boolean supports(ConfigAttribute attribute) {
+ if ("RUN_AS".equals(attribute.getAttribute())) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/OtherTargetObject.java b/core/src/test/java/org/acegisecurity/OtherTargetObject.java
new file mode 100644
index 0000000000..58a45f6c05
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/OtherTargetObject.java
@@ -0,0 +1,56 @@
+/* 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;
+
+/**
+ * Simply extends {@link TargetObject} so we have a different object to put
+ * configuration attributes against.
+ *
+ *
+ * There is no different behaviour. We have to define each method so that
+ * Class.getMethod(methodName, args)
returns a
+ * Method
referencing this class rather than the parent class.
+ *
+ * We need to implement ITargetObject
again because the
+ * MethodDefinitionAttributes
only locates attributes on
+ * interfaces explicitly defined by the intercepted class (not the interfaces
+ * defined by its parent class or classes).
+ *
Authentication
+ * class that was on the ContextHolder
at the time of
+ * method invocation, and a boolean indicating if the
+ * Authentication
object is authenticated or not
+ */
+ public String makeLowerCase(String input) {
+ Context context = ContextHolder.getContext();
+
+ if ((context != null) && (context instanceof SecureContext)) {
+ Authentication auth = ((SecureContext) context).getAuthentication();
+
+ if (auth == null) {
+ return input.toLowerCase() + " Authentication empty";
+ } else {
+ return input.toLowerCase() + " " + auth.getClass().getName()
+ + " " + auth.isAuthenticated();
+ }
+ } else {
+ return input.toLowerCase() + " ContextHolder Not Security Aware";
+ }
+ }
+
+ /**
+ * Returns the uppercase string, followed by security environment
+ * information.
+ *
+ * @param input the message to make uppercase
+ *
+ * @return the uppercase message, a space, the Authentication
+ * class that was on the ContextHolder
at the time of
+ * method invocation, and a boolean indicating if the
+ * Authentication
object is authenticated or not
+ *
+ * @throws AccessDeniedException if for some reason this method was being
+ * called and the ContextHolder
was null
+ * or did not hold a SecureContext
+ */
+ public String makeUpperCase(String input) {
+ Context context = ContextHolder.getContext();
+
+ if ((context == null) || !(context instanceof SecureContext)) {
+ throw new AccessDeniedException(
+ "For some reason the SecurityInterceptor allowed this call, meaning the ContextHolder should have been populated, but it was not.");
+ }
+
+ Authentication auth = ((SecureContext) context).getAuthentication();
+
+ return input.toUpperCase() + " " + auth.getClass().getName() + " "
+ + auth.isAuthenticated();
+ }
+
+ /**
+ * Delegates through to the {@link #toLowerCase(String)} method.
+ *
+ * @param input the method to be made uppercase
+ *
+ * @return
+ */
+ public String publicMakeLowerCase(String input) {
+ return this.makeLowerCase(input);
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/adapters/AbstractAdapterAuthenticationTokenTests.java b/core/src/test/java/org/acegisecurity/adapters/AbstractAdapterAuthenticationTokenTests.java
new file mode 100644
index 0000000000..a406cf064d
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/adapters/AbstractAdapterAuthenticationTokenTests.java
@@ -0,0 +1,163 @@
+/* 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.adapters;
+
+import junit.framework.TestCase;
+
+import net.sf.acegisecurity.GrantedAuthority;
+import net.sf.acegisecurity.GrantedAuthorityImpl;
+
+
+/**
+ * Tests {@link AbstractAdapterAuthenticationToken}.
+ *
+ * @author Ben Alex
+ * @version $Id$
+ */
+public class AbstractAdapterAuthenticationTokenTests extends TestCase {
+ //~ Constructors ===========================================================
+
+ public AbstractAdapterAuthenticationTokenTests() {
+ super();
+ }
+
+ public AbstractAdapterAuthenticationTokenTests(String arg0) {
+ super(arg0);
+ }
+
+ //~ Methods ================================================================
+
+ public final void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AbstractAdapterAuthenticationTokenTests.class);
+ }
+
+ public void testGetters() throws Exception {
+ MockDecisionManagerImpl token = new MockDecisionManagerImpl("my_password",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ assertEquals("Test", token.getPrincipal());
+ assertEquals("Password", token.getCredentials());
+ assertEquals("my_password".hashCode(), token.getKeyHash());
+ }
+
+ public void testIsUserInRole() throws Exception {
+ MockDecisionManagerImpl token = new MockDecisionManagerImpl("my_password",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ assertTrue(token.isUserInRole("ROLE_ONE"));
+ assertTrue(token.isUserInRole("ROLE_TWO"));
+ assertTrue(!token.isUserInRole(""));
+ assertTrue(!token.isUserInRole("ROLE_ONE "));
+ assertTrue(!token.isUserInRole("role_one"));
+ assertTrue(!token.isUserInRole("ROLE_XXXX"));
+ }
+
+ public void testNoArgsConstructor() {
+ try {
+ new MockDecisionManagerImpl();
+ fail("Should have thrown IllegalArgumentException");
+ } catch (IllegalArgumentException expected) {
+ assertTrue(true);
+ }
+ }
+
+ public void testObjectsEquals() throws Exception {
+ MockDecisionManagerImpl token1 = new MockDecisionManagerImpl("my_password",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ MockDecisionManagerImpl token2 = new MockDecisionManagerImpl("my_password",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ assertEquals(token1, token2);
+
+ MockDecisionManagerImpl token3 = new MockDecisionManagerImpl("my_password",
+ "Test", "Password_Changed",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ assertTrue(!token1.equals(token3));
+
+ MockDecisionManagerImpl token4 = new MockDecisionManagerImpl("my_password",
+ "Test_Changed", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ assertTrue(!token1.equals(token4));
+
+ MockDecisionManagerImpl token5 = new MockDecisionManagerImpl("password_changed",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ assertTrue(!token1.equals(token5));
+
+ MockDecisionManagerImpl token6 = new MockDecisionManagerImpl("my_password",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO_CHANGED")});
+ assertTrue(!token1.equals(token6));
+
+ MockDecisionManagerImpl token7 = new MockDecisionManagerImpl("my_password",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE")});
+ assertTrue(!token1.equals(token7));
+
+ assertTrue(!token1.equals(new Integer(100)));
+ }
+
+ public void testSetAuthenticatedAlwaysReturnsTrue()
+ throws Exception {
+ MockDecisionManagerImpl token = new MockDecisionManagerImpl("my_password",
+ "Test", "Password",
+ new GrantedAuthority[] {new GrantedAuthorityImpl("ROLE_ONE"), new GrantedAuthorityImpl(
+ "ROLE_TWO")});
+ assertTrue(token.isAuthenticated());
+ token.setAuthenticated(false);
+ assertTrue(token.isAuthenticated());
+ }
+
+ //~ Inner Classes ==========================================================
+
+ private class MockDecisionManagerImpl
+ extends AbstractAdapterAuthenticationToken {
+ private String password;
+ private String username;
+
+ public MockDecisionManagerImpl(String key, String username,
+ String password, GrantedAuthority[] authorities) {
+ super(key, authorities);
+ this.username = username;
+ this.password = password;
+ }
+
+ private MockDecisionManagerImpl() {
+ throw new IllegalArgumentException();
+ }
+
+ public Object getCredentials() {
+ return this.password;
+ }
+
+ public Object getPrincipal() {
+ return this.username;
+ }
+ }
+}
diff --git a/core/src/test/java/org/acegisecurity/adapters/adaptertest-invalid.xml b/core/src/test/java/org/acegisecurity/adapters/adaptertest-invalid.xml
new file mode 100644
index 0000000000..d2d53302fa
--- /dev/null
+++ b/core/src/test/java/org/acegisecurity/adapters/adaptertest-invalid.xml
@@ -0,0 +1,38 @@
+
+
+
+
+