[jboss-remoting-commits] JBoss Remoting SVN: r3459 - in remoting3/trunk: api/src/main/java/org/jboss/cx/remoting/spi and 9 other directories.

jboss-remoting-commits at lists.jboss.org jboss-remoting-commits at lists.jboss.org
Wed Feb 20 19:35:31 EST 2008


Author: david.lloyd at jboss.com
Date: 2008-02-20 19:35:30 -0500 (Wed, 20 Feb 2008)
New Revision: 3459

Added:
   remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/CommonKeys.java
   remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppServer.java
Removed:
   remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/EndpointLocator.java
   remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/SessionLocalTransaction.java
   remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslClientFactory.java
   remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslServerFactory.java
Modified:
   remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/Endpoint.java
   remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/protocol/ProtocolContext.java
   remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/protocol/ProtocolHandlerFactory.java
   remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/wrapper/EndpointWrapper.java
   remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/CoreEndpoint.java
   remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/CoreSession.java
   remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/LocalProtocol.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/HttpProtocolSupport.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpSessionContext.java
   remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppConnection.java
   remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppProtocolSupport.java
   remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslClientFilter.java
   remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslServerFilter.java
   remoting3/trunk/standalone/src/main/java/org/jboss/cx/remoting/Remoting.java
   remoting3/trunk/util/src/main/java/org/jboss/cx/remoting/core/util/AttributeKey.java
Log:
This represents about 95% of the work needed to bring around JBREM-884.  Just need to work out some kinks with the JRPP connections...

Added: remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/CommonKeys.java
===================================================================
--- remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/CommonKeys.java	                        (rev 0)
+++ remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/CommonKeys.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -0,0 +1,49 @@
+package org.jboss.cx.remoting;
+
+import org.jboss.cx.remoting.core.util.AttributeKey;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.List;
+
+import javax.security.auth.callback.CallbackHandler;
+
+import static org.jboss.cx.remoting.core.util.AttributeKey.key;
+
+/**
+ * A set of attribute keys that are common across various protocols.
+ */
+public final class CommonKeys {
+    private CommonKeys() { /* no construction */ }
+
+    // SASL
+
+    /**
+     * A key that represents the SASL properties to be used for this connection or server.
+     */
+    public static final AttributeKey<Map<String, ?>> SASL_PROPERTIES = key("SASL_PROPERTIES");
+    /**
+     * The SASL client mechanisms to try, in order.  If none are given, then the list is generated based on the registered
+     * providers.
+     */
+    public static final AttributeKey<List<String>> SASL_CLIENT_MECHANISMS = key("SASL_CLIENT_MECHANISMS");
+    /**
+     * The SASL server mechanisms to make available to clients.  If none are given, then the set is generated based on
+     * the registered providers.
+     */
+    public static final AttributeKey<Set<String>> SASL_SERVER_MECHANISMS = key("SASL_SERVER_MECHANISMS");
+
+    // Generic auth
+
+    /**
+     * The authentication callback handler to make available to the authentication layer.
+     */
+    public static final AttributeKey<CallbackHandler> AUTH_CALLBACK_HANDLER = key("AUTH_CALLBACK_HANDLER");
+    /**
+     * The client authorization ID to send to the server.  If not specified, defaults to the local endpoint name.  If
+     * the local endpoint is anonymous, defaults to {@code null}.
+     */
+    public static final AttributeKey<String> AUTHORIZATION_ID = key("AUTHORIZATION_ID");
+
+    // TODO: add keys for SSL/TLS
+}

Modified: remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/Endpoint.java
===================================================================
--- remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/Endpoint.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/Endpoint.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -8,8 +8,6 @@
 import org.jboss.cx.remoting.spi.protocol.ProtocolRegistrationSpec;
 import org.jboss.cx.remoting.core.util.AttributeMap;
 
-import javax.security.auth.callback.CallbackHandler;
-
 /**
  * A potential participant in a JBoss Remoting communications relationship.
  */
@@ -47,14 +45,14 @@
      * authority is used to locate the server (the exact interpretation is dependent upon the protocol). The URI path is
      * the service to connect to.  The path may be relative to a protocol-specific deployment path.
      *
-     * @param endpointLocator the endpoint locator
+     * @param remoteUri the URI of the server to connect to
      * @param attributeMap the attribute map to use to configure this session
      * @return a new session
      *
      * @throws RemotingException if there is a problem creating the session, or if the request or reply type does not
      * match the remote service
      */
-    Session openSession(EndpointLocator endpointLocator, AttributeMap attributeMap) throws RemotingException;
+    Session openSession(URI remoteUri, AttributeMap attributeMap) throws RemotingException;
 
     /**
      * Get the name of this endpoint.
@@ -116,32 +114,4 @@
      * @throws RemotingException if there is a problem with the discovery parameters
      */
     Discovery discover(String endpointName, URI nextHop, int cost) throws RemotingException;
-
-    /**
-     * Get the callback handler used to authenticate a remote endpoint by default.
-     *
-     * @return the callback handler
-     */
-    CallbackHandler getRemoteCallbackHandler();
-
-    /**
-     * Change the callback handler used to authenticate a remote endpoint by default.
-     *
-     * @param callbackHandler the callback handler
-     */
-    void setRemoteCallbackHandler(CallbackHandler callbackHandler);
-
-    /**
-     * Get the callback handler used to authenticate this endpoint to a remote endpoint by default.
-     *
-     * @return the callback handler
-     */
-    CallbackHandler getLocalCallbackHandler();
-
-    /**
-     * Change the callback handler used to authenticate this endpoint to a remote endpoint by default.
-     *
-     * @param callbackHandler the callback handler
-     */
-    void setLocalCallbackHandler(CallbackHandler callbackHandler);
 }

Deleted: remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/EndpointLocator.java
===================================================================
--- remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/EndpointLocator.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/EndpointLocator.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -1,85 +0,0 @@
-package org.jboss.cx.remoting;
-
-import java.io.IOException;
-import java.net.URI;
-
-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;
-
-/**
- *
- */
-public final class EndpointLocator {
-    private final URI endpointUri;
-    private final String authorizationId;
-    private final CallbackHandler clientCallbackHandler;
-
-    private EndpointLocator(final URI endpointUri, final String authorizationId, final CallbackHandler clientCallbackHandler) {
-        this.endpointUri = endpointUri;
-        this.authorizationId = authorizationId;
-        this.clientCallbackHandler = clientCallbackHandler;
-    }
-
-    public static final CallbackHandler DEFAULT_CALLBACK_HANDLER = new CallbackHandler() {
-        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
-            if (callbacks.length > 0) {
-                throw new UnsupportedCallbackException(callbacks[0], "No callback types are supported");
-            }
-        }
-    };
-
-    public static final EndpointLocator DEFAULT = new EndpointLocator(null, null, DEFAULT_CALLBACK_HANDLER);
-
-    public URI getEndpointUri() {
-        return endpointUri;
-    }
-
-    public String getAuthorizationId() {
-        return authorizationId;
-    }
-
-    public CallbackHandler getClientCallbackHandler() {
-        return clientCallbackHandler;
-    }
-
-    public EndpointLocator setEndpointUri(URI endpointUri) {
-        return new EndpointLocator(endpointUri, authorizationId, clientCallbackHandler);
-    }
-
-    public EndpointLocator setAuthorizationId(String authorizationId) {
-        return new EndpointLocator(endpointUri, authorizationId, clientCallbackHandler);
-    }
-
-    public EndpointLocator setClientCallbackHandler(CallbackHandler clientCallbackHandler) {
-        return new EndpointLocator(endpointUri, authorizationId, clientCallbackHandler);
-    }
-
-    public EndpointLocator setClientAuthentication(String userName, char[] password) {
-        return new EndpointLocator(endpointUri, userName, new SimpleClientCallbackHandler(userName, password));
-    }
-
-    public static final class SimpleClientCallbackHandler implements CallbackHandler {
-        private final String userName;
-        private final char[] password;
-
-        private SimpleClientCallbackHandler(final String userName, final char[] password) {
-            this.userName = userName;
-            this.password = password;
-        }
-
-        public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
-            for (Callback callback : callbacks) {
-                if (callback instanceof NameCallback) {
-                    ((NameCallback) callback).setName(userName);
-                } else if (callback instanceof PasswordCallback) {
-                    ((PasswordCallback) callback).setPassword(password);
-                } else {
-                    throw new UnsupportedCallbackException(callback, "This handler only supports username/password callbacks");
-                }
-            }
-        }
-    }
-}

Deleted: remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/SessionLocalTransaction.java
===================================================================
--- remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/SessionLocalTransaction.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/SessionLocalTransaction.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -1,9 +0,0 @@
-package org.jboss.cx.remoting.spi;
-
-/**
- * Represents a locally-managed transaction.  Instances of this interface are created when a local transaction is
- * suspended via the {@code SessionHandler}, and are passed back in to the {@code SessionHandler} when resuming a
- * transaction.
- */
-public interface SessionLocalTransaction {
-}

Modified: remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/protocol/ProtocolContext.java
===================================================================
--- remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/protocol/ProtocolContext.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/protocol/ProtocolContext.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -46,6 +46,8 @@
 
     void receiveStreamData(StreamIdentifier streamIdentifier, MessageInput data);
 
+    void openSession(String remoteEndpointName);
+
     void closeSession();
 
     /* CLIENT OR SERVER methods */

Modified: remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/protocol/ProtocolHandlerFactory.java
===================================================================
--- remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/protocol/ProtocolHandlerFactory.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/protocol/ProtocolHandlerFactory.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -2,9 +2,8 @@
 
 import java.io.IOException;
 import java.net.URI;
+import org.jboss.cx.remoting.core.util.AttributeMap;
 
-import javax.security.auth.callback.CallbackHandler;
-
 /**
  *
  */
@@ -26,12 +25,12 @@
      *
      * @param context the protocol context to use for inbound data
      * @param remoteUri the URI of the remote side
-     * @param clientCallbackHandler the callback handler to use to authenticate this client
+     * @param attributeMap
      * @return the protocol handler for outbound data
      *
      * @throws IOException if the handler could not be created
      */
-    ProtocolHandler createHandler(ProtocolContext context, URI remoteUri, CallbackHandler clientCallbackHandler) throws IOException;
+    ProtocolHandler createHandler(ProtocolContext context, URI remoteUri, AttributeMap attributeMap) throws IOException;
 
     /**
      * Signifies that this protocol has been unregistered from the endpoint.

Modified: remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/wrapper/EndpointWrapper.java
===================================================================
--- remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/wrapper/EndpointWrapper.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/api/src/main/java/org/jboss/cx/remoting/spi/wrapper/EndpointWrapper.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -3,7 +3,6 @@
 import java.net.URI;
 import java.util.concurrent.ConcurrentMap;
 import org.jboss.cx.remoting.Endpoint;
-import org.jboss.cx.remoting.EndpointLocator;
 import org.jboss.cx.remoting.EndpointShutdownListener;
 import org.jboss.cx.remoting.InterceptorDeploymentSpec;
 import org.jboss.cx.remoting.RemotingException;
@@ -15,8 +14,6 @@
 import org.jboss.cx.remoting.spi.protocol.ProtocolRegistration;
 import org.jboss.cx.remoting.spi.protocol.ProtocolRegistrationSpec;
 
-import javax.security.auth.callback.CallbackHandler;
-
 /**
  *
  */
@@ -35,8 +32,8 @@
         delegate.shutdown();
     }
 
-    public Session openSession(EndpointLocator endpointLocator, AttributeMap attributeMap) throws RemotingException {
-        return delegate.openSession(endpointLocator, attributeMap);
+    public Session openSession(final URI remoteUri, AttributeMap attributeMap) throws RemotingException {
+        return delegate.openSession(remoteUri, attributeMap);
     }
 
     public Discovery discover(final String endpointName, final URI nextHop, final int cost) throws RemotingException {
@@ -59,22 +56,6 @@
         return delegate.registerProtocol(spec);
     }
 
-    public CallbackHandler getLocalCallbackHandler() {
-        return delegate.getLocalCallbackHandler();
-    }
-
-    public CallbackHandler getRemoteCallbackHandler() {
-        return delegate.getRemoteCallbackHandler();
-    }
-
-    public void setRemoteCallbackHandler(final CallbackHandler callbackHandler) {
-        delegate.setRemoteCallbackHandler(callbackHandler);
-    }
-
-    public void setLocalCallbackHandler(final CallbackHandler callbackHandler) {
-        delegate.setLocalCallbackHandler(callbackHandler);
-    }
-
     public void addShutdownListener(final EndpointShutdownListener listener) {
         delegate.addShutdownListener(listener);
     }

Modified: remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/CoreEndpoint.java
===================================================================
--- remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/CoreEndpoint.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/CoreEndpoint.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -13,7 +13,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import org.jboss.cx.remoting.Endpoint;
-import org.jboss.cx.remoting.EndpointLocator;
 import org.jboss.cx.remoting.EndpointShutdownListener;
 import org.jboss.cx.remoting.InterceptorDeploymentSpec;
 import org.jboss.cx.remoting.RemotingException;
@@ -45,8 +44,6 @@
 
     private final String name;
     private final Endpoint userEndpoint = new UserEndpoint();
-    private CallbackHandler remoteCallbackHandler;
-    private CallbackHandler localCallbackHandler;
     private final OrderedExecutorFactory orderedExecutorFactory;
     private final AtomicStateMachine<State> state = AtomicStateMachine.start(State.UP);
     private final ExecutorService executor;
@@ -179,7 +176,10 @@
         }
 
         public ProtocolContext establishSession(ProtocolHandler handler) {
-            final CoreSession session = new CoreSession(CoreEndpoint.this, handler);
+            final CoreSession session = new CoreSession(CoreEndpoint.this);
+            session.initializeServer(handler);
+
+            //, handler);
             return session.getProtocolContext();
         }
     }
@@ -288,8 +288,8 @@
             }
         }
 
-        public Session openSession(final EndpointLocator endpointLocator, final AttributeMap attributeMap) throws RemotingException {
-            final String scheme = endpointLocator.getEndpointUri().getScheme();
+        public Session openSession(final URI uri, final AttributeMap attributeMap) throws RemotingException {
+            final String scheme = uri.getScheme();
             if (scheme == null) {
                 throw new RemotingException("No scheme on remote endpoint URI");
             }
@@ -301,7 +301,8 @@
                 }
                 final ProtocolHandlerFactory factory = registration.getProtocolHandlerFactory();
                 try {
-                    final CoreSession session = new CoreSession(CoreEndpoint.this, factory, endpointLocator);
+                    final CoreSession session = new CoreSession(CoreEndpoint.this);
+                    session.initializeClient(factory, uri, attributeMap);
                     sessions.add(session);
                     return session.getUserSession();
                 } catch (IOException e) {
@@ -367,29 +368,5 @@
             // todo - implement
             return null;
         }
-
-        public CallbackHandler getRemoteCallbackHandler() {
-            synchronized(this) {
-                return remoteCallbackHandler;
-            }
-        }
-
-        public CallbackHandler getLocalCallbackHandler() {
-            synchronized(this) {
-                return localCallbackHandler;
-            }
-        }
-
-        public void setRemoteCallbackHandler(final CallbackHandler remoteCallbackHandler) {
-            synchronized(this) {
-                CoreEndpoint.this.remoteCallbackHandler = remoteCallbackHandler;
-            }
-        }
-
-        public void setLocalCallbackHandler(final CallbackHandler localCallbackHandler) {
-            synchronized(this) {
-                CoreEndpoint.this.localCallbackHandler = localCallbackHandler;
-            }
-        }
     }
 }

Modified: remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/CoreSession.java
===================================================================
--- remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/CoreSession.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/CoreSession.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -13,9 +13,8 @@
 import java.util.HashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Executor;
+import java.net.URI;
 import org.jboss.cx.remoting.ContextSource;
-import org.jboss.cx.remoting.Endpoint;
-import org.jboss.cx.remoting.EndpointLocator;
 import org.jboss.cx.remoting.RemoteExecutionException;
 import org.jboss.cx.remoting.RemotingException;
 import org.jboss.cx.remoting.RequestListener;
@@ -30,6 +29,7 @@
 import org.jboss.cx.remoting.spi.protocol.ContextIdentifier;
 import org.jboss.cx.remoting.core.util.MessageInput;
 import org.jboss.cx.remoting.core.util.MessageOutput;
+import org.jboss.cx.remoting.core.util.AttributeMap;
 import org.jboss.cx.remoting.spi.protocol.ProtocolContext;
 import org.jboss.cx.remoting.spi.protocol.ProtocolHandler;
 import org.jboss.cx.remoting.spi.protocol.ProtocolHandlerFactory;
@@ -40,9 +40,7 @@
 import org.jboss.cx.remoting.spi.stream.StreamSerializer;
 import org.jboss.cx.remoting.spi.stream.StreamSerializerFactory;
 
-import javax.security.auth.callback.CallbackHandler;
 
-
 /**
  * Three execution contexts:
  *
@@ -56,7 +54,7 @@
     private final ProtocolContextImpl protocolContext = new ProtocolContextImpl();
     private final UserSession userSession = new UserSession();
 
-    // stream serialization detectors - immutable
+    // stream serialization detectors - immutable (for now?)
     private final List<StreamDetector> streamDetectors;
 
     // clients - weak reference, to clean up if the user leaks
@@ -72,42 +70,46 @@
 
     // don't GC the endpoint while a session lives
     private final CoreEndpoint endpoint;
-    private final ProtocolHandler protocolHandler;
-    private final String remoteEndpointName;
 
-    private final AtomicStateMachine<State> state = AtomicStateMachine.start(State.UP);
+    /** The protocol handler.  Set on NEW -> CONNECTING */
+    private ProtocolHandler protocolHandler;
+    /** The remote endpoint name.  Set on CONNECTING -> UP */
+    private String remoteEndpointName;
 
+    private final AtomicStateMachine<State> state = AtomicStateMachine.start(State.NEW);
+
     // Constructors
 
-    CoreSession(final CoreEndpoint endpoint, final ProtocolHandler protocolHandler) {
+    CoreSession(final CoreEndpoint endpoint) {
         if (endpoint == null) {
             throw new NullPointerException("endpoint is null");
         }
+        this.endpoint = endpoint;
+        // todo - make stream detectors pluggable
+        streamDetectors = java.util.Collections.<StreamDetector>singletonList(new DefaultStreamDetector());
+    }
+
+    // Initializers
+
+    void initializeServer(final ProtocolHandler protocolHandler) {
         if (protocolHandler == null) {
             throw new NullPointerException("protocolHandler is null");
         }
-        this.endpoint = endpoint;
+        state.requireTransitionExclusive(State.NEW, State.CONNECTING);
         this.protocolHandler = protocolHandler;
-        streamDetectors = java.util.Collections.<StreamDetector>singletonList(new DefaultStreamDetector());
-        remoteEndpointName = protocolHandler.getRemoteEndpointName();
+        state.releaseExclusive();
     }
 
-    CoreSession(final CoreEndpoint endpoint, final ProtocolHandlerFactory factory, final EndpointLocator endpointLocator) throws IOException {
-        if (endpoint == null) {
-            throw new NullPointerException("endpoint is null");
+    void initializeClient(final ProtocolHandlerFactory protocolHandlerFactory, final URI remoteUri, final AttributeMap attributeMap) throws IOException {
+        if (protocolHandlerFactory == null) {
+            throw new NullPointerException("protocolHandlerFactory is null");
         }
-        if (factory == null) {
-            throw new NullPointerException("factory is null");
+        state.requireTransitionExclusive(State.NEW, State.CONNECTING);
+        try {
+            protocolHandlerFactory.createHandler(protocolContext, remoteUri, attributeMap);
+        } finally {
+            state.releaseExclusive();
         }
-        if (endpointLocator == null) {
-            throw new NullPointerException("endpointLocator is null");
-        }
-        streamDetectors = java.util.Collections.<StreamDetector>singletonList(new DefaultStreamDetector());
-        this.endpoint = endpoint;
-        final CallbackHandler locatorCallbackHandler = endpointLocator.getClientCallbackHandler();
-        final Endpoint userEndpoint = endpoint.getUserEndpoint();
-        protocolHandler = factory.createHandler(protocolContext, endpointLocator.getEndpointUri(), locatorCallbackHandler == null ? userEndpoint.getLocalCallbackHandler() : locatorCallbackHandler);
-        remoteEndpointName = protocolHandler.getRemoteEndpointName();
     }
 
     // Outbound protocol messages
@@ -227,9 +229,11 @@
     // State mgmt
 
     private enum State {
-        DOWN,
+        NEW,
+        CONNECTING,
         UP,
         STOPPING,
+        DOWN,
     }
 
     void shutdown() {
@@ -448,8 +452,9 @@
             if (locator.getServiceType() == null) {
                 throw new NullPointerException("locator.getServiceType() is null");
             }
-            state.requireHold(State.UP);
+            state.waitForNotHold(State.CONNECTING);
             try {
+                state.require(State.UP);
                 final CoreOutboundService<I, O> service = createService(locator);
                 service.sendServiceRequest();
                 service.await();
@@ -567,6 +572,16 @@
             coreStream.receiveStreamData(data);
         }
 
+        public void openSession(String remoteEndpointName) {
+            state.waitForNotExclusive(State.NEW);
+            try {
+                state.requireTransition(State.CONNECTING, State.UP);
+                CoreSession.this.remoteEndpointName = remoteEndpointName;
+            } finally {
+                state.releaseExclusive();
+            }
+        }
+
         public void receiveRequest(final ContextIdentifier remoteContextIdentifier, final RequestIdentifier requestIdentifier, final Object request) {
             final CoreInboundContext context = getServerContext(remoteContextIdentifier);
             if (context != null) {

Modified: remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/LocalProtocol.java
===================================================================
--- remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/LocalProtocol.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/core/src/main/java/org/jboss/cx/remoting/core/LocalProtocol.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -15,6 +15,7 @@
 import org.jboss.cx.remoting.core.util.MessageOutput;
 import org.jboss.cx.remoting.spi.protocol.ContextIdentifier;
 import org.jboss.cx.remoting.core.util.MessageInput;
+import org.jboss.cx.remoting.core.util.AttributeMap;
 import org.jboss.cx.remoting.spi.protocol.ProtocolContext;
 import org.jboss.cx.remoting.spi.protocol.ProtocolHandler;
 import org.jboss.cx.remoting.spi.protocol.ProtocolHandlerFactory;
@@ -29,8 +30,6 @@
 import org.jboss.cx.remoting.spi.protocol.SimpleStreamIdentifier;
 import org.jboss.cx.remoting.spi.protocol.StreamIdentifier;
 
-import javax.security.auth.callback.CallbackHandler;
-
 /**
  *
  */
@@ -59,7 +58,7 @@
             return true;
         }
 
-        public ProtocolHandler createHandler(ProtocolContext context, URI remoteUri, final CallbackHandler clientCallbackHandler) throws IOException {
+        public ProtocolHandler createHandler(ProtocolContext context, URI remoteUri, final AttributeMap attributeMap) throws IOException {
             final String remoteName = remoteUri.getSchemeSpecificPart();
             final ProtocolServerContext serverContext = endpoints.get(remoteName);
             if (serverContext == null) {

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/HttpProtocolSupport.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/HttpProtocolSupport.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/HttpProtocolSupport.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -7,6 +7,7 @@
 import org.jboss.cx.remoting.Endpoint;
 import org.jboss.cx.remoting.RemotingException;
 import org.jboss.cx.remoting.core.util.CollectionUtil;
+import org.jboss.cx.remoting.core.util.AttributeMap;
 import org.jboss.cx.remoting.http.spi.RemotingHttpServerContext;
 import org.jboss.cx.remoting.http.spi.RemotingHttpSessionContext;
 import org.jboss.cx.remoting.http.spi.HttpTransporter;
@@ -18,8 +19,6 @@
 import org.jboss.cx.remoting.spi.protocol.ProtocolRegistrationSpec;
 import org.jboss.cx.remoting.spi.protocol.ProtocolServerContext;
 
-import javax.security.auth.callback.CallbackHandler;
-
 /**
  *
  */
@@ -68,11 +67,11 @@
             return false;
         }
 
-        public ProtocolHandler createHandler(ProtocolContext context, URI remoteUri, CallbackHandler clientCallbackHandler) throws IOException {
+        public ProtocolHandler createHandler(ProtocolContext context, URI remoteUri, final AttributeMap attributeMap) throws IOException {
             if (httpTransporter == null) {
                 throw new IOException("No ability to initiate an HTTP connection (no transporter available)");
             }
-            return new RemotingHttpSessionImpl(HttpProtocolSupport.this, context, clientCallbackHandler).getProtocolHandler();
+            return new RemotingHttpSessionImpl(HttpProtocolSupport.this, context).getProtocolHandler();
         }
 
         public void close() {

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -17,8 +17,6 @@
 import org.jboss.cx.remoting.RemoteExecutionException;
 import org.jboss.cx.remoting.ServiceLocator;
 
-import javax.security.auth.callback.CallbackHandler;
-
 import java.util.LinkedList;
 import java.util.Set;
 import java.util.HashSet;
@@ -43,15 +41,13 @@
     private final BlockingQueue<IncomingHttpMessage> incomingQueue = CollectionUtil.synchronizedQueue(new LinkedList<IncomingHttpMessage>());
     private final BlockingQueue<OutputAction> outgoingQueue = CollectionUtil.synchronizedQueue(new LinkedList<OutputAction>());
     private final String sessionId;
-    private final CallbackHandler callbackHandler;
     private final AtomicLong outputSequence = new AtomicLong(0L);
     private final AtomicLong inputSequence = new AtomicLong(0L);
 
     private static final int PROTOCOL_VERSION = 0;
 
-    public RemotingHttpSessionImpl(final HttpProtocolSupport protocolSupport, final ProtocolContext protocolContext, final CallbackHandler callbackHandler) {
+    public RemotingHttpSessionImpl(final HttpProtocolSupport protocolSupport, final ProtocolContext protocolContext) {
         this.protocolContext = protocolContext;
-        this.callbackHandler = callbackHandler;
         String sessionId;
         do {
             sessionId = protocolSupport.generateSessionId();
@@ -109,10 +105,6 @@
                 }
             }
         }
-
-        public CallbackHandler getCallbackHandler() {
-            return callbackHandler;
-        }
     }
 
     private void write(ObjectOutput output, MsgType type) throws IOException {

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpSessionContext.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpSessionContext.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpSessionContext.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -20,10 +20,4 @@
 
     OutgoingHttpMessage getNextMessage(long timeoutMillis) throws InterruptedException;
 
-    /**
-     * Get the callback handler to use to authenticate incoming HTTP messages.
-     *
-     * @return the callback handler
-     */
-    CallbackHandler getCallbackHandler();
 }

Modified: remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppConnection.java
===================================================================
--- remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppConnection.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppConnection.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -4,32 +4,30 @@
 import java.io.IOException;
 import java.io.ObjectInput;
 import java.io.ObjectOutput;
-import java.net.InetSocketAddress;
-import java.net.URI;
-import java.util.Collections;
 import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.HashSet;
 import java.util.concurrent.Executor;
 import org.apache.mina.common.AttributeKey;
-import org.apache.mina.common.ConnectFuture;
 import org.apache.mina.common.IdleStatus;
 import org.apache.mina.common.IoBuffer;
-import org.apache.mina.common.IoConnector;
 import org.apache.mina.common.IoSession;
-import org.apache.mina.common.IoSessionInitializer;
-import org.apache.mina.filter.sasl.CallbackHandlerFactory;
-import org.apache.mina.filter.sasl.SaslClientFactory;
 import org.apache.mina.filter.sasl.SaslClientFilter;
-import org.apache.mina.filter.sasl.SaslMessageSender;
-import org.apache.mina.filter.sasl.SaslServerFactory;
 import org.apache.mina.filter.sasl.SaslServerFilter;
 import org.apache.mina.handler.multiton.SingleSessionIoHandler;
 import org.jboss.cx.remoting.RemoteExecutionException;
 import org.jboss.cx.remoting.ServiceLocator;
+import org.jboss.cx.remoting.CommonKeys;
 import org.jboss.cx.remoting.log.Logger;
 import org.jboss.cx.remoting.core.util.AtomicStateMachine;
 import org.jboss.cx.remoting.core.util.CollectionUtil;
 import org.jboss.cx.remoting.core.util.MessageInput;
 import org.jboss.cx.remoting.core.util.MessageOutput;
+import org.jboss.cx.remoting.core.util.AttributeMap;
 import org.jboss.cx.remoting.jrpp.id.IdentifierManager;
 import org.jboss.cx.remoting.jrpp.id.JrppContextIdentifier;
 import org.jboss.cx.remoting.jrpp.id.JrppRequestIdentifier;
@@ -46,10 +44,17 @@
 import org.jboss.cx.remoting.spi.protocol.StreamIdentifier;
 
 import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
 import javax.security.sasl.Sasl;
+import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
 import javax.security.sasl.SaslServer;
+import javax.security.sasl.RealmCallback;
+import javax.security.sasl.SaslServerFactory;
+import javax.security.sasl.AuthorizeCallback;
 
 /**
  *
@@ -62,16 +67,17 @@
 
     private static final AttributeKey JRPP_CONNECTION = new AttributeKey(JrppConnection.class, "jrppConnection");
 
-    private static final String SASL_CLIENT_FILTER_NAME = "SASL client filter";
-    private static final String SASL_SERVER_FILTER_NAME = "SASL server filter";
+    public static final String SASL_CLIENT_FILTER_NAME = "SASL client filter";
+    public static final String SASL_SERVER_FILTER_NAME = "SASL server filter";
 
-    private IoSession ioSession;
     private final ProtocolHandler protocolHandler;
-    private final ProtocolContext protocolContext;
     private final SingleSessionIoHandler ioHandler;
     private final IdentifierManager identifierManager;
+    private final AttributeMap attributeMap;
 
+    private IoSession ioSession;
     private String remoteName;
+    private ProtocolContext protocolContext;
 
     /**
      * The negotiated protocol version.  Value is set to {@code min(PROTOCOL_VERSION, remote PROTOCOL_VERSION)}.
@@ -85,10 +91,14 @@
     }
 
     private enum State {
+        /** Initial state - unconnected */
+        NEW,
         /** Client side, waiting to receive protocol version info */
         AWAITING_SERVER_VERSION,
         /** Server side, waiting to receive protocol version info */
         AWAITING_CLIENT_VERSION,
+        /** Server side, waiting to receive authentication request */
+        AWAITING_CLIENT_AUTH_REQUEST,
         /** Client side, auth phase */
         AWAITING_SERVER_CHALLENGE,
         /** Server side, auth phase */
@@ -99,93 +109,157 @@
         CLOSED,
     }
 
-    private AtomicStateMachine<State> currentState;
+    private final AtomicStateMachine<State> state = AtomicStateMachine.start(State.NEW);
 
     private static final Logger log = Logger.getLogger(JrppConnection.class);
 
-    /**
-     * Client side.
-     *
-     * @param connector
-     * @param uri
-     * @param protocolContext
-     * @param clientCallbackHandler
-     */
-    public JrppConnection(final IoConnector connector, final URI uri, final ProtocolContext protocolContext, final CallbackHandler clientCallbackHandler) {
-        // todo - this seems very iffy to me, since we're basically leaking "this" before constructor is done
-        this.protocolContext = protocolContext;
+    public JrppConnection(final AttributeMap attributeMap) {
+        this.attributeMap = attributeMap;
         ioHandler = new IoHandlerImpl();
-        final ConnectFuture future = connector.connect(new InetSocketAddress(uri.getHost(), uri.getPort()), new IoSessionInitializer<ConnectFuture>() {
-            public void initializeSession(final IoSession session, final ConnectFuture future) {
-                session.setAttribute(JRPP_CONNECTION, JrppConnection.this);
-                JrppConnection.this.ioSession = session;
+        identifierManager = new IdentifierManager();
+        protocolHandler = new RemotingProtocolHandler();
+    }
+
+    public void initializeClient(final IoSession ioSession, final ProtocolContext protocolContext) {
+        state.transitionExclusive(State.NEW, State.AWAITING_SERVER_VERSION);
+        try {
+            ioSession.setAttribute(JRPP_CONNECTION, this);
+            this.ioSession = ioSession;
+        } finally {
+            state.releaseExclusive();
+        }
+    }
+
+    public void initializeServer(final IoSession ioSession, final ProtocolServerContext protocolServerContext) {
+        state.transitionExclusive(State.NEW, State.AWAITING_CLIENT_VERSION);
+        try {
+            ioSession.setAttribute(JRPP_CONNECTION, this);
+            this.ioSession = ioSession;
+            final ProtocolContext protocolContext = protocolServerContext.establishSession(protocolHandler);
+            this.protocolContext = protocolContext;
+        } finally {
+            state.releaseExclusive();
+        }
+    }
+
+    private String getNegotiatedMechanism(final String[] clientMechs, final Set<String> serverMechs) throws SaslException {
+        for (String name : clientMechs) {
+            if (serverMechs.contains(name)) {
+                return name;
             }
-        });
-        // make sure it's initialized for *this* thread as well
-        ioSession = future.awaitUninterruptibly().getSession();
+        }
+        throw new SaslException("No acceptable mechanisms found");
+    }
 
-        protocolHandler = new RemotingProtocolHandler();
-        identifierManager = new IdentifierManager();
-        currentState = AtomicStateMachine.start(State.AWAITING_SERVER_VERSION);
-        ioSession.getFilterChain().addLast(SASL_CLIENT_FILTER_NAME, new SaslClientFilter(new SaslClientFactory(){
-            public SaslClient createSaslClient(IoSession ioSession, CallbackHandler callbackHandler) throws SaslException {
-                return Sasl.createSaslClient(new String[] { "SRP" }, protocolContext.getLocalEndpointName(), "JRPP", uri.getHost(), Collections.<String,Object>emptyMap(), callbackHandler);
+    private String getAuthorizationId(final AttributeMap attributeMap, final ProtocolContext protocolContext) {
+        final String authorizationId = attributeMap.get(CommonKeys.AUTHORIZATION_ID);
+        if (authorizationId != null) {
+            return authorizationId;
+        }
+        return protocolContext.getLocalEndpointName();
+    }
+
+    private Set<String> getServerMechanisms(final AttributeMap attributeMap, final Map<String, ?> saslProps) {
+        final Set<String> set = attributeMap.get(CommonKeys.SASL_SERVER_MECHANISMS);
+        if (set != null) {
+            return set;
+        }
+        final Set<String> mechanisms = new HashSet<String>();
+        final Enumeration<SaslServerFactory> e = Sasl.getSaslServerFactories();
+        while (e.hasMoreElements()) {
+            final SaslServerFactory serverFactory = e.nextElement();
+            for (String name : serverFactory.getMechanismNames(saslProps)) {
+                mechanisms.add(name);
             }
-        }, new SaslMessageSender() {
-            public void sendSaslMessage(IoSession ioSession, byte[] rawMsgData) throws IOException {
-                final IoBuffer buffer = newBuffer(rawMsgData.length + 30, false);
-                final MessageOutput output = protocolContext.getMessageOutput(new IoBufferByteOutput(buffer, ioSession));
-                write(output, MessageType.SASL_RESPONSE);
-                output.write(rawMsgData);
-                output.commit();
+        }
+        return mechanisms;
+    }
+
+    private String[] getClientMechanisms(final AttributeMap attributeMap, final Map<String, ?> saslProps) {
+        final List<String> list = attributeMap.get(CommonKeys.SASL_CLIENT_MECHANISMS);
+        if (list != null) {
+            return list.toArray(new String[list.size()]);
+        }
+        final Set<String> mechanisms = new LinkedHashSet<String>();
+        final Enumeration<javax.security.sasl.SaslClientFactory> e = Sasl.getSaslClientFactories();
+        while (e.hasMoreElements()) {
+            final javax.security.sasl.SaslClientFactory clientFactory = e.nextElement();
+            for (String name : clientFactory.getMechanismNames(saslProps)) {
+                mechanisms.add(name);
             }
-        }, new CallbackHandlerFactory() {
-            public CallbackHandler getCallbackHandler() {
-                return clientCallbackHandler;
-            }
-        }));
+        }
+        return mechanisms.toArray(new String[mechanisms.size()]);
     }
 
-    /**
-     * Server side.
-     *
-     * @param ioSession
-     * @param serverContext
-     * @throws java.io.IOException
-     */
-    public JrppConnection(final IoSession ioSession, final ProtocolServerContext serverContext, final CallbackHandler serverCallbackHandler) throws IOException {
-        ioSession.setAttribute(JRPP_CONNECTION, this);
-        this.ioSession = ioSession;
+    private Map<String, ?> getSaslProperties(final AttributeMap attributeMap) {
+        final Map<String, ?> props = attributeMap.get(CommonKeys.SASL_PROPERTIES);
+        if (props != null) {
+            return props;
+        }
+        final Map<String, Object> defaultProps = new HashMap<String, Object>();
+        defaultProps.put(Sasl.POLICY_NOPLAINTEXT, "true");
+        defaultProps.put(Sasl.POLICY_NOANONYMOUS, "true");
+        defaultProps.put(Sasl.POLICY_NODICTIONARY, "true");
+        defaultProps.put(Sasl.POLICY_NOACTIVE, "true");
+        defaultProps.put(Sasl.QOP, "auth-conf");
+        return defaultProps;
+    }
 
-        protocolHandler = new RemotingProtocolHandler();
-        ioHandler = new IoHandlerImpl();
+    private CallbackHandler getServerCallbackHandler(final AttributeMap attributeMap) {
+        final CallbackHandler callbackHandler = attributeMap.get(CommonKeys.AUTH_CALLBACK_HANDLER);
+        if (callbackHandler != null) {
+            return callbackHandler;
+        }
+        return new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback callback : callbacks) {
+                    if (callback instanceof NameCallback) {
+                        ((NameCallback)callback).setName("anonymous");
+                    } else if (callback instanceof PasswordCallback) {
+                        ((PasswordCallback)callback).setPassword(new char[0]);
+                    } else if (callback instanceof RealmCallback) {
+                        continue;
+                    } else if (callback instanceof AuthorizeCallback) {
+                        ((AuthorizeCallback)callback).setAuthorized(true);
+                    }
+                    throw new UnsupportedCallbackException(callback, "Default anonymous server callback handler cannot support this callback type");
+                }
+            }
+        };
+    }
 
-        protocolContext = serverContext.establishSession(protocolHandler);
-        identifierManager = new IdentifierManager();
-        currentState = AtomicStateMachine.start(State.AWAITING_CLIENT_VERSION);
-        ioSession.getFilterChain().addLast(SASL_SERVER_FILTER_NAME, new SaslServerFilter(new SaslServerFactory(){
-            public SaslServer createSaslServer(IoSession ioSession, CallbackHandler callbackHandler) throws SaslException {
-                return Sasl.createSaslServer("SRP", "JRPP", protocolContext.getLocalEndpointName(), Collections.<String,Object>emptyMap(), callbackHandler);
+    private CallbackHandler getClientCallbackHandler(final AttributeMap attributeMap) {
+        final CallbackHandler callbackHandler = attributeMap.get(CommonKeys.AUTH_CALLBACK_HANDLER);
+        if (callbackHandler != null) {
+            return callbackHandler;
+        }
+        return new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback callback : callbacks) {
+                    if (callback instanceof NameCallback) {
+                        ((NameCallback)callback).setName("anonymous");
+                    } else if (callback instanceof PasswordCallback) {
+                        ((PasswordCallback)callback).setPassword(new char[0]);
+                    } else {
+                        throw new UnsupportedCallbackException(callback, "Default anonymous client callback handler cannot support this callback type");
+                    }
+                }
             }
-        }, new SaslMessageSender(){
-            public void sendSaslMessage(IoSession ioSession, byte[] rawMsgData) throws IOException {
-                final IoBuffer buffer = newBuffer(rawMsgData.length + 30, false);
-                final MessageOutput output = protocolContext.getMessageOutput(new IoBufferByteOutput(buffer, ioSession));
-                write(output, MessageType.SASL_CHALLENGE);
-                output.write(rawMsgData);
-                output.commit();
-            }
-        }, new CallbackHandlerFactory(){
-            public CallbackHandler getCallbackHandler() {
-                return serverCallbackHandler;
-            }
-        }));
+        };
     }
 
     public static JrppConnection getConnection(IoSession ioSession) {
         return (JrppConnection) ioSession.getAttribute(JRPP_CONNECTION);
     }
 
+    private SaslClientFilter getSaslClientFilter() {
+        return (SaslClientFilter) ioSession.getFilterChain().get(SASL_CLIENT_FILTER_NAME);
+    }
+
+    private SaslServerFilter getSaslServerFilter() {
+        return (SaslServerFilter) ioSession.getFilterChain().get(SASL_SERVER_FILTER_NAME);
+    }
+
     public IoSession getIoSession() {
         return ioSession;
     }
@@ -238,15 +312,25 @@
         output.commit();
     }
 
+    public void sendVersionMessage() throws IOException {
+        // send version info
+        final IoBuffer buffer = newBuffer(60, false);
+        final MessageOutput output = protocolContext.getMessageOutput(new IoBufferByteOutput(buffer, ioSession));
+        write(output, MessageType.VERSION);
+        output.writeShort(PROTOCOL_VERSION);
+        output.writeUTF(protocolContext.getLocalEndpointName());
+        output.commit();
+    }
+
     public boolean waitForUp() throws IOException {
-        while (! currentState.in(State.UP, State.CLOSED)) {
-            currentState.waitForAny();
+        while (! state.in(State.UP, State.CLOSED)) {
+            state.waitForAny();
         }
-        return currentState.in(State.UP);
+        return state.in(State.UP);
     }
 
     private void close() {
-        currentState.transition(State.CLOSED);
+        state.transition(State.CLOSED);
         ioSession.close().awaitUninterruptibly();
         protocolContext.closeSession();
     }
@@ -281,7 +365,7 @@
         }
 
         public void closeSession() throws IOException {
-            if (currentState.transition(State.CLOSED)) {
+            if (state.transition(State.CLOSED)) {
                 // todo - maybe we don't need to wait?
                 ioSession.close().awaitUninterruptibly();
             }
@@ -292,7 +376,7 @@
         }
 
         public void closeService(ServiceIdentifier serviceIdentifier) throws IOException {
-            if (! currentState.in(State.UP)) {
+            if (! state.in(State.UP)) {
                 return;
             }
             final IoBuffer buffer = newBuffer(60, false);
@@ -303,7 +387,7 @@
         }
 
         public void closeContext(ContextIdentifier contextIdentifier) throws IOException {
-            if (! currentState.in(State.UP)) {
+            if (! state.in(State.UP)) {
                 return;
             }
             final IoBuffer buffer = newBuffer(60, false);
@@ -314,7 +398,7 @@
         }
 
         public void closeStream(StreamIdentifier streamIdentifier) throws IOException {
-            if (! currentState.in(State.UP)) {
+            if (! state.in(State.UP)) {
                 return;
             }
             if (true /* todo if close not already sent */) {
@@ -342,7 +426,7 @@
             if (locator == null) {
                 throw new NullPointerException("locator is null");
             }
-            if (! currentState.in(State.UP)) {
+            if (! state.in(State.UP)) {
                 throw new IllegalStateException("JrppConnection is not in the UP state!");
             }
             final IoBuffer buffer = newBuffer(500, true);
@@ -486,13 +570,8 @@
         }
 
         public void sessionOpened() throws IOException {
-            // send version info
-            final IoBuffer buffer = newBuffer(60, false);
-            final MessageOutput output = protocolContext.getMessageOutput(new IoBufferByteOutput(buffer, ioSession));
-            write(output, MessageType.VERSION);
-            output.writeShort(PROTOCOL_VERSION);
-            output.writeUTF(protocolContext.getLocalEndpointName());
-            output.commit();
+            // TODO - there may be a mina bug where this method is not guaranteed to be called before any messages can be received! DIRMINA-535
+            sendVersionMessage();
         }
 
         public void sessionClosed() {
@@ -528,9 +607,9 @@
             final MessageInput input = protocolContext.getMessageInput(new IoBufferByteInput((IoBuffer) message));
             final MessageType type = MessageType.values()[input.readByte() & 0xff];
             if (trace) {
-                log.trace("Received message of type %s in state %s", type, currentState.getState());
+                log.trace("Received message of type %s in state %s", type, state.getState());
             }
-            OUT: switch (currentState.getState()) {
+            OUT: switch (state.getState()) {
                 case AWAITING_CLIENT_VERSION: {
                     switch (type) {
                         case VERSION: {
@@ -540,16 +619,36 @@
                             }
                             final String name = input.readUTF();
                             remoteName = name.length() > 0 ? name : null;
-                            SaslServerFilter saslServerFilter = getSaslServerFilter();
+                            state.requireTransition(State.AWAITING_CLIENT_AUTH_REQUEST);
+                            return;
+                        }
+                        default: break OUT;
+                    }
+                }
+                case AWAITING_CLIENT_AUTH_REQUEST: {
+                    switch (type) {
+                        case AUTH_REQUEST: {
+                            final int mechCount = input.readInt();
+                            final String[] clientMechs = new String[mechCount];
+                            for (int i = 0; i < mechCount; i ++) {
+                                clientMechs[i] = input.readUTF();
+                            }
+                            final CallbackHandler callbackHandler = getServerCallbackHandler(attributeMap);
+                            final Map<String, ?> saslProps = getSaslProperties(attributeMap);
+                            final Set<String> serverMechs = getServerMechanisms(attributeMap, saslProps);
+                            final String negotiatedMechanism = getNegotiatedMechanism(clientMechs, serverMechs);
+                            final SaslServer saslServer = Sasl.createSaslServer(negotiatedMechanism, "jrpp", protocolContext.getLocalEndpointName(), saslProps, callbackHandler);
+                            final SaslServerFilter saslServerFilter = getSaslServerFilter();
+                            saslServerFilter.setSaslServer(ioSession, saslServer);
                             if (saslServerFilter.sendInitialChallenge(ioSession)) {
                                 // complete (that was quick!)
                                 final IoBuffer buffer = newBuffer(60, false);
                                 final MessageOutput output = protocolContext.getMessageOutput(new IoBufferByteOutput(buffer, ioSession));
                                 write(output, MessageType.AUTH_SUCCESS);
                                 output.commit();
-                                currentState.requireTransition(State.AWAITING_CLIENT_VERSION, State.UP);
+                                state.requireTransition(State.AWAITING_CLIENT_VERSION, State.UP);
                             } else {
-                                currentState.requireTransition(State.AWAITING_CLIENT_VERSION, State.AWAITING_CLIENT_RESPONSE);
+                                state.requireTransition(State.AWAITING_CLIENT_VERSION, State.AWAITING_CLIENT_RESPONSE);
                             }
                             return;
                         }
@@ -565,7 +664,14 @@
                             }
                             final String name = input.readUTF();
                             remoteName = name.length() > 0 ? name : null;
-                            currentState.requireTransition(State.AWAITING_SERVER_VERSION, State.AWAITING_SERVER_CHALLENGE);
+                            final CallbackHandler callbackHandler = getClientCallbackHandler(attributeMap);
+                            final Map<String, ?> saslProps = getSaslProperties(attributeMap);
+                            final String[] clientMechs = getClientMechanisms(attributeMap, saslProps);
+                            final String authorizationId = getAuthorizationId(attributeMap, protocolContext);
+                            final SaslClient saslClient = Sasl.createSaslClient(clientMechs, authorizationId, "jrpp", remoteName, saslProps, callbackHandler);
+                            final SaslClientFilter saslClientFilter = getSaslClientFilter();
+                            saslClientFilter.setSaslClient(ioSession, saslClient);
+                            state.requireTransition(State.AWAITING_SERVER_VERSION, State.AWAITING_SERVER_CHALLENGE);
                             return;
                         }
                         default: break OUT;
@@ -587,7 +693,7 @@
                                     write(output, MessageType.AUTH_SUCCESS);
                                     output.commit();
                                     saslServerFilter.startEncryption(ioSession);
-                                    currentState.requireTransition(State.AWAITING_CLIENT_RESPONSE, State.UP);
+                                    state.requireTransition(State.AWAITING_CLIENT_RESPONSE, State.UP);
                                 }
                             } catch (SaslException ex) {
                                 final IoBuffer buffer = newBuffer(60, false);
@@ -595,6 +701,8 @@
                                 write(output, MessageType.AUTH_FAILED);
                                 output.commit();
                                 log.info("Client authentication failed (" + ex.getMessage() + ")");
+                                // todo - retry counter - JBREM-907
+                                state.requireTransition(State.AWAITING_CLIENT_RESPONSE, State.AWAITING_CLIENT_AUTH_REQUEST);
                             }
                             return;
                         }
@@ -613,12 +721,20 @@
                         case AUTH_SUCCESS: {
                             SaslClientFilter saslClientFilter = getSaslClientFilter();
                             saslClientFilter.startEncryption(ioSession);
-                            currentState.requireTransition(State.AWAITING_SERVER_CHALLENGE, State.UP);
+                            state.requireTransition(State.AWAITING_SERVER_CHALLENGE, State.UP);
                             return;
                         }
                         case AUTH_FAILED: {
                             log.info("JRPP client rejected authentication");
-                            close();
+                            final SaslClientFilter oldClientFilter = getSaslClientFilter();
+                            oldClientFilter.destroy();
+                            final CallbackHandler callbackHandler = getClientCallbackHandler(attributeMap);
+                            final Map<String, ?> saslProps = getSaslProperties(attributeMap);
+                            final String[] clientMechs = getClientMechanisms(attributeMap, saslProps);
+                            final String authorizationId = getAuthorizationId(attributeMap, protocolContext);
+                            final SaslClient saslClient = Sasl.createSaslClient(clientMechs, authorizationId, "jrpp", remoteName, saslProps, callbackHandler);
+                            final SaslClientFilter saslClientFilter = getSaslClientFilter();
+                            saslClientFilter.setSaslClient(ioSession, saslClient);
                             return;
                         }
                         default: break OUT;
@@ -723,17 +839,9 @@
                     }
                 }
             }
-            throw new IllegalStateException("Got message " + type + " during " + currentState);
+            throw new IllegalStateException("Got message " + type + " during " + state);
         }
 
-        private SaslClientFilter getSaslClientFilter() {
-            return (SaslClientFilter) ioSession.getFilterChain().get(SASL_CLIENT_FILTER_NAME);
-        }
-
-        private SaslServerFilter getSaslServerFilter() {
-            return (SaslServerFilter) ioSession.getFilterChain().get(SASL_SERVER_FILTER_NAME);
-        }
-
         public void messageSent(Object object) {
         }
     }
@@ -743,6 +851,7 @@
      */
     private enum MessageType {
         VERSION,
+        AUTH_REQUEST,
         SASL_CHALLENGE,
         SASL_RESPONSE,
         AUTH_SUCCESS,

Modified: remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppProtocolSupport.java
===================================================================
--- remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppProtocolSupport.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppProtocolSupport.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -3,24 +3,24 @@
 import java.io.IOException;
 import java.net.SocketAddress;
 import java.net.URI;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import org.apache.mina.common.IoAcceptor;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Executor;
 import org.apache.mina.common.IoConnector;
-import org.apache.mina.common.IoHandler;
 import org.apache.mina.common.IoSession;
+import org.apache.mina.common.ConnectFuture;
+import org.apache.mina.common.IoSessionInitializer;
+import org.apache.mina.common.IoProcessor;
 import org.apache.mina.filter.logging.LoggingFilter;
+import org.apache.mina.filter.sasl.SaslClientFilter;
+import org.apache.mina.filter.sasl.SaslMessageSender;
 import org.apache.mina.handler.multiton.SingleSessionIoHandler;
 import org.apache.mina.handler.multiton.SingleSessionIoHandlerDelegate;
 import org.apache.mina.handler.multiton.SingleSessionIoHandlerFactory;
 import org.apache.mina.transport.socket.nio.NioProcessor;
-import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
 import org.apache.mina.transport.socket.nio.NioSocketConnector;
 import org.jboss.cx.remoting.Endpoint;
-import org.jboss.cx.remoting.EndpointShutdownListener;
 import org.jboss.cx.remoting.RemotingException;
-import org.jboss.cx.remoting.core.util.CollectionUtil;
+import org.jboss.cx.remoting.core.util.AttributeMap;
 import org.jboss.cx.remoting.jrpp.mina.FramingIoFilter;
 import org.jboss.cx.remoting.spi.protocol.ProtocolContext;
 import org.jboss.cx.remoting.spi.protocol.ProtocolHandler;
@@ -29,63 +29,91 @@
 import org.jboss.cx.remoting.spi.protocol.ProtocolRegistrationSpec;
 import org.jboss.cx.remoting.spi.protocol.ProtocolServerContext;
 
-import javax.security.auth.callback.CallbackHandler;
-
 /**
  *
  */
 public final class JrppProtocolSupport {
-    @SuppressWarnings ({"UnusedDeclaration"})
-    private final Endpoint endpoint;
-    private final ProtocolServerContext serverContext;
-    private final IoHandler serverIoHandler = new SingleSessionIoHandlerDelegate(new ServerSessionHandlerFactory());
-    private final Set<IoAcceptor> ioAcceptors = CollectionUtil.synchronizedSet(CollectionUtil.<IoAcceptor>hashSet());
-    // todo - make the thread pools configurable
-    private final ExecutorService threadPool = Executors.newCachedThreadPool();
-    private final NioProcessor nioProcessor = new NioProcessor(threadPool);
-    private final ProtocolHandlerFactoryImpl protocolHandlerFactory = new ProtocolHandlerFactoryImpl();
+    private ProtocolHandlerFactoryImpl protocolHandlerFactory;
 
-    public JrppProtocolSupport(final Endpoint endpoint) throws RemotingException {
+    /** Thread pool to use.  Set before {@code create}. */
+    private Executor executor;
+    /** Endpoint.  Set before {@code create}. */
+    private Endpoint endpoint;
+
+    /** The NIO processor.  Set upon {@code create}. */
+    private IoProcessor ioProcessor;
+    /** Protocol server context.  Set upon {@code create}. */
+    private ProtocolServerContext serverContext;
+    /** Protocol registration.  Set upon {@code create}. */
+    private ProtocolRegistration registration;
+
+    public JrppProtocolSupport() {
+    }
+
+    // Accessors
+
+    public Executor getExecutor() {
+        return executor;
+    }
+
+    public void setExecutor(final Executor executor) {
+        this.executor = executor;
+    }
+
+    public Endpoint getEndpoint() {
+        return endpoint;
+    }
+
+    public void setEndpoint(final Endpoint endpoint) {
+        this.endpoint = endpoint;
+    }
+
+    // Package getters
+
+    IoProcessor getIoProcessor() {
+        return ioProcessor;
+    }
+
+    ProtocolServerContext getServerContext() {
+        return serverContext;
+    }
+
+    // Lifecycle
+
+    public void create() throws RemotingException {
+        ioProcessor = new NioProcessor(executor);
+        protocolHandlerFactory = new ProtocolHandlerFactoryImpl();
         final ProtocolRegistrationSpec spec = ProtocolRegistrationSpec.DEFAULT.setScheme("jrpp").setProtocolHandlerFactory(protocolHandlerFactory);
         final ProtocolRegistration registration = endpoint.registerProtocol(spec);
         serverContext = registration.getProtocolServerContext();
-        this.endpoint = endpoint;
-        endpoint.addShutdownListener(new EndpointShutdownListener() {
-            public void handleShutdown(Endpoint endpoint) {
-                shutdown();
-            }
-        });
+        this.registration = registration;
     }
 
-    public void addServer(final SocketAddress address) throws IOException {
-        // todo - make the acceptor managable so it can be started and stopped
-        final IoAcceptor ioAcceptor = new NioSocketAcceptor(threadPool, nioProcessor);
-        ioAcceptor.setDefaultLocalAddress(address);
-        ioAcceptor.setHandler(serverIoHandler);
-        ioAcceptor.getFilterChain().addLast("framing filter", new FramingIoFilter());
-        ioAcceptor.getFilterChain().addLast("debug 0", new LoggingFilter());
-        ioAcceptor.bind();
-        ioAcceptors.add(ioAcceptor);
+    public void start() {
+        registration.start();
     }
 
-    public void shutdown() {
-        for (IoAcceptor acceptor : ioAcceptors) {
-            acceptor.unbind();
+    public void stop() {
+        registration.stop();
+    }
+
+    public void destroy() {
+        if (ioProcessor != null) {
+            ioProcessor.dispose();
         }
-        for (IoAcceptor acceptor : ioAcceptors) {
-            acceptor.dispose();
+        if (registration != null) {
+            registration.unregister();
+            registration = null;
         }
-        ioAcceptors.clear();
-        protocolHandlerFactory.connector.dispose();
-        threadPool.shutdown();
+        protocolHandlerFactory = null;
+        serverContext = null;
     }
 
-    private final class ServerSessionHandlerFactory implements SingleSessionIoHandlerFactory {
-        public SingleSessionIoHandler getHandler(IoSession ioSession) throws IOException {
-            final JrppConnection connection;
-            connection = new JrppConnection(ioSession, serverContext, endpoint.getRemoteCallbackHandler());
-            return connection.getIoHandler();
-        }
+    // Utilities
+
+    private SocketAddress getSocketAddressFromUri(final URI uri) {
+        // todo - validate host and/or port!
+        return new InetSocketAddress(uri.getHost(), uri.getPort());
     }
 
     /**
@@ -94,9 +122,15 @@
     private final class ProtocolHandlerFactoryImpl implements ProtocolHandlerFactory, SingleSessionIoHandlerFactory {
         private final IoConnector connector;
 
+        @SuppressWarnings ({"unchecked"})
         public ProtocolHandlerFactoryImpl() {
-            connector = new NioSocketConnector(threadPool, nioProcessor);
+            connector = new NioSocketConnector(executor, ioProcessor);
             connector.getFilterChain().addLast("framing filter", new FramingIoFilter());
+            connector.getFilterChain().addLast(JrppConnection.SASL_CLIENT_FILTER_NAME, new SaslClientFilter(new SaslMessageSender() {
+                public void sendSaslMessage(IoSession ioSession, byte[] rawMsgData) throws IOException {
+                    JrppConnection.getConnection(ioSession).sendResponse(rawMsgData);
+                }
+            }));
             connector.getFilterChain().addLast("debug 0", new LoggingFilter());
             connector.setHandler(new SingleSessionIoHandlerDelegate(this));
         }
@@ -105,19 +139,21 @@
             return false;
         }
 
-        public ProtocolHandler createHandler(ProtocolContext context, URI remoteUri, CallbackHandler clientCallbackHandler) throws IOException {
+        public ProtocolHandler createHandler(final ProtocolContext context, final URI remoteUri, final AttributeMap attributeMap) throws IOException {
             // todo - add a connect timeout
             // todo - local connect addr
-            final JrppConnection jrppConnection = new JrppConnection(connector, remoteUri, context, clientCallbackHandler);
-            if (jrppConnection.waitForUp()) {
-                return jrppConnection.getProtocolHandler();
-            } else {
-                throw new IOException("Failed to initiate a JRPP connection");
-            }
+            final JrppConnection jrppConnection = new JrppConnection(attributeMap);
+            final SocketAddress serverAddress = getSocketAddressFromUri(remoteUri);
+            final ConnectFuture future = connector.connect(serverAddress, new IoSessionInitializer<ConnectFuture>() {
+                public void initializeSession(final IoSession ioSession, final ConnectFuture connectFuture) {
+                    jrppConnection.initializeClient(ioSession, context);
+                }
+            });
+            future.awaitUninterruptibly();
+            return jrppConnection.getProtocolHandler();
         }
 
         public void close() {
-            shutdown();
         }
 
         public SingleSessionIoHandler getHandler(IoSession session) throws Exception {

Added: remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppServer.java
===================================================================
--- remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppServer.java	                        (rev 0)
+++ remoting3/trunk/jrpp/src/main/java/org/jboss/cx/remoting/jrpp/JrppServer.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -0,0 +1,118 @@
+package org.jboss.cx.remoting.jrpp;
+
+import java.net.SocketAddress;
+import java.util.concurrent.Executor;
+import java.io.IOException;
+import org.apache.mina.transport.socket.nio.NioSocketAcceptor;
+import org.apache.mina.common.IoAcceptor;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoProcessor;
+import org.apache.mina.filter.logging.LoggingFilter;
+import org.apache.mina.filter.sasl.SaslServerFilter;
+import org.apache.mina.filter.sasl.SaslMessageSender;
+import org.apache.mina.handler.multiton.SingleSessionIoHandlerFactory;
+import org.apache.mina.handler.multiton.SingleSessionIoHandler;
+import org.apache.mina.handler.multiton.SingleSessionIoHandlerDelegate;
+import org.jboss.cx.remoting.jrpp.mina.FramingIoFilter;
+import org.jboss.cx.remoting.spi.protocol.ProtocolServerContext;
+import org.jboss.cx.remoting.core.util.AttributeMap;
+
+/**
+ *
+ */
+public final class JrppServer {
+    private final IoHandler ioHandler = new SingleSessionIoHandlerDelegate(new ServerSessionHandlerFactory());
+
+    // injected properties
+
+    /** The server socket address.  Set before {@code create}. */
+    private SocketAddress socketAddress;
+    /** Protocol support object.  Set before {@code create}. */
+    private JrppProtocolSupport protocolSupport;
+
+    // calculated properties
+
+    /** Executor.  Set upon {@code create}. */
+    private Executor executor;
+    /** NIO Processor.  Set upon {@code create}. */
+    private IoProcessor ioProcessor;
+    /** IO Acceptor.  Set upon {@code create}. */
+    private IoAcceptor ioAcceptor;
+    /** Protocol server context.  Set upon {@code create}. */
+    private ProtocolServerContext serverContext;
+    /** Attribute map.  Set before {@code create}. */
+    private AttributeMap attributeMap;
+
+    // Accessors
+
+    public SocketAddress getSocketAddress() {
+        return socketAddress;
+    }
+
+    public void setSocketAddress(final SocketAddress socketAddress) {
+        this.socketAddress = socketAddress;
+    }
+
+    public JrppProtocolSupport getProtocolSupport() {
+        return protocolSupport;
+    }
+
+    public void setProtocolSupport(final JrppProtocolSupport protocolSupport) {
+        this.protocolSupport = protocolSupport;
+    }
+
+    public AttributeMap getAttributeMap() {
+        return attributeMap;
+    }
+
+    public void setAttributeMap(final AttributeMap attributeMap) {
+        this.attributeMap = attributeMap;
+    }
+
+    // Lifecycle
+
+    @SuppressWarnings ({"unchecked"})
+    public void create() {
+        serverContext = protocolSupport.getServerContext();
+        executor = protocolSupport.getExecutor();
+        ioProcessor = protocolSupport.getIoProcessor();
+        ioAcceptor = new NioSocketAcceptor(executor, ioProcessor);
+        ioAcceptor.setDefaultLocalAddress(socketAddress);
+        ioAcceptor.setHandler(ioHandler);
+        ioAcceptor.getFilterChain().addLast("framing filter", new FramingIoFilter());
+        ioAcceptor.getFilterChain().addLast(JrppConnection.SASL_SERVER_FILTER_NAME, new SaslServerFilter(new SaslMessageSender() {
+            public void sendSaslMessage(IoSession ioSession, byte[] rawMsgData) throws IOException {
+                JrppConnection.getConnection(ioSession).sendChallenge(rawMsgData);
+            }
+        }));
+        ioAcceptor.getFilterChain().addLast("debug 0", new LoggingFilter());
+    }
+
+    public void start() throws IOException {
+        ioAcceptor.bind();
+    }
+
+    public void stop() {
+        ioAcceptor.unbind();
+    }
+
+    public void destroy() {
+        ioAcceptor.dispose();
+        ioAcceptor = null;
+        ioProcessor = null;
+        executor = null;
+        serverContext = null;
+    }
+
+    // MINA support
+
+    private final class ServerSessionHandlerFactory implements SingleSessionIoHandlerFactory {
+        public SingleSessionIoHandler getHandler(IoSession ioSession) throws IOException {
+            final JrppConnection connection = new JrppConnection(attributeMap);
+            connection.initializeServer(ioSession, serverContext);
+            return connection.getIoHandler();
+        }
+    }
+
+}

Deleted: remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslClientFactory.java
===================================================================
--- remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslClientFactory.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslClientFactory.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -1,14 +0,0 @@
-package org.apache.mina.filter.sasl;
-
-import org.apache.mina.common.IoSession;
-
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.sasl.SaslClient;
-import javax.security.sasl.SaslException;
-
-/**
- *
- */
-public interface SaslClientFactory {
-    SaslClient createSaslClient(IoSession ioSession, CallbackHandler callbackHandler) throws SaslException;
-}

Modified: remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslClientFilter.java
===================================================================
--- remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslClientFilter.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslClientFilter.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -2,7 +2,6 @@
 
 import java.io.IOException;
 import org.apache.mina.common.AttributeKey;
-import org.apache.mina.common.IoFilterChain;
 import org.apache.mina.common.IoSession;
 
 import javax.security.sasl.Sasl;
@@ -28,19 +27,13 @@
 public final class SaslClientFilter extends AbstractSaslFilter {
     private static final AttributeKey SASL_CLIENT_KEY = new AttributeKey(SaslClientFilter.class, "saslClient");
 
-    private final SaslClientFactory saslClientFactory;
-    private final CallbackHandlerFactory callbackHandlerFactory;
-
     /**
      * Construct a new SASL client filter.
      *
-     * @param saslClientFactory a factory which may be used to create a new SASL client instance for an {@code IoSession}.
      * @param messageSender the message sender, used to send response messages
      */
-    public SaslClientFilter(final SaslClientFactory saslClientFactory, final SaslMessageSender messageSender, final CallbackHandlerFactory callbackHandlerFactory) {
+    public SaslClientFilter(final SaslMessageSender messageSender) {
         super(messageSender);
-        this.saslClientFactory = saslClientFactory;
-        this.callbackHandlerFactory = callbackHandlerFactory;
     }
 
     /**
@@ -49,11 +42,21 @@
      * @param ioSession the session
      * @return the SASL client instance
      */
-    protected SaslClient getSaslClient(IoSession ioSession) {
+    public SaslClient getSaslClient(IoSession ioSession) {
         return (SaslClient) ioSession.getAttribute(SASL_CLIENT_KEY);
     }
 
     /**
+     * Set the {@code SaslClient} instance for the given session.
+     *
+     * @param ioSession the session
+     * @param saslClient the SASL client instance
+     */
+    public void setSaslClient(IoSession ioSession, SaslClient saslClient) {
+        ioSession.setAttribute(SASL_CLIENT_KEY, saslClient);
+    }
+
+    /**
      * Handle a received (and decoded) SASL challenge message.  This method is called when the upper-level
      * protocol receives a complete SASL challenge message.  If a response is produced, it will be sent via the
      * provided {@link org.apache.mina.filter.sasl.SaslMessageSender}.
@@ -117,19 +120,6 @@
         return (String) getSaslClient(ioSession).getNegotiatedProperty(Sasl.QOP);
     }
 
-    public void onPreAdd(IoFilterChain ioFilterChain, String string, NextFilter nextFilter) throws Exception {
-        final IoSession ioSession = ioFilterChain.getSession();
-        ioSession.setAttribute(SASL_CLIENT_KEY, saslClientFactory.createSaslClient(ioSession, callbackHandlerFactory.getCallbackHandler()));
-    }
-
-    public void onPostRemove(IoFilterChain ioFilterChain, String string, NextFilter nextFilter) throws Exception {
-        final IoSession ioSession = ioFilterChain.getSession();
-        final SaslClient client = getSaslClient(ioSession);
-        if (client != null) {
-            client.dispose();
-        }
-    }
-
     protected byte[] wrap(IoSession ioSession, byte[] data, int offs, int len) throws SaslException {
         return getSaslClient(ioSession).wrap(data, offs, len);
     }

Deleted: remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslServerFactory.java
===================================================================
--- remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslServerFactory.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslServerFactory.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -1,14 +0,0 @@
-package org.apache.mina.filter.sasl;
-
-import org.apache.mina.common.IoSession;
-
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.sasl.SaslException;
-import javax.security.sasl.SaslServer;
-
-/**
- *
- */
-public interface SaslServerFactory {
-    SaslServer createSaslServer(IoSession ioSession, CallbackHandler callbackHandler) throws SaslException;
-}

Modified: remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslServerFilter.java
===================================================================
--- remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslServerFilter.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/mina-sasl/src/main/java/org/apache/mina/filter/sasl/SaslServerFilter.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -2,7 +2,6 @@
 
 import java.io.IOException;
 import org.apache.mina.common.AttributeKey;
-import org.apache.mina.common.IoFilterChain;
 import org.apache.mina.common.IoSession;
 
 import javax.security.sasl.Sasl;
@@ -28,19 +27,13 @@
 public final class SaslServerFilter extends AbstractSaslFilter {
     private static final AttributeKey SASL_SERVER_KEY = new AttributeKey(SaslServerFilter.class, "saslServer");
 
-    private final SaslServerFactory saslServerFactory;
-    private final CallbackHandlerFactory callbackHandlerFactory;
-
     /**
      * Construct a new SASL server filter.
      *
-     * @param saslServerFactory a factory which may be used to create a new SASL server instance for an {@code IoSession}.
      * @param messageSender the message sender, used to send challenge messages
      */
-    public SaslServerFilter(final SaslServerFactory saslServerFactory, final SaslMessageSender messageSender, final CallbackHandlerFactory callbackHandlerFactory) {
+    public SaslServerFilter(final SaslMessageSender messageSender) {
         super(messageSender);
-        this.saslServerFactory = saslServerFactory;
-        this.callbackHandlerFactory = callbackHandlerFactory;
     }
 
     /**
@@ -49,11 +42,21 @@
      * @param ioSession the session
      * @return the SASL server instance
      */
-    protected SaslServer getSaslServer(IoSession ioSession) {
+    public SaslServer getSaslServer(IoSession ioSession) {
         return (SaslServer) ioSession.getAttribute(SASL_SERVER_KEY);
     }
 
     /**
+     * Set the {@code SaslServer} instance for the given session.
+     *
+     * @param ioSession the session
+     * @param saslServer the SASL server instance
+     */
+    public void setSaslServer(IoSession ioSession, SaslServer saslServer) {
+        ioSession.setAttribute(SASL_SERVER_KEY, saslServer);
+    }
+
+    /**
      * Handle a received (and decoded) SASL response message.  This method is called when the upper-level
      * protocol receives a complete SASL response message.  If another challenge is produced, it will be sent via the
      * provided {@link org.apache.mina.filter.sasl.SaslMessageSender}.
@@ -114,23 +117,6 @@
         return (String) getSaslServer(ioSession).getNegotiatedProperty(Sasl.QOP);
     }
 
-    public void onPreAdd(IoFilterChain ioFilterChain, String string, NextFilter nextFilter) throws Exception {
-        final IoSession ioSession = ioFilterChain.getSession();
-        final SaslServer saslServer = saslServerFactory.createSaslServer(ioSession, callbackHandlerFactory.getCallbackHandler());
-        if (saslServer == null) {
-            throw new NullPointerException("saslServer is null");
-        }
-        ioSession.setAttribute(SASL_SERVER_KEY, saslServer);
-    }
-
-    public void onPostRemove(IoFilterChain ioFilterChain, String string, NextFilter nextFilter) throws Exception {
-        final IoSession ioSession = ioFilterChain.getSession();
-        final SaslServer server = getSaslServer(ioSession);
-        if (server != null) {
-            server.dispose();
-        }
-    }
-
     protected byte[] wrap(IoSession ioSession, byte[] data, int offs, int len) throws SaslException {
         return getSaslServer(ioSession).wrap(data, offs, len);
     }

Modified: remoting3/trunk/standalone/src/main/java/org/jboss/cx/remoting/Remoting.java
===================================================================
--- remoting3/trunk/standalone/src/main/java/org/jboss/cx/remoting/Remoting.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/standalone/src/main/java/org/jboss/cx/remoting/Remoting.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -1,12 +1,21 @@
 package org.jboss.cx.remoting;
 
 import java.net.URI;
+import java.io.IOException;
 import org.jboss.cx.remoting.log.Logger;
 import org.jboss.cx.remoting.core.CoreEndpointProvider;
+import org.jboss.cx.remoting.core.util.AttributeMap;
+import org.jboss.cx.remoting.core.util.AttributeHashMap;
 import org.jboss.cx.remoting.spi.EndpointProvider;
 import org.jboss.cx.remoting.spi.wrapper.ContextSourceWrapper;
 import org.jboss.cx.remoting.spi.wrapper.SessionWrapper;
 
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+
 /**
  *
  */
@@ -21,11 +30,26 @@
         return EndpointProviderHolder.provider.createEndpoint(name);
     }
 
-    public static Session createEndpointAndSession(String endpointName, URI remoteUri, String userName, char[] password) throws RemotingException {
+    public static Session createEndpointAndSession(String endpointName, URI remoteUri, final String userName, final char[] password) throws RemotingException {
         final Endpoint endpoint = createEndpoint(endpointName);
         boolean ok = false;
+        final CallbackHandler callbackHandler = new CallbackHandler() {
+            public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
+                for (Callback callback : callbacks) {
+                    if (callback instanceof NameCallback) {
+                        ((NameCallback)callback).setName(userName);
+                    } else if (callback instanceof PasswordCallback) {
+                        ((PasswordCallback)callback).setPassword(password);
+                    } else {
+                        throw new UnsupportedCallbackException(callback);
+                    }
+                }
+            }
+        };
+        final AttributeMap attributeMap = new AttributeHashMap();
+        attributeMap.put(CommonKeys.AUTH_CALLBACK_HANDLER, callbackHandler);
         try {
-            final Session session = new SessionWrapper(endpoint.openSession(EndpointLocator.DEFAULT.setEndpointUri(remoteUri).setClientAuthentication(userName, password), null)) {
+            final Session session = new SessionWrapper(endpoint.openSession(remoteUri, attributeMap)) {
                 public void close() throws RemotingException {
                     try {
                         super.close();

Modified: remoting3/trunk/util/src/main/java/org/jboss/cx/remoting/core/util/AttributeKey.java
===================================================================
--- remoting3/trunk/util/src/main/java/org/jboss/cx/remoting/core/util/AttributeKey.java	2008-02-19 08:12:17 UTC (rev 3458)
+++ remoting3/trunk/util/src/main/java/org/jboss/cx/remoting/core/util/AttributeKey.java	2008-02-21 00:35:30 UTC (rev 3459)
@@ -6,6 +6,10 @@
 public final class AttributeKey<T> {
     private final String name;
 
+    public static <T> AttributeKey<T> key(String name) {
+        return new AttributeKey<T>(name);
+    }
+
     public AttributeKey(final String name) {
         this.name = name;
     }




More information about the jboss-remoting-commits mailing list