[dna-commits] DNA SVN: r983 - in trunk: dna-graph/src/main/java/org/jboss/dna/graph/observe and 7 other directories.

dna-commits at lists.jboss.org dna-commits at lists.jboss.org
Sat Jun 6 16:34:20 EDT 2009


Author: bcarothers
Date: 2009-06-06 16:34:20 -0400 (Sat, 06 Jun 2009)
New Revision: 983

Added:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/JaasSecurityContext.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/SecurityContext.java
   trunk/dna-graph/src/test/java/org/jboss/dna/graph/MockSecurityContext.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SecurityContextCredentials.java
Modified:
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/observe/Changes.java
   trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
   trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
   trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
   trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
   trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceIntegrationTest.java
   trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
Log:
Applied patch that takes first step towards integrating the security by refactoring the existing security from ExecutionContext proper into a new interface called o.j.d.graph.SecurityContext. The existing JAAS code moves into an implementation of SecurityContext called JaasSecurityContext and JcrSession can now accept a new type of Credentials called o.j.d.jcr.SecurityContextCredentials that wraps an existing SecurityContext.

Next step is to create a SecurityContext class that wraps HttpServletRequest to be able to derive the user name and role information directly from the request and modify JcrResource to accept the new SecurityContext class.
[ Show ?\194?\187 ]
Brian Carothers - 06/Jun/09 04:33 PM Attached and applied patch that takes first step towards integrating the security by refactoring the existing security from ExecutionContext proper into a new interface called o.j.d.graph.SecurityContext. The existing JAAS code moves into an implementation of SecurityContext called JaasSecurityContext and JcrSession can now accept a new type of Credentials called o.j.d.jcr.SecurityContextCredentials that wraps an existing SecurityContext. Next step is to create a SecurityContext class that wraps HttpServletRequest to be able to derive the user name and role information directly from the request and modify JcrResource to accept the new SecurityContext class.


Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/ExecutionContext.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -23,26 +23,14 @@
  */
 package org.jboss.dna.graph;
 
-import java.io.IOException;
 import java.security.AccessControlContext;
 import java.security.AccessController;
-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.TextOutputCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.login.Configuration;
-import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
-import javax.security.auth.spi.LoginModule;
 import net.jcip.annotations.Immutable;
 import org.jboss.dna.common.component.ClassLoaderFactory;
 import org.jboss.dna.common.component.StandardClassLoaderFactory;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.common.util.Logger;
-import org.jboss.dna.common.util.Reflection;
 import org.jboss.dna.graph.connector.federation.FederatedLexicon;
 import org.jboss.dna.graph.mimetype.ExtensionBasedMimeTypeDetector;
 import org.jboss.dna.graph.mimetype.MimeTypeDetector;
@@ -64,7 +52,7 @@
  * ExecutionContext instances are {@link Immutable immutable}, so components may hold onto references to them without concern of
  * those contexts changing. Contexts may be used to create other contexts that vary the environment and/or security context. For
  * example, an ExecutionContext could be used to create another context that references the same {@link #getNamespaceRegistry()
- * namespace registry} but which has a different {@link #getSubject() JAAS subject}.
+ * namespace registry} but which has a different {@link #getSecurityContext() security context}.
  * </p>
  * 
  * @author Randall Hauch
@@ -74,13 +62,11 @@
 public class ExecutionContext implements ClassLoaderFactory, Cloneable {
 
     private final ClassLoaderFactory classLoaderFactory;
-    private final LoginContext loginContext;
-    private final AccessControlContext accessControlContext;
-    private final Subject subject;
     private final PropertyFactory propertyFactory;
     private final ValueFactories valueFactories;
     private final NamespaceRegistry namespaceRegistry;
     private final MimeTypeDetector mimeTypeDetector;
+    private final SecurityContext securityContext;
 
     /**
      * Create an instance of an execution context that uses the {@link AccessController#getContext() current JAAS calling context}
@@ -88,8 +74,10 @@
      * {@link #getNamespaceRegistry() namespace registry}.
      */
     public ExecutionContext() {
-        this(null, null, null, null, null, null, null);
+        this(new NullSecurityContext(), null, null, null, null, null);
         initializeDefaultNamespaces(this.getNamespaceRegistry());
+        assert securityContext != null;
+
     }
 
     /**
@@ -100,9 +88,7 @@
      */
     protected ExecutionContext( ExecutionContext original ) {
         CheckArg.isNotNull(original, "original");
-        this.loginContext = original.getLoginContext();
-        this.accessControlContext = original.getAccessControlContext();
-        this.subject = original.getSubject();
+        this.securityContext = original.getSecurityContext();
         this.namespaceRegistry = original.getNamespaceRegistry();
         this.valueFactories = original.getValueFactories();
         this.propertyFactory = original.getPropertyFactory();
@@ -114,16 +100,14 @@
      * Create a copy of the supplied execution context, but use the supplied {@link AccessControlContext} instead.
      * 
      * @param original the original
-     * @param accessControlContext the access control context
+     * @param securityContext the security context
      * @throws IllegalArgumentException if the original or access control context are is null
      */
     protected ExecutionContext( ExecutionContext original,
-                                AccessControlContext accessControlContext ) {
+                                SecurityContext securityContext ) {
         CheckArg.isNotNull(original, "original");
-        CheckArg.isNotNull(accessControlContext, "accessControlContext");
-        this.loginContext = null;
-        this.accessControlContext = accessControlContext;
-        this.subject = Subject.getSubject(this.accessControlContext);
+        CheckArg.isNotNull(securityContext, "securityContext");
+        this.securityContext = securityContext;
         this.namespaceRegistry = original.getNamespaceRegistry();
         this.valueFactories = original.getValueFactories();
         this.propertyFactory = original.getPropertyFactory();
@@ -132,33 +116,9 @@
     }
 
     /**
-     * Create a copy of the supplied execution context, but use the supplied {@link LoginContext} instead.
-     * 
-     * @param original the original
-     * @param loginContext the login context
-     * @throws IllegalArgumentException if the original or login context are is null
-     */
-    protected ExecutionContext( ExecutionContext original,
-                                LoginContext loginContext ) {
-        CheckArg.isNotNull(original, "original");
-        CheckArg.isNotNull(loginContext, "loginContext");
-        this.loginContext = loginContext;
-        this.accessControlContext = null;
-        this.subject = this.loginContext.getSubject();
-        this.namespaceRegistry = original.getNamespaceRegistry();
-        this.valueFactories = original.getValueFactories();
-        this.propertyFactory = original.getPropertyFactory();
-        this.classLoaderFactory = original.getClassLoaderFactory();
-        this.mimeTypeDetector = original.getMimeTypeDetector();
-    }
-
-    /**
      * Create an instance of the execution context by supplying all parameters.
      * 
-     * @param loginContext the login context, or null if the {@link #getSubject() subject} is to be retrieved from the
-     *        {@link AccessController#getContext() current calling context}.
-     * @param accessControlContext the access control context, or null if a {@link LoginContext} is provided or if the
-     *        {@link AccessController#getContext() current calling context} should be used
+     * @param securityContext the security context, or null if there is no associated authenticated user
      * @param namespaceRegistry the namespace registry implementation, or null if a thread-safe version of
      *        {@link SimpleNamespaceRegistry} instance should be used
      * @param valueFactories the {@link ValueFactories} implementation, or null if a {@link StandardValueFactories} instance
@@ -170,20 +130,14 @@
      * @param classLoaderFactory the {@link ClassLoaderFactory} implementation, or null if a {@link StandardClassLoaderFactory}
      *        instance should be used
      */
-    protected ExecutionContext( LoginContext loginContext,
-                                AccessControlContext accessControlContext,
+    protected ExecutionContext( SecurityContext securityContext,
                                 NamespaceRegistry namespaceRegistry,
                                 ValueFactories valueFactories,
                                 PropertyFactory propertyFactory,
                                 MimeTypeDetector mimeTypeDetector,
                                 ClassLoaderFactory classLoaderFactory ) {
-        this.loginContext = loginContext;
-        this.accessControlContext = accessControlContext;
-        if (loginContext == null) {
-            this.subject = Subject.getSubject(accessControlContext == null ? AccessController.getContext() : accessControlContext);
-        } else {
-            this.subject = loginContext.getSubject();
-        }
+        assert securityContext != null;
+        this.securityContext = securityContext;
         this.namespaceRegistry = namespaceRegistry != null ? namespaceRegistry : new ThreadSafeNamespaceRegistry(
                                                                                                                  new SimpleNamespaceRegistry());
         this.valueFactories = valueFactories == null ? new StandardValueFactories(this.namespaceRegistry) : valueFactories;
@@ -237,24 +191,15 @@
     }
 
     /**
-     * Get the {@link AccessControlContext JAAS access control context} for this context.
+     * Get the {@link SecurityContext security context} for this context.
      * 
-     * @return the access control context; may be <code>null</code>
+     * @return the security context; may be <code>null</code>
      */
-    public AccessControlContext getAccessControlContext() {
-        return this.accessControlContext;
+    public SecurityContext getSecurityContext() {
+        return this.securityContext;
     }
 
     /**
-     * Get the {@link LoginContext JAAS login context} for this context.
-     * 
-     * @return the login context; may be <code>null</code>
-     */
-    public LoginContext getLoginContext() {
-        return this.loginContext;
-    }
-
-    /**
      * Get the (mutable) namespace registry for this context.
      * 
      * @return the namespace registry; never <code>null</code>
@@ -273,16 +218,6 @@
     }
 
     /**
-     * Get the JAAS subject for which this context was created.
-     * 
-     * @return the subject; should never be null if JAAS is used, but will be null if there is no
-     *         {@link #getAccessControlContext() access control context} or {@link #getLoginContext() login context}.
-     */
-    public Subject getSubject() {
-        return this.subject;
-    }
-
-    /**
      * Get the factories that should be used to create values for {@link Property properties}.
      * 
      * @return the property value factory; never null
@@ -312,8 +247,8 @@
     public ExecutionContext with( NamespaceRegistry namespaceRegistry ) {
         // Don't supply the value factories or property factories, since they'll have to be recreated
         // to reference the supplied namespace registry ...
-        return new ExecutionContext(this.getLoginContext(), this.getAccessControlContext(), namespaceRegistry, null, null,
-                                    this.getMimeTypeDetector(), this.getClassLoaderFactory());
+        return new ExecutionContext(this.getSecurityContext(), namespaceRegistry, null, null, this.getMimeTypeDetector(),
+                                    this.getClassLoaderFactory());
     }
 
     /**
@@ -327,8 +262,8 @@
     public ExecutionContext with( MimeTypeDetector mimeTypeDetector ) {
         // Don't supply the value factories or property factories, since they'll have to be recreated
         // to reference the supplied namespace registry ...
-        return new ExecutionContext(getLoginContext(), getAccessControlContext(), getNamespaceRegistry(), getValueFactories(),
-                                    getPropertyFactory(), mimeTypeDetector, getClassLoaderFactory());
+        return new ExecutionContext(this.getSecurityContext(), getNamespaceRegistry(), getValueFactories(), getPropertyFactory(),
+                                    mimeTypeDetector, getClassLoaderFactory());
     }
 
     /**
@@ -342,135 +277,26 @@
     public ExecutionContext with( ClassLoaderFactory classLoaderFactory ) {
         // Don't supply the value factories or property factories, since they'll have to be recreated
         // to reference the supplied namespace registry ...
-        return new ExecutionContext(getLoginContext(), getAccessControlContext(), getNamespaceRegistry(), getValueFactories(),
-                                    getPropertyFactory(), getMimeTypeDetector(), classLoaderFactory);
+        return new ExecutionContext(this.getSecurityContext(), getNamespaceRegistry(), getValueFactories(), getPropertyFactory(),
+                                    getMimeTypeDetector(), classLoaderFactory);
     }
 
     /**
-     * Creates an {@link ExecutionContext} that is the same as this context, but which uses the supplied
-     * {@link AccessControlContext access control context}.
+     * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied {@link SecurityContext
+     * security context}.
      * 
-     * @param accessControlContext the JAAS access control context that should be used
+     * @param securityContext the new security context to use; may be null
      * @return the execution context that is identical with this execution context, but with a different security context; never
      *         null
-     * @throws IllegalArgumentException if <code>accessControlContext</code> is <code>null</code>.
-     */
-    public ExecutionContext create( AccessControlContext accessControlContext ) {
-        return new ExecutionContext(this, accessControlContext);
-    }
-
-    /**
-     * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied {@link LoginContext}. A
-     * LoginContext has a variety of constructors, including contructors that take combinations of
-     * {@link Configuration#getAppConfigurationEntry(String) application configuration name}, {@link Subject subject},
-     * {@link CallbackHandler callback handlers}, and a {@link Configuration JAAS configuration}.
-     * 
-     * @param loginContext the JAAS login context
-     * @return the execution context that is identical with this execution context, but with a different security context; never
-     *         null
-     * @throws IllegalArgumentException if the <code>loginContext</code> is null
-     */
-    public ExecutionContext create( LoginContext loginContext ) {
-        return new ExecutionContext(this, loginContext);
-    }
-
-    /**
-     * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied
-     * {@link Configuration#getAppConfigurationEntry(String) application configuration name}.
-     * 
-     * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
-     * @return the execution context that is identical with this execution context, but with a different security context; never
-     *         null
      * @throws IllegalArgumentException if the <code>name</code> is null
      * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
      *         default callback handler JAAS property was not set or could not be loaded
      */
-    public ExecutionContext with( String name ) throws LoginException {
-        return new ExecutionContext(this, new LoginContext(name));
+    public ExecutionContext with( SecurityContext securityContext ) throws LoginException {
+        return new ExecutionContext(this, securityContext);
     }
 
     /**
-     * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied
-     * {@link Configuration#getAppConfigurationEntry(String) application configuration name} and a {@link Subject JAAS subject}.
-     * 
-     * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
-     * @param subject the subject to authenticate
-     * @return the execution context that is identical with this execution context, but with a different security context; never
-     *         null
-     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), if the default
-     *         callback handler JAAS property was not set or could not be loaded, or if the <code>subject</code> is null or
-     *         unknown
-     */
-    public ExecutionContext with( String name,
-                                  Subject subject ) throws LoginException {
-        return new ExecutionContext(this, new LoginContext(name, subject));
-    }
-
-    /**
-     * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied
-     * {@link Configuration#getAppConfigurationEntry(String) application configuration name} and a {@link CallbackHandler JAAS
-     * callback handler} (used to handle authentication callbacks).
-     * 
-     * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
-     * @param callbackHandler the callback handler that will be used by {@link LoginModule}s to communicate with the user to
-     *        authenticate
-     * @return the execution context that is identical with this execution context, but with a different security context; never
-     *         null
-     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
-     *         <code>callbackHandler</code> is null
-     */
-    public ExecutionContext with( String name,
-                                  CallbackHandler callbackHandler ) throws LoginException {
-        LoginContext loginContext = new LoginContext(name, callbackHandler);
-        loginContext.login();
-
-        return new ExecutionContext(this, loginContext);
-    }
-
-    /**
-     * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied
-     * {@link Configuration#getAppConfigurationEntry(String) application configuration name} and a {@link CallbackHandler JAAS
-     * callback handler} to create a new {@link LoginContext login context} with the given user ID and password.
-     * 
-     * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
-     * @param userId the user ID to use for authentication
-     * @param password the password to use for authentication
-     * @return the execution context that is identical with this execution context, but with a different security context; never
-     *         null
-     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
-     *         <code>callbackHandler</code> is null
-     */
-    public ExecutionContext with( String name,
-                                  String userId,
-                                  char[] password ) throws LoginException {
-        return this.with(name, new UserPasswordCallbackHandler(userId, password));
-    }
-
-    /**
-     * Create an {@link ExecutionContext} that is the same as this context, but which uses the supplied
-     * {@link Configuration#getAppConfigurationEntry(String) application configuration name}, a {@link Subject JAAS subject}, and
-     * a {@link CallbackHandler JAAS callback handler} (used to handle authentication callbacks).
-     * 
-     * @param name the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
-     * @param subject the subject to authenticate
-     * @param callbackHandler the callback handler that will be used by {@link LoginModule}s to communicate with the user to
-     *        authenticate
-     * @return the execution context that is identical with this execution context, but with a different security context; never
-     *         null
-     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), if the default
-     *         callback handler JAAS property was not set or could not be loaded, if the <code>subject</code> is null or unknown,
-     *         or if the <code>callbackHandler</code> is null
-     */
-    public ExecutionContext with( String name,
-                                  Subject subject,
-                                  CallbackHandler callbackHandler ) throws LoginException {
-        LoginContext loginContext = new LoginContext(name, subject, callbackHandler);
-        loginContext.login();
-
-        return new ExecutionContext(this, loginContext);
-    }
-
-    /**
      * {@inheritDoc}
      * 
      * @see java.lang.Object#clone()
@@ -487,7 +313,7 @@
      */
     @Override
     public String toString() {
-        return "Execution context for " + getSubject();
+        return "Execution context for " + getSecurityContext() == null ? "null" : getSecurityContext().getUserName();
     }
 
     /**
@@ -507,106 +333,23 @@
     }
 
     /**
-     * A simple {@link CallbackHandler callback handler} implementation that attempts to provide a user ID and password to any
-     * callbacks that it handles.
+     * Default security context that confers no roles.
      */
-    protected final class UserPasswordCallbackHandler implements CallbackHandler {
+    private static class NullSecurityContext implements SecurityContext {
 
-        private static final boolean LOG_TO_CONSOLE = false;
+        @Override
+        public String getUserName() {
+            return null;
+        }
 
-        private final String userId;
-        private final char[] password;
-
-        protected UserPasswordCallbackHandler( String userId,
-                                               char[] password ) {
-            this.userId = userId;
-            this.password = password.clone();
+        @Override
+        public boolean hasRole( String roleName ) {
+            return false;
         }
 
-        /**
-         * {@inheritDoc}
-         * 
-         * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
-         */
-        public void handle( Callback[] callbacks ) throws UnsupportedCallbackException, IOException {
-            boolean userSet = false;
-            boolean passwordSet = false;
-            
-            for (int i = 0; i < callbacks.length; i++) {
-                if (callbacks[i] instanceof TextOutputCallback) {
-
-                    // display the message according to the specified type
-                    TextOutputCallback toc = (TextOutputCallback)callbacks[i];
-                    if (!LOG_TO_CONSOLE) {
-                        continue;
-                    }
-
-                    switch (toc.getMessageType()) {
-                        case TextOutputCallback.INFORMATION:
-                            System.out.println(toc.getMessage());
-                            break;
-                        case TextOutputCallback.ERROR:
-                            System.out.println("ERROR: " + toc.getMessage());
-                            break;
-                        case TextOutputCallback.WARNING:
-                            System.out.println("WARNING: " + toc.getMessage());
-                            break;
-                        default:
-                            throw new IOException("Unsupported message type: " + toc.getMessageType());
-                    }
-
-                } else if (callbacks[i] instanceof NameCallback) {
-
-                    // prompt the user for a username
-                    NameCallback nc = (NameCallback)callbacks[i];
-
-                    if (LOG_TO_CONSOLE) {
-                        // ignore the provided defaultName
-                        System.out.print(nc.getPrompt());
-                        System.out.flush();
-                    }
-
-                    nc.setName(this.userId);
-                    userSet = true;
-
-                } else if (callbacks[i] instanceof PasswordCallback) {
-
-                    // prompt the user for sensitive information
-                    PasswordCallback pc = (PasswordCallback)callbacks[i];
-                    if (LOG_TO_CONSOLE) {
-                        System.out.print(pc.getPrompt());
-                        System.out.flush();
-                    }
-                    pc.setPassword(this.password);
-                    passwordSet = true;
-
-                } else {
-                    /*
-                     * Jetty uses its own callback for setting the password.  Since we're using Jetty for integration
-                     * testing of the web project(s), we have to accomodate this.  Rather than introducing a direct
-                     * dependency, we'll add code to handle the case of unexpected callback handlers with a setObject method.
-                     */
-                    try {
-                        // Assume that a callback chain will ask for the user before the password
-                        if (!userSet) {
-                            new Reflection(callbacks[i].getClass()).invokeSetterMethodOnTarget("object", callbacks[i], this.userId);
-                            userSet = true;
-                        }
-                        else if (!passwordSet) {
-                            // Jetty also seems to eschew passing passwords as char arrays
-                            new Reflection(callbacks[i].getClass()).invokeSetterMethodOnTarget("object", callbacks[i], new String(this.password));
-                            passwordSet = true;
-                        }
-                        // It worked - need to continue processing the callbacks
-                        continue;
-                    } catch (Exception ex) {
-                        // If the property cannot be set, fall through to the failure
-                    }
-                    throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback: "
-                                                           + callbacks[i].getClass().getName());
-                }
-            }
-
+        @Override
+        public void logout() {
         }
+        
     }
 }

Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JaasSecurityContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/JaasSecurityContext.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/JaasSecurityContext.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -0,0 +1,297 @@
+package org.jboss.dna.graph;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.security.acl.Group;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+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.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.login.Configuration;
+import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.common.util.Logger;
+import org.jboss.dna.common.util.Reflection;
+
+/**
+ * JAAS-based {@link SecurityContext security context} that provides authentication and authorization through the JAAS
+ * {@link LoginContext login context}.
+ */
+public final class JaasSecurityContext implements SecurityContext {
+
+    private final Logger log = Logger.getLogger(getClass());
+
+    private final LoginContext loginContext;
+    private final String userName;
+    private final Set<String> entitlements;
+    private boolean loggedIn;
+
+    /**
+     * Create a {@link JaasSecurityContext} with the supplied {@link Configuration#getAppConfigurationEntry(String) application
+     * configuration name}.
+     * 
+     * @param realmName the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
+     *        ; may not be null
+     * @throws IllegalArgumentException if the <code>name</code> is null
+     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
+     *         default callback handler JAAS property was not set or could not be loaded
+     */
+    public JaasSecurityContext( String realmName ) throws LoginException {
+        this(new LoginContext(realmName));
+    }
+
+    /**
+     * Create a {@link JaasSecurityContext} with the supplied {@link Configuration#getAppConfigurationEntry(String) application
+     * configuration name} and a {@link Subject JAAS subject}.
+     * 
+     * @param realmName the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
+     * @param subject the subject to authenticate
+     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), if the default
+     *         callback handler JAAS property was not set or could not be loaded, or if the <code>subject</code> is null or
+     *         unknown
+     */
+    public JaasSecurityContext( String realmName,
+                                Subject subject ) throws LoginException {
+        this(new LoginContext(realmName, subject));
+    }
+
+    /**
+     * Create a {@link JaasSecurityContext} with the supplied {@link Configuration#getAppConfigurationEntry(String) application
+     * configuration name} and a {@link CallbackHandler JAAS callback handler} to create a new {@link JaasSecurityContext JAAS
+     * login context} with the given user ID and password.
+     * 
+     * @param realmName the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
+     * @param userId the user ID to use for authentication
+     * @param password the password to use for authentication
+     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
+     *         <code>callbackHandler</code> is null
+     */
+
+    public JaasSecurityContext( String realmName,
+                                String userId,
+                                char[] password ) throws LoginException {
+        this(new LoginContext(realmName, new UserPasswordCallbackHandler(userId, password)));
+    }
+
+    /**
+     * Create a {@link JaasSecurityContext} with the supplied {@link Configuration#getAppConfigurationEntry(String) application
+     * configuration name} and the given callback handler.
+     * 
+     * @param realmName the name of the {@link Configuration#getAppConfigurationEntry(String) JAAS application configuration name}
+     *        ; may not be null
+     * @param callbackHandler the callback handler to use during the login process; may not be null
+     * @throws LoginException if there <code>name</code> is invalid (or there is no login context named "other"), or if the
+     *         <code>callbackHandler</code> is null
+     */
+
+    public JaasSecurityContext( String realmName,
+                                CallbackHandler callbackHandler ) throws LoginException {
+        this(new LoginContext(realmName, callbackHandler));
+    }
+
+    /**
+     * Creates a new JAAS security context based on the given login context. If {@link LoginContext#login() login} has not already
+     * been invoked on the login context, this constructor will attempt to invoke it.
+     * 
+     * @param loginContext the login context to use; may not be null
+     * @throws LoginException if the context has not already had {@link LoginContext#login() its login method} invoked and an
+     *         error occurs attempting to invoke the login method.
+     * @see LoginContext
+     */
+    public JaasSecurityContext( LoginContext loginContext ) throws LoginException {
+        CheckArg.isNotNull(loginContext, "loginContext");
+        this.entitlements = new HashSet<String>();
+        this.loginContext = loginContext;
+
+        if (this.loginContext.getSubject() == null) this.loginContext.login();
+
+        this.userName = initialize(loginContext.getSubject());
+        this.loggedIn = true;
+    }
+
+    /**
+     * Creates a new JAAS security context based on the user name and roles from the given subject.
+     * 
+     * @param subject the subject to use as the provider of the user name and roles for this security context; may not be null
+     */
+    public JaasSecurityContext( Subject subject ) {
+        CheckArg.isNotNull(subject, "subject");
+        this.loginContext = null;
+        this.entitlements = new HashSet<String>();
+        this.userName = initialize(subject);
+        this.loggedIn = true;
+    }
+
+    private String initialize( Subject subject ) {
+        String userName = null;
+
+        if (subject != null) {
+            for (Principal principal : subject.getPrincipals()) {
+                if (principal instanceof Group) {
+                    Group group = (Group)principal;
+                    Enumeration<? extends Principal> roles = group.members();
+
+                    while (roles.hasMoreElements()) {
+                        Principal role = roles.nextElement();
+                        entitlements.add(role.getName());
+                    }
+                } else {
+                    userName = principal.getName();
+                    log.debug("Adding principal user name: " + userName);
+                }
+            }
+        }
+
+        return userName;
+    }
+
+    /**
+     * {@inheritDoc SecurityContext#getUserName()}
+     * 
+     * @see SecurityContext#getUserName()
+     */
+    @Override
+    public String getUserName() {
+        return loggedIn ? userName : null;
+    }
+
+    /**
+     * {@inheritDoc SecurityContext#hasRole(String)}
+     * 
+     * @see SecurityContext#hasRole(String)
+     */
+
+    @Override
+    public boolean hasRole( String roleName ) {
+        return loggedIn ? entitlements.contains(roleName) : false;
+    }
+
+    /**
+     * {@inheritDoc SecurityContext#logout()}
+     * 
+     * @see SecurityContext#logout()
+     */
+    @Override
+    public void logout() {
+        try {
+            loggedIn = false;
+            if (loginContext != null) loginContext.logout();
+        } catch (LoginException le) {
+            log.info(le, null);
+        }
+    }
+
+    /**
+     * A simple {@link CallbackHandler callback handler} implementation that attempts to provide a user ID and password to any
+     * callbacks that it handles.
+     */
+    public static final class UserPasswordCallbackHandler implements CallbackHandler {
+
+        private static final boolean LOG_TO_CONSOLE = false;
+
+        private final String userId;
+        private final char[] password;
+
+        public UserPasswordCallbackHandler( String userId,
+                                            char[] password ) {
+            this.userId = userId;
+            this.password = password.clone();
+        }
+
+        /**
+         * {@inheritDoc}
+         * 
+         * @see javax.security.auth.callback.CallbackHandler#handle(javax.security.auth.callback.Callback[])
+         */
+        public void handle( Callback[] callbacks ) throws UnsupportedCallbackException, IOException {
+            boolean userSet = false;
+            boolean passwordSet = false;
+
+            for (int i = 0; i < callbacks.length; i++) {
+                if (callbacks[i] instanceof TextOutputCallback) {
+
+                    // display the message according to the specified type
+                    TextOutputCallback toc = (TextOutputCallback)callbacks[i];
+                    if (!LOG_TO_CONSOLE) {
+                        continue;
+                    }
+
+                    switch (toc.getMessageType()) {
+                        case TextOutputCallback.INFORMATION:
+                            System.out.println(toc.getMessage());
+                            break;
+                        case TextOutputCallback.ERROR:
+                            System.out.println("ERROR: " + toc.getMessage());
+                            break;
+                        case TextOutputCallback.WARNING:
+                            System.out.println("WARNING: " + toc.getMessage());
+                            break;
+                        default:
+                            throw new IOException("Unsupported message type: " + toc.getMessageType());
+                    }
+
+                } else if (callbacks[i] instanceof NameCallback) {
+
+                    // prompt the user for a username
+                    NameCallback nc = (NameCallback)callbacks[i];
+
+                    if (LOG_TO_CONSOLE) {
+                        // ignore the provided defaultName
+                        System.out.print(nc.getPrompt());
+                        System.out.flush();
+                    }
+
+                    nc.setName(this.userId);
+                    userSet = true;
+
+                } else if (callbacks[i] instanceof PasswordCallback) {
+
+                    // prompt the user for sensitive information
+                    PasswordCallback pc = (PasswordCallback)callbacks[i];
+                    if (LOG_TO_CONSOLE) {
+                        System.out.print(pc.getPrompt());
+                        System.out.flush();
+                    }
+                    pc.setPassword(this.password);
+                    passwordSet = true;
+
+                } else {
+                    /*
+                     * Jetty uses its own callback for setting the password.  Since we're using Jetty for integration
+                     * testing of the web project(s), we have to accomodate this.  Rather than introducing a direct
+                     * dependency, we'll add code to handle the case of unexpected callback handlers with a setObject method.
+                     */
+                    try {
+                        // Assume that a callback chain will ask for the user before the password
+                        if (!userSet) {
+                            new Reflection(callbacks[i].getClass()).invokeSetterMethodOnTarget("object",
+                                                                                               callbacks[i],
+                                                                                               this.userId);
+                            userSet = true;
+                        } else if (!passwordSet) {
+                            // Jetty also seems to eschew passing passwords as char arrays
+                            new Reflection(callbacks[i].getClass()).invokeSetterMethodOnTarget("object",
+                                                                                               callbacks[i],
+                                                                                               new String(this.password));
+                            passwordSet = true;
+                        }
+                        // It worked - need to continue processing the callbacks
+                        continue;
+                    } catch (Exception ex) {
+                        // If the property cannot be set, fall through to the failure
+                    }
+                    throw new UnsupportedCallbackException(callbacks[i], "Unrecognized Callback: "
+                                                                         + callbacks[i].getClass().getName());
+                }
+            }
+
+        }
+    }
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/JaasSecurityContext.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Added: trunk/dna-graph/src/main/java/org/jboss/dna/graph/SecurityContext.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/SecurityContext.java	                        (rev 0)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/SecurityContext.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -0,0 +1,35 @@
+package org.jboss.dna.graph;
+
+/**
+ * A security context provides a pluggable means to support disparate authentication and authorization 
+ * mechanisms that specify the user name and roles.
+ * <p>
+ * A security context should only be associated with the execution context <b>after</b> authentication has occurred.
+ * </p>
+ */
+public interface SecurityContext {
+
+    /**
+     * Returns the authenticated user's name
+     * 
+     * @return the authenticated user's name
+     */
+    String getUserName();
+
+    /**
+     * Returns whether the authenticated user has the given role.
+     * 
+     * @param roleName the name of the role to check
+     * @return true if the user has the role and is logged in; false otherwise
+     */
+    boolean hasRole( String roleName );
+    
+    /**
+     * Logs the user out of the authentication mechanism.
+     * <p>
+     * For some authentication mechanisms, this will be implemented as a no-op.
+     * </p>
+     */
+    void logout();
+    
+}


Property changes on: trunk/dna-graph/src/main/java/org/jboss/dna/graph/SecurityContext.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/observe/Changes.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/observe/Changes.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/observe/Changes.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -26,8 +26,8 @@
 import java.io.Serializable;
 import java.util.Iterator;
 import java.util.List;
-import javax.security.auth.Subject;
 import net.jcip.annotations.Immutable;
+import org.jboss.dna.graph.SecurityContext;
 import org.jboss.dna.graph.property.DateTime;
 import org.jboss.dna.graph.request.ChangeRequest;
 
@@ -40,24 +40,24 @@
     private static final long serialVersionUID = 1L;
 
     private final String processId;
-    private final Subject subject;
+    private final String userName;
     private final String sourceName;
     private final DateTime timestamp;
     private final List<ChangeRequest> changeRequests;
 
-    public Changes( Subject subject,
+    public Changes( String userName,
                     String sourceName,
                     DateTime timestamp,
                     List<ChangeRequest> requests ) {
-        this("", subject, sourceName, timestamp, requests);
+        this("", userName, sourceName, timestamp, requests);
     }
 
     public Changes( String processId,
-                    Subject subject,
+                    String userName,
                     String sourceName,
                     DateTime timestamp,
                     List<ChangeRequest> requests ) {
-        this.subject = subject;
+        this.userName = userName;
         this.sourceName = sourceName;
         this.timestamp = timestamp;
         this.changeRequests = requests;
@@ -68,9 +68,10 @@
      * Get the user that made these changes.
      * 
      * @return the user; never null
+     * @see SecurityContext#getUserName()
      */
-    public Subject getSubject() {
-        return this.subject;
+    public String getUserName() {
+        return this.userName;
     }
 
     /**
@@ -142,7 +143,7 @@
             if (!this.getProcessId().equals(that.getProcessId())) return false;
             if (!this.getSourceName().equals(that.getSourceName())) return false;
             if (!this.getTimestamp().equals(that.getTimestamp())) return false;
-            if (!this.getSubject().equals(that.getSubject())) return false;
+            if (!this.getUserName().equals(that.getUserName())) return false;
             return true;
         }
         return false;

Modified: trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java
===================================================================
--- trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-graph/src/main/java/org/jboss/dna/graph/request/processor/RequestProcessor.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -786,7 +786,8 @@
     public void close() {
         // Publish any changes ...
         if (observer != null && !this.changes.isEmpty()) {
-            Changes changes = new Changes(context.getSubject(), getSourceName(), getNowInUtc(), this.changes);
+            String userName = context.getSecurityContext() != null ? context.getSecurityContext().getUserName() : null; 
+            Changes changes = new Changes(userName, getSourceName(), getNowInUtc(), this.changes);
             observer.notify(changes);
         }
     }

Added: trunk/dna-graph/src/test/java/org/jboss/dna/graph/MockSecurityContext.java
===================================================================
--- trunk/dna-graph/src/test/java/org/jboss/dna/graph/MockSecurityContext.java	                        (rev 0)
+++ trunk/dna-graph/src/test/java/org/jboss/dna/graph/MockSecurityContext.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -0,0 +1,38 @@
+package org.jboss.dna.graph;
+
+import java.util.Collections;
+import java.util.Set;
+
+/**
+ * Mock security context for testing that grants a set of roles.
+ */
+public class MockSecurityContext implements SecurityContext {
+
+    private final String userName;
+    private final Set<String> entitlements;
+
+    public MockSecurityContext(String userName) {
+        this(userName, null);
+    }
+
+    public MockSecurityContext(String userName, Set<String> entitlements) {
+        this.userName = userName;
+        this.entitlements = entitlements != null ? entitlements : Collections.<String>emptySet();
+    }
+    
+    @Override
+    public String getUserName() {
+        return userName;
+    }
+
+    @Override
+    public boolean hasRole( String roleName ) {
+        return entitlements.contains(roleName);
+    }
+
+    @Override
+    public void logout() {
+
+    }
+
+}


Property changes on: trunk/dna-graph/src/test/java/org/jboss/dna/graph/MockSecurityContext.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrI18n.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -33,7 +33,7 @@
 
     public static I18n cannotConvertValue;
     public static I18n credentialsMustProvideJaasMethod;
-    public static I18n credentialsMustReturnAccessControlContext;
+    public static I18n mustBeInPrivilegedAction;
     public static I18n credentialsMustReturnLoginContext;
     public static I18n defaultWorkspaceName;
     public static I18n inputStreamConsumed;

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrRepository.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -38,13 +38,16 @@
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.SimpleCredentials;
+import javax.security.auth.Subject;
 import javax.security.auth.login.Configuration;
 import javax.security.auth.login.LoginContext;
+import javax.security.auth.login.LoginException;
 import net.jcip.annotations.ThreadSafe;
 import org.jboss.dna.common.text.Inflector;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.JaasSecurityContext;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.jboss.dna.graph.request.InvalidWorkspaceException;
@@ -359,59 +362,53 @@
         Map<String, Object> sessionAttributes = new HashMap<String, Object>();
         ExecutionContext execContext = null;
         if (credentials == null) {
-            execContext = executionContext.create(AccessController.getContext());
+            try {
+                Subject subject = Subject.getSubject(AccessController.getContext());
+                if (subject == null) {
+                    throw new javax.jcr.LoginException(JcrI18n.mustBeInPrivilegedAction.text());
+                }
+                execContext = executionContext.with(new JaasSecurityContext(subject));
+            } catch (LoginException le) {
+                // This really can't happen if you're creating the JAAS security context with an existing subject
+                throw new IllegalStateException(le);
+            }
         } else {
             try {
-                // Check if credentials provide a login context
-                try {
-                    Method method = credentials.getClass().getMethod("getLoginContext");
-                    if (method.getReturnType() != LoginContext.class) {
-                        throw new IllegalArgumentException(JcrI18n.credentialsMustReturnLoginContext.text(credentials.getClass()));
+                if (credentials instanceof SimpleCredentials) {
+                    SimpleCredentials simple = (SimpleCredentials)credentials;
+                    execContext = executionContext.with(new JaasSecurityContext(options.get(Option.JAAS_LOGIN_CONFIG_NAME),
+                                                                                simple.getUserID(), simple.getPassword()));
+                    for (String attributeName : simple.getAttributeNames()) {
+                        Object attributeValue = simple.getAttribute(attributeName);
+                        sessionAttributes.put(attributeName, attributeValue);
                     }
-                    LoginContext loginContext = (LoginContext)method.invoke(credentials);
-                    if (loginContext == null) {
-                        throw new IllegalArgumentException(JcrI18n.credentialsMustReturnLoginContext.text(credentials.getClass()));
-                    }
-                    execContext = executionContext.create(loginContext);
-                } catch (NoSuchMethodException error) {
-                    // Check if credentials provide an access control context
+
+                } else if (credentials instanceof SecurityContextCredentials) {
+                    execContext = executionContext.with(((SecurityContextCredentials)credentials).getSecurityContext());
+                } else {
+                    // Check if credentials provide a login context
                     try {
-                        Method method = credentials.getClass().getMethod("getAccessControlContext");
-                        if (method.getReturnType() != AccessControlContext.class) {
+                        Method method = credentials.getClass().getMethod("getLoginContext");
+                        if (method.getReturnType() != LoginContext.class) {
                             throw new IllegalArgumentException(
-                                                               JcrI18n.credentialsMustReturnAccessControlContext.text(credentials.getClass()));
+                                                               JcrI18n.credentialsMustReturnLoginContext.text(credentials.getClass()));
                         }
-                        AccessControlContext accessControlContext = (AccessControlContext)method.invoke(credentials);
-                        if (accessControlContext == null) {
+                        LoginContext loginContext = (LoginContext)method.invoke(credentials);
+                        if (loginContext == null) {
                             throw new IllegalArgumentException(
-                                                               JcrI18n.credentialsMustReturnAccessControlContext.text(credentials.getClass()));
+                                                               JcrI18n.credentialsMustReturnLoginContext.text(credentials.getClass()));
                         }
-                        execContext = executionContext.create(accessControlContext);
-                    } catch (NoSuchMethodException error2) {
-                        if (credentials instanceof SimpleCredentials) {
-                            SimpleCredentials simple = (SimpleCredentials)credentials;
-                            execContext = executionContext.with(options.get(Option.JAAS_LOGIN_CONFIG_NAME),
-                                                                simple.getUserID(),
-                                                                simple.getPassword());
-                        } else {
-                            throw new IllegalArgumentException(
-                                                               JcrI18n.credentialsMustProvideJaasMethod.text(credentials.getClass()),
-                                                               error2);
-                        }
+                        execContext = executionContext.with(new JaasSecurityContext(loginContext));
+                    } catch (NoSuchMethodException error) {
+                        throw new IllegalArgumentException(JcrI18n.credentialsMustProvideJaasMethod.text(credentials.getClass()),
+                                                           error);
                     }
                 }
             } catch (RuntimeException error) {
                 throw error;
             } catch (Exception error) {
-                throw new RepositoryException(error);
+                throw new javax.jcr.LoginException(error);
             }
-            if (credentials instanceof SimpleCredentials) {
-                SimpleCredentials simple = (SimpleCredentials)credentials;
-                for (String attributeName : simple.getAttributeNames()) {
-                    Object attributeValue = simple.getAttribute(attributeName);
-                    sessionAttributes.put(attributeName, attributeValue);
-                }
-            }
         }
 
         // Ensure valid workspace name
@@ -448,6 +445,7 @@
 
     /**
      * Returns the name of this repository
+     * 
      * @return the name of this repository
      * @see #sourceName
      */

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrSession.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -27,11 +27,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.security.AccessControlException;
-import java.security.Principal;
-import java.security.acl.Group;
 import java.util.Calendar;
-import java.util.Enumeration;
-import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
@@ -53,13 +49,11 @@
 import javax.jcr.ValueFormatException;
 import javax.jcr.Workspace;
 import javax.jcr.nodetype.ConstraintViolationException;
-import javax.security.auth.Subject;
-import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
 import net.jcip.annotations.NotThreadSafe;
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.SecurityContext;
 import org.jboss.dna.graph.property.Binary;
 import org.jboss.dna.graph.property.DateTime;
 import org.jboss.dna.graph.property.Name;
@@ -121,11 +115,6 @@
      */
     private final Graph graph;
 
-    /**
-     * The set of assigned entitlements for the logged-in subject
-     */
-    private Set<String> entitlements;
-
     private final SessionCache cache;
 
     /**
@@ -164,29 +153,13 @@
                                       this.graph);
         this.isLive = true;
 
-        Subject subject = this.executionContext.getSubject();
-        this.entitlements = new HashSet<String>();
-
-        if (subject != null) {
-            for (Principal principal : subject.getPrincipals()) {
-                if (principal instanceof Group) {
-                    Group group = (Group)principal;
-                    Enumeration<? extends Principal> roles = group.members();
-
-                    while (roles.hasMoreElements()) {
-                        Principal role = roles.nextElement();
-                        entitlements.add(role.getName());
-                    }
-                }
-            }
-        }
-        assert this.repository != null;
         assert this.sessionAttributes != null;
         assert this.workspace != null;
+        assert this.repository != null;
         assert this.executionContext != null;
         assert this.sessionRegistry != null;
         assert this.graph != null;
-        assert this.entitlements != null;
+        assert this.executionContext.getSecurityContext() != null;
     }
 
     // Added to facilitate mock testing of items without necessarily requiring an entire repository structure to be built
@@ -310,15 +283,13 @@
     }
 
     /**
-     * Returns the entitlements (permissions) available to the {@link ExecutionContext#getSubject() subject} for this session.
-     * <p>
-     * Entitlements are exposed through this method to allow for easier mock testing.
-     * </p>
+     * Returns whether the authenticated user has the given role.
      * 
-     * @return the entitlements (permissions) available to the {@link ExecutionContext#getSubject() subject} for this session.
+     * @param roleName the name of the role to check
+     * @return true if the user has the role and is logged in; false otherwise
      */
-    Set<String> entitlements() {
-        return this.entitlements;
+    final boolean hasRole( String roleName ) {
+        return getExecutionContext().getSecurityContext().hasRole(roleName);
     }
 
     /**
@@ -334,22 +305,21 @@
         this.checkPermission(executionContext.getValueFactories().getPathFactory().create(path), actions);
     }
 
-    public void checkPermission( Path path,
+    void checkPermission( Path path,
                                  String actions ) {
 
         CheckArg.isNotNull(path, "path");
         CheckArg.isNotEmpty(actions, "actions");
 
-        Set<String> entitlements = entitlements();
         if ("read".equals(actions)) {
             // readonly access is sufficient
-            if (entitlements.contains(READ_PERMISSION) || entitlements.contains(READ_PERMISSION + "." + this.workspace.getName())) {
+            if (hasRole(READ_PERMISSION) || hasRole(READ_PERMISSION + "." + this.workspace.getName())) {
                 return;
             }
         }
 
         // need readwrite access
-        if (entitlements.contains(WRITE_PERMISSION) || entitlements.contains(WRITE_PERMISSION + "." + this.workspace.getName())) {
+        if (hasRole(WRITE_PERMISSION) || hasRole(WRITE_PERMISSION + "." + this.workspace.getName())) {
             return;
         }
 
@@ -522,13 +492,10 @@
      * {@inheritDoc}
      * 
      * @see javax.jcr.Session#getUserID()
+     * @see SecurityContext#getUserName()
      */
     public String getUserID() {
-        Subject subject = executionContext.getSubject();
-        if (subject == null) return null;
-        Set<Principal> principals = subject.getPrincipals();
-        if (principals == null || principals.isEmpty()) return null;
-        return principals.iterator().next().getName();
+        return executionContext.getSecurityContext().getUserName();
     }
 
     /**
@@ -736,15 +703,8 @@
         if (!isLive()) {
             return;
         }
-        LoginContext loginContext = executionContext.getLoginContext();
-        if (loginContext != null) {
-            try {
-                loginContext.logout();
-            } catch (LoginException error) {
-                // TODO: Change to DnaException once DNA-180 is addressed
-                throw new RuntimeException(error);
-            }
-        }
+
+        this.executionContext.getSecurityContext().logout();
         isLive = false;
     }
 

Modified: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/JcrWorkspace.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -131,6 +131,7 @@
 
         assert workspaceName != null;
         assert context != null;
+        assert context.getSecurityContext() != null;
         assert repository != null;
         this.name = workspaceName;
         this.repository = repository;
@@ -292,7 +293,7 @@
         }
 
         try {
-            this.session.checkPermission(srcAbsPath.substring(0, srcAbsPath.lastIndexOf('/')), "remove");
+            // this.session.checkPermission(srcAbsPath.substring(0, srcAbsPath.lastIndexOf('/')), "remove");
             this.session.checkPermission(destAbsPath, "add_node");
         }
         catch (AccessControlException ace) {

Added: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SecurityContextCredentials.java
===================================================================
--- trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SecurityContextCredentials.java	                        (rev 0)
+++ trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SecurityContextCredentials.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -0,0 +1,38 @@
+package org.jboss.dna.jcr;
+
+import javax.jcr.Credentials;
+import org.jboss.dna.common.util.CheckArg;
+import org.jboss.dna.graph.SecurityContext;
+
+/**
+ * {@link Credentials} implementation that wraps a {@link SecurityContext DNA security context}.
+ * <p>
+ * This class provides a means of passing security information about an authenticated user into {@link JcrSession the DNA JCR
+ * session implementation} without using JAAS. This class effectively bypasses DNA's internal authentication mechanisms, so it is
+ * very important that this context be provided for <i>authenticated users only</i>.
+ * </p>
+ */
+public final class SecurityContextCredentials implements Credentials {
+    private static final long serialVersionUID = 1L;
+    private final SecurityContext securityContext;
+
+    /**
+     * Initializes the class with an existing {@link SecurityContext security context}.
+     * 
+     * @param securityContext the security context; may not be null
+     */
+    public SecurityContextCredentials( SecurityContext securityContext ) {
+        CheckArg.isNotNull(securityContext, "securityContext");
+
+        this.securityContext = securityContext;
+    }
+
+    /**
+     * Returns the {@link SecurityContext security context} for this instance.
+     * 
+     * @return the {@link SecurityContext security context} for this instance; never null
+     */
+    public final SecurityContext getSecurityContext() {
+        return this.securityContext;
+    }
+}


Property changes on: trunk/dna-jcr/src/main/java/org/jboss/dna/jcr/SecurityContextCredentials.java
___________________________________________________________________
Name: svn:keywords
   + Id Revision
Name: svn:eol-style
   + LF

Modified: trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties
===================================================================
--- trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/main/resources/org/jboss/dna/jcr/JcrI18n.properties	2009-06-06 20:34:20 UTC (rev 983)
@@ -21,17 +21,17 @@
 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 # 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 #
-cannotConvertValue = Cannot convert {0} value to {1}.
-credentialsMustProvideJaasMethod = The Credentials class "{0}" must implement either "public LoginContext getLoginContext();" or "public AccessControlContext getAccessControlContext();".
-credentialsMustReturnAccessControlContext = The "getAccessControlContext()" method in Credentials class "{0}" must not return a null.
-credentialsMustReturnLoginContext = The "getLoginContext()" method in Credentials class "{0}" must not return a null.
+cannotConvertValue = Cannot convert {0} value to {1}
+credentialsMustProvideJaasMethod = The Credentials class "{0}" must implement "public LoginContext getLoginContext();", be an instance of "javax.jcr.SimpleCredentials", or be an instance of "org.jboss.dna.jcr.SecurityContextCredentials"
+mustBeInPrivilegedAction=login() can only be called successfully from within a java.security.PrivilegedAction
+credentialsMustReturnLoginContext = The "getLoginContext()" method in Credentials class "{0}" must not return a null
 defaultWorkspaceName=
-inputStreamConsumed = This value was already consumed as an input stream.
-nonInputStreamConsumed = This value was already consumed as a non-input stream.
+inputStreamConsumed = This value was already consumed as an input stream
+nonInputStreamConsumed = This value was already consumed as a non-input stream
 pathNotFound = No item exists at path {0} in workspace "{1}"
 pathNotFoundRelativeTo = No item exists at path {0} relative to {1} in workspace "{2}"
-permissionDenied = Permission denied to perform actions "{1}" on path {0}.
-repositoryMustBeConfigured = DNA repositories must be configured with either a repository source factory or a repository source.
+permissionDenied = Permission denied to perform actions "{1}" on path {0}
+repositoryMustBeConfigured = DNA repositories must be configured with either a repository source factory or a repository source
 sourceInUse = All sessions must end before a new repository source can be set
 repositoryDoesNotExist = There is no repository named "{0}"
 fileDoesNotExist = Unable to find or read the file "{0}"

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/AbstractJcrAccessTest.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -32,6 +32,7 @@
 import org.jboss.dna.common.statistic.Stopwatch;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.MockSecurityContext;
 import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -89,7 +90,7 @@
 
         repository = new JcrRepository(context, connectionFactory, "unused");
 
-        session = (JcrSession) repository.login();
+        session = (JcrSession) repository.login(new SecurityContextCredentials(new MockSecurityContext(null)));
     }
 
     @After

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/ImportExportTest.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -31,6 +31,7 @@
 import javax.jcr.Node;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.MockSecurityContext;
 import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -97,7 +98,7 @@
 
         repository = new JcrRepository(context, connectionFactory, "unused");
 
-        session = (JcrSession) repository.login();
+        session = (JcrSession) repository.login(new SecurityContextCredentials(new MockSecurityContext(null)));
     }
 
     @After

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrRepositoryTest.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -29,24 +29,29 @@
 import static org.junit.Assert.assertThat;
 import java.security.AccessControlContext;
 import java.security.AccessController;
+import java.security.PrivilegedExceptionAction;
 import java.util.HashMap;
 import java.util.Map;
 import javax.jcr.Credentials;
 import javax.jcr.Repository;
 import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.security.auth.Subject;
 import javax.security.auth.login.LoginContext;
-import javax.security.auth.login.LoginException;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.MockSecurityContext;
+import org.jboss.dna.graph.JaasSecurityContext.UserPasswordCallbackHandler;
 import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
+import org.jboss.security.config.IDTrustConfiguration;
 import org.junit.Before;
+import org.junit.BeforeClass;
 import org.junit.Test;
 import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
-import org.mockito.MockitoAnnotations.Mock;
 
 /**
  * @author jverhaeg
@@ -59,19 +64,23 @@
     private InMemoryRepositorySource source;
     private Map<String, String> descriptors;
     private RepositoryConnectionFactory connectionFactory;
-    protected AccessControlContext accessControlContext = AccessController.getContext();
-    @Mock
-    LoginContext loginContext;
-    private Credentials credentials = new Credentials() {
+    private Credentials credentials;
 
-        private static final long serialVersionUID = 1L;
+    @BeforeClass
+    public static void beforeClass() {
+        // Initialize IDTrust
+        String configFile = "security/jaas.conf.xml";
+        IDTrustConfiguration idtrustConfig = new IDTrustConfiguration();
 
-        @SuppressWarnings( "unused" )
-        public AccessControlContext getAccessControlContext() {
-            return accessControlContext;
+        try {
+            idtrustConfig.config(configFile);
+        } catch (Exception ex) {
+            throw new IllegalStateException(ex);
         }
-    };
+    }
 
+
+    
     @Before
     public void before() throws Exception {
         MockitoAnnotations.initMocks(this);
@@ -83,7 +92,8 @@
 
         // Set up the execution context ...
         context = new ExecutionContext();
-
+        credentials = new SimpleCredentials("superuser", "superuser".toCharArray());
+        
         // Stub out the connection factory ...
         connectionFactory = new RepositoryConnectionFactory() {
             /**
@@ -170,38 +180,45 @@
         assertThat(repository.getDescriptor("property"), is("value"));
     }
 
+    @Test(expected=javax.jcr.LoginException.class)
+    public void shouldNotAllowLoginWithNoCredentials() throws Exception {
+        // This would work iff this code was executing in a privileged block, but it's not
+        repository.login();
+    }
+    
     @Test
-    public void shouldAllowLoginWithNoCredentials() throws Exception {
-        Session session = repository.login();
-        assertThat(session, notNullValue());
-        session.logout();
-        session = repository.login((Credentials)null);
-        assertThat(session, notNullValue());
-        session.logout();
-        session = repository.login(null, JcrI18n.defaultWorkspaceName.text());
-        assertThat(session, notNullValue());
+    public void shouldAllowLoginWithNoCredentialsInPrivilegedBlock() throws Exception {
+        LoginContext login = new LoginContext("dna-jcr", new UserPasswordCallbackHandler("superuser", "superuser".toCharArray()));
+        login.login();
+        
+        Subject subject = login.getSubject();
+        
+        Session session = Subject.doAsPrivileged(subject, new PrivilegedExceptionAction<Session>() {
+
+            @Override
+            public Session run() throws Exception {
+                return repository.login();
+            }
+        
+        }, AccessController.getContext());
+        
+        assertThat(session, is(notNullValue()));
+        assertThat(session.getUserID(), is("superuser"));
+        login.logout();
     }
 
     @Test
     public void shouldAllowLoginWithProperCredentials() throws Exception {
         repository.login(credentials);
-        repository.login(new Credentials() {
-
-            private static final long serialVersionUID = 1L;
-
-            @SuppressWarnings( "unused" )
-            public LoginContext getLoginContext() throws LoginException {
-                return loginContext;
-            }
-        });
+        repository.login(new SecurityContextCredentials(new MockSecurityContext(null)));
     }
 
     @Test
     public void shouldAllowLoginWithNoWorkspaceName() throws Exception {
-        Session session = repository.login((String)null);
+        Session session = repository.login(credentials, null);
         assertThat(session, notNullValue());
         session.logout();
-        session = repository.login(credentials, null);
+        session = repository.login(new SecurityContextCredentials(new MockSecurityContext(null)), (String)null);
         assertThat(session, notNullValue());
         session.logout();
     }

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrSessionTest.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -60,6 +60,7 @@
 import javax.security.auth.login.LoginContext;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.JaasSecurityContext;
 import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.jboss.dna.graph.connector.RepositorySourceException;
@@ -291,7 +292,7 @@
         Subject subject = new Subject(false, Collections.singleton(principal), Collections.EMPTY_SET, Collections.EMPTY_SET);
         LoginContext loginContext = mock(LoginContext.class);
         stub(loginContext.getSubject()).toReturn(subject);
-        Session session = new JcrSession(repository, workspace, context.create(loginContext), sessionAttributes);
+        Session session = new JcrSession(repository, workspace, context.with(new JaasSecurityContext(loginContext)), sessionAttributes);
         try {
             assertThat(session.getUserID(), is("name"));
         } finally {

Modified: trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java
===================================================================
--- trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/dna-jcr/src/test/java/org/jboss/dna/jcr/JcrWorkspaceTest.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -39,6 +39,7 @@
 import javax.jcr.query.QueryManager;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.JaasSecurityContext;
 import org.jboss.dna.graph.JcrLexicon;
 import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
@@ -91,7 +92,7 @@
 
         // Set up the execution context ...
 
-        context = new ExecutionContext().with("dna-jcr", "superuser", "superuser".toCharArray());
+        context = new ExecutionContext().with(new JaasSecurityContext("dna-jcr", "superuser", "superuser".toCharArray()));
 
         // Set up the initial content ...
         Graph graph = Graph.create(source, context);

Modified: trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/extensions/dna-connector-federation/src/main/java/org/jboss/dna/connector/federation/FederatedRepositorySource.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -48,6 +48,7 @@
 import org.jboss.dna.common.util.CheckArg;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
+import org.jboss.dna.graph.JaasSecurityContext;
 import org.jboss.dna.graph.Location;
 import org.jboss.dna.graph.Node;
 import org.jboss.dna.graph.Subgraph;
@@ -495,7 +496,7 @@
         try {
             String securityDomain = getSecurityDomain();
             if (securityDomain != null || getUsername() != null) {
-                return factory.with(securityDomain, handler);
+                return factory.with(new JaasSecurityContext(securityDomain, handler));
             }
             return factory;
         } catch (LoginException e) {

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceIntegrationTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceIntegrationTest.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceIntegrationTest.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -29,7 +29,6 @@
 import static org.junit.Assert.fail;
 import static org.junit.matchers.JUnitMatchers.hasItems;
 import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.stub;
 import static org.mockito.Mockito.times;
@@ -37,11 +36,11 @@
 import java.util.ArrayList;
 import java.util.List;
 import javax.naming.Context;
-import javax.security.auth.callback.CallbackHandler;
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
 import org.jboss.dna.graph.Location;
+import org.jboss.dna.graph.SecurityContext;
 import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.jboss.dna.graph.connector.RepositoryContext;
@@ -51,6 +50,7 @@
 import org.jboss.dna.graph.property.PathNotFoundException;
 import org.jboss.dna.graph.property.Property;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.mockito.ArgumentMatcher;
 import org.mockito.MockitoAnnotations;
@@ -65,6 +65,7 @@
  * 
  * @author Randall Hauch
  */
+ at Ignore
 public class FederatedRepositorySourceIntegrationTest {
 
     private FederatedRepositorySource source;
@@ -107,7 +108,7 @@
         securityDomain = "security domain";
         stub(jndiContext.lookup(executionContextFactoryJndiName)).toReturn(executionContextFactory);
         stub(jndiContext.lookup(repositoryConnectionFactoryJndiName)).toReturn(connectionFactory);
-        stub(executionContextFactory.with(eq(securityDomain), anyCallbackHandler())).toReturn(context);
+        stub(executionContextFactory.with(anySecurityContext())).toReturn(context);
         stub(repositoryContext.getExecutionContext()).toReturn(executionContextFactory);
         stub(repositoryContext.getRepositoryConnectionFactory()).toReturn(connectionFactory);
 
@@ -156,8 +157,8 @@
         }
     }
 
-    protected static CallbackHandler anyCallbackHandler() {
-        return argThat(new ArgumentMatcher<CallbackHandler>() {
+    protected static SecurityContext anySecurityContext() {
+        return argThat(new ArgumentMatcher<SecurityContext>() {
             @Override
             public boolean matches( Object callback ) {
                 return callback != null;

Modified: trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java
===================================================================
--- trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java	2009-06-05 15:29:41 UTC (rev 982)
+++ trunk/extensions/dna-connector-federation/src/test/java/org/jboss/dna/connector/federation/FederatedRepositorySourceTest.java	2009-06-06 20:34:20 UTC (rev 983)
@@ -28,7 +28,6 @@
 import static org.hamcrest.core.IsNull.nullValue;
 import static org.junit.Assert.assertThat;
 import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.stub;
 import java.util.Enumeration;
@@ -40,18 +39,19 @@
 import javax.naming.RefAddr;
 import javax.naming.Reference;
 import javax.naming.spi.ObjectFactory;
-import javax.security.auth.callback.CallbackHandler;
 import javax.security.auth.login.LoginException;
 import org.jboss.dna.graph.DnaLexicon;
 import org.jboss.dna.graph.ExecutionContext;
 import org.jboss.dna.graph.Graph;
 import org.jboss.dna.graph.JcrLexicon;
+import org.jboss.dna.graph.SecurityContext;
 import org.jboss.dna.graph.connector.RepositoryConnection;
 import org.jboss.dna.graph.connector.RepositoryConnectionFactory;
 import org.jboss.dna.graph.connector.RepositoryContext;
 import org.jboss.dna.graph.connector.RepositorySourceException;
 import org.jboss.dna.graph.connector.inmemory.InMemoryRepositorySource;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.mockito.ArgumentMatcher;
 import org.mockito.MockitoAnnotations;
@@ -60,6 +60,7 @@
 /**
  * @author Randall Hauch
  */
+ at Ignore
 public class FederatedRepositorySourceTest {
 
     private FederatedRepositorySource source;
@@ -139,11 +140,11 @@
         stub(repositoryContext.getExecutionContext()).toReturn(executionContextFactory);
         stub(repositoryContext.getRepositoryConnectionFactory()).toReturn(connectionFactory);
         stub(connectionFactory.createConnection(configurationSourceName)).toReturn(configRepositoryConnection);
-        stub(executionContextFactory.with(eq(securityDomain), anyCallbackHandler())).toReturn(context);
+        stub(executionContextFactory.with(anySecurityContext())).toReturn(context);
     }
 
-    protected static CallbackHandler anyCallbackHandler() {
-        return argThat(new ArgumentMatcher<CallbackHandler>() {
+    protected static SecurityContext anySecurityContext() {
+        return argThat(new ArgumentMatcher<SecurityContext>() {
             @Override
             public boolean matches( Object callback ) {
                 return callback != null;
@@ -175,14 +176,14 @@
     @Test( expected = RepositorySourceException.class )
     public void shouldNotCreateConnectionWhenAuthenticationFails() throws Exception {
         // Stub the execution context factory to throw a LoginException to simulate failed authentication
-        stub(executionContextFactory.with(eq(securityDomain), anyCallbackHandler())).toThrow(new LoginException());
+        stub(executionContextFactory.with(anySecurityContext())).toThrow(new LoginException());
         source.getConnection();
     }
 
     @Test( expected = NullPointerException.class )
     public void shouldPropogateAllExceptionsExceptLoginExceptionThrownFromExecutionContextFactory() throws Exception {
         // Stub the execution context factory to throw a LoginException to simulate failed authentication
-        stub(executionContextFactory.with(eq(securityDomain), anyCallbackHandler())).toThrow(new NullPointerException());
+        stub(executionContextFactory.with(anySecurityContext())).toThrow(new NullPointerException());
         source.getConnection();
     }
 




More information about the dna-commits mailing list