[jboss-remoting-commits] JBoss Remoting SVN: r5099 - in remoting3/trunk/jboss-remoting/src: main/java/org/jboss/remoting3/spi and 3 other directories.

jboss-remoting-commits at lists.jboss.org jboss-remoting-commits at lists.jboss.org
Thu Apr 30 18:50:25 EDT 2009


Author: david.lloyd at jboss.com
Date: 2009-04-30 18:50:24 -0400 (Thu, 30 Apr 2009)
New Revision: 5099

Added:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnector.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnectorImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientListener.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Connection.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureResult.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/NotOpenException.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/UnknownURISchemeException.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractConnectionProviderContext.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandlerFactory.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderFactory.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandlerConnector.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/Result.java
Removed:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AbstractContextImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AbstractRequestListener.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientExternalizer.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSource.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSourceExternalizer.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSourceImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandlerSource.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ResourceType.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceContext.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceContextImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractEndpointConnectionAcceptor.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnection.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnectionAcceptor.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandlerSource.java
Modified:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContext.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContextImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Endpoint.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/IndeterminateOutcomeException.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalServiceConfiguration.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemoteExecutionException.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Remoting.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RequestListener.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceNotFoundException.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationListener.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/package-info.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractAutoCloseable.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProvider.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/InputStreamHandlerFactory.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/OutputStreamHandlerFactory.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/StreamHandler.java
   remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/EndpointTestCase.java
   remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/spi/CloseableTestCase.java
Log:
Finish migration to connection-oriented model

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AbstractContextImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AbstractContextImpl.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AbstractContextImpl.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,56 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.Executor;
-import org.jboss.remoting3.spi.AbstractHandleableCloseable;
-
-/**
- *
- */
-abstract class AbstractContextImpl<T> extends AbstractHandleableCloseable<T> {
-
-    private final ConcurrentMap<Object, Object> attributes = new ConcurrentHashMap<Object, Object>();
-
-    AbstractContextImpl(final Executor executor) {
-        super(executor);
-    }
-
-    public ConcurrentMap<Object, Object> getAttributes() {
-        return attributes;
-    }
-
-    protected Executor getExecutor() {
-        return super.getExecutor();
-    }
-
-    protected boolean isOpen() {
-        return super.isOpen();
-    }
-
-    public String toString() {
-        return "generic context instance <" + Integer.toHexString(hashCode()) + ">";
-    }
-}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AbstractRequestListener.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AbstractRequestListener.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AbstractRequestListener.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,56 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-/**
- * A simple request listener implementation that implements all methods with no-operation implementations.
- *
- * @param <I> the request type
- * @param <O> the reply type
- */
-public abstract class AbstractRequestListener<I, O> implements RequestListener<I, O> {
-
-    /**
-     * {@inheritDoc}  This implementation performs no operation.
-     */
-    public void handleClientOpen(final ClientContext context) {
-    }
-
-    /**
-     * {@inheritDoc}  This implementation performs no operation.
-     */
-    public void handleServiceOpen(final ServiceContext context) {
-    }
-
-    /**
-     * {@inheritDoc}  This implementation performs no operation.
-     */
-    public void handleServiceClose(final ServiceContext context) {
-    }
-
-    /**
-     * {@inheritDoc}  This implementation performs no operation.
-     */
-    public void handleClientClose(final ClientContext context) {
-    }
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -25,11 +25,14 @@
 import java.io.IOException;
 import java.io.ObjectStreamException;
 import java.util.concurrent.CancellationException;
-import java.util.concurrent.ConcurrentMap;
 import org.jboss.xnio.IoFuture;
 
 /**
  * A communications client.  The client may be associated with state maintained by the local and/or remote side.
+ * <p/>
+ * This interface is part of the Remoting public API.  It is intended to be consumed by Remoting applications; it is
+ * not intended to be implemented by them.  Methods may be added to this interface in future minor releases without
+ * advance notice.
  *
  * @param <I> the request type
  * @param <O> the reply type
@@ -107,11 +110,4 @@
      * @throws IOException if the request could not be sent
      */
     IoFuture<? extends O> send(I request) throws IOException;
-
-    /**
-     * Get the attribute map.  This map holds metadata about the current clinet.
-     *
-     * @return the attribute map
-     */
-    ConcurrentMap<Object, Object> getAttributes();
 }

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnector.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnector.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnector.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,51 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3;
+
+import org.jboss.xnio.IoFuture;
+
+/**
+ * A client connector.  Such a connector can usually be sent across a link to a specific peer.  Attempting to access
+ * the client from the wrong peer, or attempting to send the connector to a peer for whom it is not intended, will
+ * result in an exception.
+ */
+public interface ClientConnector<I, O> {
+
+    /**
+     * Get the future client associated with this connector.  This method may only be called after this connector
+     * has passed over its associated connection.
+     *
+     * @return the future client
+     * @throws SecurityException if this client is being accessed from the wrong peer
+     */
+    IoFuture<? extends Client<I, O>> getFutureClient() throws SecurityException;
+
+    /**
+     * Get the client context associated with this connector.  This method may only be called from the originating
+     * side of the connection.
+     *
+     * @return the client context
+     * @throws SecurityException if the client context is accessed on the remote side of the connection
+     */
+    ClientContext getClientContext() throws SecurityException;
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnectorImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnectorImpl.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnectorImpl.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3;
+
+import org.jboss.xnio.IoFuture;
+import org.jboss.remoting3.spi.RequestHandlerConnector;
+import org.jboss.remoting3.spi.RequestHandler;
+import org.jboss.remoting3.spi.Cancellable;
+import java.io.Serializable;
+import java.io.IOException;
+
+final class ClientConnectorImpl<I, O> implements ClientConnector<I, O>, Serializable {
+
+    private static final long serialVersionUID = -263585821458635701L;
+
+    private transient final ClientContext clientContext;
+
+    private final RequestHandlerConnector requestHandlerConnector;
+    private final Endpoint endpoint;
+    private final Class<I> requestClass;
+    private final Class<O> replyClass;
+
+    ClientConnectorImpl(final RequestHandlerConnector requestHandlerConnector, final Endpoint endpoint, final Class<I> requestClass, final Class<O> replyClass, final ClientContext clientContext) {
+        this.requestHandlerConnector = requestHandlerConnector;
+        this.endpoint = endpoint;
+        this.requestClass = requestClass;
+        this.replyClass = replyClass;
+        this.clientContext = clientContext;
+    }
+
+    public IoFuture<? extends Client<I, O>> getFutureClient() throws SecurityException {
+        if (clientContext != null) {
+            throw new SecurityException("Connector has not been sent");
+        }
+        return new FutureResult<Client<I, O>, RequestHandler>() {
+            private final Cancellable cancellable = requestHandlerConnector.createRequestHandler(getResult());
+
+            protected Client<I, O> translate(final RequestHandler result) throws IOException {
+                return endpoint.createClient(result, requestClass, replyClass);
+            }
+
+            public IoFuture<Client<I, O>> cancel() {
+                cancellable.cancel();
+                return super.cancel();
+            }
+        };
+    }
+
+    public ClientContext getClientContext() {
+        if (clientContext == null) {
+            throw new SecurityException("Connector has already been sent");
+        }
+        return clientContext;
+    }
+
+
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContext.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContext.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContext.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,7 +22,7 @@
 
 package org.jboss.remoting3;
 
-import java.util.concurrent.ConcurrentMap;
+import java.io.IOException;
 
 /**
  * The server context for a single remote client instance.
@@ -30,18 +30,18 @@
  * @apiviz.exclude
  */
 public interface ClientContext extends HandleableCloseable<ClientContext> {
+
     /**
-     * Get the attributes for this end of the channel as a map.
+     * Get the connection associated with this client context.
      *
-     * @return the attribute map
+     * @return the connection
      */
-    ConcurrentMap<Object, Object> getAttributes();
+    Connection getConnection();
 
     /**
-     * Get the service that this context is associated with, or {@code null} if there is no
-     * service.
+     * Close the client from the server side.
      *
-     * @return the service, or {@code null} if there is none
+     * @throws IOException if an I/O error occurs
      */
-    ServiceContext getServiceContext();
+    void close() throws IOException;
 }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContextImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContextImpl.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContextImpl.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -23,29 +23,30 @@
 package org.jboss.remoting3;
 
 import java.util.concurrent.Executor;
+import org.jboss.remoting3.spi.AbstractHandleableCloseable;
 import org.jboss.xnio.log.Logger;
 
 /**
  *
  */
-final class ClientContextImpl extends AbstractContextImpl<ClientContext> implements ClientContext {
+final class ClientContextImpl extends AbstractHandleableCloseable<ClientContext> implements ClientContext {
 
+    @SuppressWarnings({ "UnusedDeclaration" })
     private static final Logger log = Logger.getLogger("org.jboss.remoting.client-context");
 
-    private final ServiceContextImpl serviceContext;
+    private final Connection connection;
 
-    ClientContextImpl(final Executor executor) {
+    ClientContextImpl(final Executor executor, final Connection connection) {
         super(executor);
-        serviceContext = null;
+        this.connection = connection;
     }
 
-    ClientContextImpl(final ServiceContextImpl serviceContext) {
-        super(serviceContext.getExecutor());
-        this.serviceContext = serviceContext;
+    protected Executor getExecutor() {
+        return super.getExecutor();
     }
 
-    public ServiceContext getServiceContext() {
-        return serviceContext;
+    public Connection getConnection() {
+        return connection;
     }
 
     public String toString() {

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientExternalizer.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientExternalizer.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientExternalizer.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,69 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-import org.jboss.remoting3.spi.RequestHandler;
-
-/**
- *
- */
-final class ClientExternalizer implements Externalizer {
-
-    private static final long serialVersionUID = 814228455390899997L;
-
-    private final EndpointImpl endpoint;
-
-    ClientExternalizer(final EndpointImpl endpoint) {
-        this.endpoint = endpoint;
-    }
-
-    private static <I, O> void doWriteExternal(final ClientImpl<I, O> client, final ObjectOutput output) throws IOException {
-        output.writeObject(client.getRequestClass());
-        output.writeObject(client.getReplyClass());
-        output.writeObject(client.getRequestHandlerHandle().getResource());
-    }
-
-    public void writeExternal(final Object o, final ObjectOutput output) throws IOException {
-        doWriteExternal((ClientImpl<?, ?>) o, output);
-    }
-
-    private <I, O> ClientImpl<I, O> doCreateExternal(Class<I> requestClass, Class<O> replyClass, RequestHandler handler) throws IOException {
-        return ClientImpl.create(handler.getHandle(), endpoint.getExecutor(), requestClass, replyClass);
-    }
-
-    public Object createExternal(final Class<?> aClass, final ObjectInput input, final Creator creator) throws IOException, ClassNotFoundException {
-        final Class<?> requestClass = (Class<?>) input.readObject();
-        final Class<?> replyClass = (Class<?>) input.readObject();
-        final RequestHandler handler = (RequestHandler) input.readObject();
-        return doCreateExternal(requestClass, replyClass, handler);
-    }
-
-    public void readExternal(final Object o, final ObjectInput input) throws IOException, ClassNotFoundException {
-        // no op
-    }
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -24,10 +24,10 @@
 
 import java.io.IOException;
 import java.util.concurrent.Executor;
-import org.jboss.remoting3.spi.Handle;
 import org.jboss.remoting3.spi.RemoteRequestContext;
 import org.jboss.remoting3.spi.ReplyHandler;
 import org.jboss.remoting3.spi.RequestHandler;
+import org.jboss.remoting3.spi.AbstractHandleableCloseable;
 import org.jboss.xnio.IoFuture;
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.log.Logger;
@@ -35,25 +35,25 @@
 /**
  *
  */
-final class ClientImpl<I, O> extends AbstractContextImpl<Client<I, O>> implements Client<I, O> {
+final class ClientImpl<I, O> extends AbstractHandleableCloseable<Client<I, O>> implements Client<I, O> {
 
     private static final Logger log = Logger.getLogger("org.jboss.remoting.client");
 
-    private final Handle<RequestHandler> handle;
+    private final RequestHandler handler;
     private final Class<I> requestClass;
     private final Class<O> replyClass;
 
-    private ClientImpl(final Handle<RequestHandler> handle, final Executor executor, final Class<I> requestClass, final Class<O> replyClass) {
+    private ClientImpl(final RequestHandler handler, final Executor executor, final Class<I> requestClass, final Class<O> replyClass) {
         super(executor);
-        this.handle = handle;
+        this.handler = handler;
         this.requestClass = requestClass;
         this.replyClass = replyClass;
     }
 
-    static <I, O> ClientImpl<I, O> create(final Handle<RequestHandler> handle, final Executor executor, final Class<I> requestClass, final Class<O> replyClass) {
-        final ClientImpl<I, O> ci = new ClientImpl<I, O>(handle, executor, requestClass, replyClass);
-        handle.addCloseHandler(new CloseHandler<Handle<RequestHandler>>() {
-            public void handleClose(final Handle<RequestHandler> closed) {
+    static <I, O> ClientImpl<I, O> create(final RequestHandler handler, final Executor executor, final Class<I> requestClass, final Class<O> replyClass) {
+        final ClientImpl<I, O> ci = new ClientImpl<I, O>(handler, executor, requestClass, replyClass);
+        handler.addCloseHandler(new CloseHandler<RequestHandler>() {
+            public void handleClose(final RequestHandler closed) {
                 IoUtils.safeClose(ci);
             }
         });
@@ -61,7 +61,7 @@
     }
 
     protected void closeAction() throws IOException {
-        handle.close();
+        handler.close();
     }
 
     public O invoke(final I request) throws IOException {
@@ -73,9 +73,9 @@
         final QueueExecutor executor = new QueueExecutor();
         final FutureReplyImpl<O> futureReply = new FutureReplyImpl<O>(executor, replyClass);
         final ReplyHandler replyHandler = futureReply.getReplyHandler();
-        final RemoteRequestContext requestContext = handle.getResource().receiveRequest(actualRequest, replyHandler);
+        final RemoteRequestContext requestContext = handler.receiveRequest(actualRequest, replyHandler);
         futureReply.setRemoteRequestContext(requestContext);
-        futureReply.addNotifier(IoUtils.<O>attachmentClosingNotifier(), executor);
+        futureReply.addNotifier(IoUtils.attachmentClosingNotifier(), executor);
         executor.runQueue();
         try {
             final O reply = futureReply.getInterruptibly();
@@ -97,9 +97,9 @@
         }
         log.trace("Client.send() sending request \"%s\"", request);
         final I actualRequest = castRequest(request);
-        final FutureReplyImpl<O> futureReply = new FutureReplyImpl<O>(executor, replyClass);
+        final FutureReplyImpl<O> futureReply = new FutureReplyImpl<O>(getExecutor(), replyClass);
         final ReplyHandler replyHandler = futureReply.getReplyHandler();
-        final RemoteRequestContext requestContext = handle.getResource().receiveRequest(actualRequest, replyHandler);
+        final RemoteRequestContext requestContext = handler.receiveRequest(actualRequest, replyHandler);
         futureReply.setRemoteRequestContext(requestContext);
         return futureReply;
     }
@@ -122,8 +122,8 @@
         return "client instance <" + Integer.toHexString(hashCode()) + ">";
     }
 
-    Handle<RequestHandler> getRequestHandlerHandle() {
-        return handle;
+    RequestHandler getRequestHandler() {
+        return handler;
     }
 
     Class<I> getRequestClass() {

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientListener.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientListener.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientListener.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,46 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3;
+
+/**
+ * A client listener associated with a service.  When a client is opened for this service, a new request listener
+ * is created and returned.
+ *
+ * @param <I> the request type
+ * @param <O> the reply type
+ *
+ * @apiviz.landmark
+ */
+public interface ClientListener<I, O> {
+
+    /**
+     * Handle a client open by returning a new request listener.  The supplied client context may be used to register
+     * a notifier for when the client is closed.
+     * <p/>
+     * If {@code null} is returned, the client is closed with an error.
+     *
+     * @param clientContext the client context
+     * @return the request listener
+     */
+    RequestListener<I, O> handleClientOpen(ClientContext clientContext);
+}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSource.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSource.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSource.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,38 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-/**
- * A source for new Remoting clients.
- *
- * @param <I> the request type
- * @param <O> the reply type
- */
-public interface ClientSource<I, O> extends HandleableCloseable<ClientSource<I, O>> {
-    /**
-     * Create a new client instance.
-     *
-     * @return the client
-     */
-    Client<I, O> createClient();
-}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSourceExternalizer.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSourceExternalizer.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSourceExternalizer.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,69 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-import org.jboss.marshalling.Creator;
-import org.jboss.marshalling.Externalizer;
-import org.jboss.remoting3.spi.RequestHandlerSource;
-
-/**
- *
- */
-final class ClientSourceExternalizer implements Externalizer {
-
-    private static final long serialVersionUID = 814228455390899997L;
-
-    private final EndpointImpl endpoint;
-
-    ClientSourceExternalizer(final EndpointImpl endpoint) {
-        this.endpoint = endpoint;
-    }
-
-    private static <I, O> void doWriteExternal(final ClientSourceImpl<I, O> clientSource, final ObjectOutput output) throws IOException {
-        output.writeObject(clientSource.getRequestClass());
-        output.writeObject(clientSource.getReplyClass());
-        output.writeObject(clientSource.getRequestHandlerSourceHandle().getResource());
-    }
-
-    public void writeExternal(final Object o, final ObjectOutput output) throws IOException {
-        doWriteExternal((ClientSourceImpl<?, ?>) o, output);
-    }
-
-    private <I, O> ClientSourceImpl<I, O> doCreateExternal(Class<I> requestClass, Class<O> replyClass, RequestHandlerSource handlerSource) throws IOException {
-        return ClientSourceImpl.create(handlerSource.getHandle(), endpoint, requestClass, replyClass);
-    }
-
-    public Object createExternal(final Class<?> aClass, final ObjectInput input, final Creator creator) throws IOException, ClassNotFoundException {
-        final Class<?> requestClass = (Class<?>) input.readObject();
-        final Class<?> replyClass = (Class<?>) input.readObject();
-        final RequestHandlerSource handlerSource = (RequestHandlerSource) input.readObject();
-        return doCreateExternal(requestClass, replyClass, handlerSource);
-    }
-
-    public void readExternal(final Object o, final ObjectInput input) throws IOException, ClassNotFoundException {
-        // no op
-    }
-}
\ No newline at end of file

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSourceImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSourceImpl.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientSourceImpl.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,94 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-import java.io.IOException;
-import org.jboss.remoting3.spi.AbstractHandleableCloseable;
-import org.jboss.remoting3.spi.Handle;
-import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.RequestHandlerSource;
-import org.jboss.xnio.IoUtils;
-import org.jboss.xnio.log.Logger;
-
-/**
- *
- */
-final class ClientSourceImpl<I, O> extends AbstractHandleableCloseable<ClientSource<I, O>> implements ClientSource<I, O> {
-
-    private static final Logger log = Logger.getLogger("org.jboss.remoting.client-source"); 
-
-    private final Handle<RequestHandlerSource> handle;
-    private final Endpoint endpoint;
-    private final Class<I> requestClass;
-    private final Class<O> replyClass;
-
-    private ClientSourceImpl(final Handle<RequestHandlerSource> handle, final EndpointImpl endpoint, final Class<I> requestClass, final Class<O> replyClass) {
-        super(endpoint.getExecutor());
-        this.handle = handle;
-        this.endpoint = endpoint;
-        this.requestClass = requestClass;
-        this.replyClass = replyClass;
-    }
-
-    static <I, O> ClientSourceImpl<I, O> create(final Handle<RequestHandlerSource> handle, final EndpointImpl endpoint, final Class<I> requestClass, final Class<O> replyClass) {
-        final ClientSourceImpl<I, O> csi = new ClientSourceImpl<I, O>(handle, endpoint, requestClass, replyClass);
-        handle.addCloseHandler(new CloseHandler<Handle<RequestHandlerSource>>() {
-            public void handleClose(final Handle<RequestHandlerSource> closed) {
-                IoUtils.safeClose(csi);
-            }
-        });
-        return csi;
-    }
-
-    protected void closeAction() throws IOException {
-        handle.close();
-    }
-
-    public Client<I, O> createClient() throws IOException {
-        if (! isOpen()) {
-            throw new IOException("Client source is not open");
-        }
-        final Handle<RequestHandler> clientHandle = handle.getResource().createRequestHandler();
-        try {
-            return endpoint.createClient(clientHandle.getResource(), requestClass, replyClass);
-        } finally {
-            IoUtils.safeClose(clientHandle);
-        }
-    }
-
-    public String toString() {
-        return "client source instance <" + Integer.toString(hashCode()) + ">";
-    }
-
-    Handle<RequestHandlerSource> getRequestHandlerSourceHandle() {
-        return handle;
-    }
-
-    Class<I> getRequestClass() {
-        return requestClass;
-    }
-
-    Class<O> getReplyClass() {
-        return replyClass;
-    }
-}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Connection.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Connection.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Connection.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,62 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3;
+
+import org.jboss.xnio.IoFuture;
+import java.io.IOException;
+
+/**
+ * A connection to a remote peer.
+ * <p/>
+ * This interface is part of the Remoting public API.  It is intended to be consumed by Remoting applications; it is
+ * not intended to be implemented by them.  Methods may be added to this interface in future minor releases without
+ * advance notice.
+ */
+public interface Connection extends HandleableCloseable<Connection> {
+
+    /**
+     * Open a client on the remote side of this connection.
+     *
+     * @param serviceType the service type
+     * @param groupName the group name
+     * @param requestClass the request class
+     * @param replyClass the reply class
+     * @param <I> the request type
+     * @param <O> the reply type
+     * @return the future client
+     */
+    <I, O> IoFuture<? extends Client<I, O>> openClient(String serviceType, String groupName, Class<I> requestClass, Class<O> replyClass);
+
+    /**
+     * Create a client connector which may <b>only</b> transmitted to the remote side of this connection, allowing
+     * it to use the included service.
+     *
+     * @param listener the local listener
+     * @param requestClass the request class
+     * @param replyClass the reply class
+     * @param <I> the request type
+     * @param <O> the reply type
+     * @return a connector which may be sent to the connection peer
+     */
+    <I, O> ClientConnector<I, O> createClientConnector(RequestListener<I, O> listener, Class<I> requestClass, Class<O> replyClass) throws IOException;
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Endpoint.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Endpoint.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Endpoint.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,32 +1,22 @@
 package org.jboss.remoting3;
 
-import java.io.Closeable;
 import java.io.IOException;
 import java.net.URI;
 import java.util.Set;
-import java.util.concurrent.ConcurrentMap;
-import org.jboss.remoting3.spi.Handle;
+import org.jboss.remoting3.spi.ConnectionProviderFactory;
 import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.RequestHandlerSource;
-import org.jboss.remoting3.spi.ConnectionProvider;
-import org.jboss.remoting3.spi.EndpointConnectionAcceptor;
 import org.jboss.xnio.IoFuture;
 
 /**
  * A potential participant in a JBoss Remoting communications relationship.
+ * <p/>
+ * This interface is part of the Remoting public API.  It is intended to be consumed by Remoting applications; it is
+ * not intended to be implemented by them.  Methods may be added to this interface in future minor releases without
+ * advance notice.
  *
  * @apiviz.landmark
  */
 public interface Endpoint extends HandleableCloseable<Endpoint> {
-    /**
-     * Get the endpoint attribute map.  This is a storage area for any data associated with this endpoint, including
-     * (but not limited to) connection and protocol information, and application information.
-     *
-     * You must have the TODO permission to invoke this method.
-     *
-     * @return the endpoint map
-     */
-    ConcurrentMap<Object, Object> getAttributes();
 
     /**
      * Get the name of this endpoint.
@@ -38,32 +28,26 @@
     /**
      * Create a request handler that can be used to receive incoming requests on this endpoint.  The client may be passed to a
      * remote endpoint as part of a request or a reply, or it may be used locally.
-     *
+     * <p/>
      * You must have the {@link org.jboss.remoting3.EndpointPermission createRequestHandler EndpointPermission} to invoke this method.
      *
-     * @param <I> the request type
-     * @param <O> the reply type
      * @param requestListener the request listener
      * @param requestClass the class of requests sent to this request listener
      * @param replyClass the class of replies received back from this request listener
      * @return a handle for the client
      * @throws IOException if an error occurs
      */
-    <I, O> Handle<RequestHandler> createLocalRequestHandler(RequestListener<I, O> requestListener, final Class<I> requestClass, final Class<O> replyClass) throws IOException;
+    <I, O> RequestHandler createLocalRequestHandler(RequestListener<I, O> requestListener, final Class<I> requestClass, final Class<O> replyClass) throws IOException;
 
     /**
      * Create a request handler source that can be used to acquire clients associated with a request listener on this endpoint.
-     * The request handler source may be ignored, passed to a remote endpoint as part of a request or a reply, or used locally.
-     * The objects that are produced by this method may be used to mass-produce {@code RequestHandler} instances.
-     *
+     * <p/>
      * You must have the {@link org.jboss.remoting3.EndpointPermission registerService EndpointPermission} to invoke this method.
      *
-     * @param <I> the request type
-     * @param <O> the reply type
      * @param configuration the configuration to use
      * @throws IOException if an error occurs
      */
-    <I, O> Handle<RequestHandlerSource> registerService(LocalServiceConfiguration<I, O> configuration) throws IOException;
+    <I, O> SimpleCloseable registerService(LocalServiceConfiguration<I, O> configuration) throws IOException;
 
     /**
      * Add a service registration listener which is called whenever a local service is registered.
@@ -76,7 +60,7 @@
 
     /**
      * Create a client that uses the given request handler to handle its requests.
-     *
+     * <p/>
      * You must have the {@link org.jboss.remoting3.EndpointPermission createClient EndpointPermission} to invoke this method.
      *
      * @param <I> the request type
@@ -90,73 +74,25 @@
     <I, O> Client<I, O> createClient(RequestHandler handler, Class<I> requestClass,  Class<O> replyClass) throws IOException;
 
     /**
-     * Create a client source that uses the given request handler source to generate clients.
+     * Open a connection with a peer.
      *
-     * You must have the {@link org.jboss.remoting3.EndpointPermission createClientSource EndpointPermission} to invoke this method.
-     *
-     * @param <I> the request type
-     * @param <O> the reply type
-     * @param handlerSource the request handler source
-     * @param requestClass the class of requests sent through this client source
-     * @param replyClass the class of replies received back through this client source
-     * @return the client source
-     * @throws IOException if an error occurs
+     * @param destination the destination
+     * @return
+     * @throws IOException
      */
-    <I, O> ClientSource<I, O> createClientSource(RequestHandlerSource handlerSource, Class<I> requestClass, Class<O> replyClass) throws IOException;
+    IoFuture<? extends Connection> connect(URI destination) throws IOException;
 
     /**
-     * Attempt to open a client source by URI.
+     * Register a connection provider for a URI scheme.  The provider factory is called with the context which can
+     * be used to accept new connections or terminate the registration.
      *
-     * @param <I> the request type
-     * @param <O> the reply type
-     * @param uri the URI of the service
-     * @param requestClass the class of requests sent through the client source
-     * @param replyClass the class of replies received back through the client source
-     * @return the future service
-     * @throws IllegalArgumentException if the URI scheme does not correspond to a client souerce connection provider
-     */
-    <I, O> IoFuture<? extends ClientSource<I, O>> openClientSource(URI uri, Class<I> requestClass, Class<O> replyClass) throws IllegalArgumentException;
-
-    /**
-     * Attempt to open a client by URI.
-     *
-     * @param <I> the request type
-     * @param <O> the reply type
-     * @param uri the URI of the service
-     * @param requestClass the class of requests sent through the client source
-     * @param replyClass the class of replies received back through the client source
-     * @return the future service
-     * @throws IllegalArgumentException if the URI scheme does not correspond to a client connection provider
-     */
-    <I, O> IoFuture<? extends Client<I, O>> openClient(URI uri, Class<I> requestClass, Class<O> replyClass) throws IllegalArgumentException;
-
-    /**
-     * Connect to a remote endpoint.
-     *
-     * @param endpointUri the URI of the endpoint to connect to
-     * @return the future connection
-     * @throws IllegalArgumentException if the URI scheme does not correspond to an endpoint connection provider
-     */
-    IoFuture<? extends Closeable> openEndpointConnection(URI endpointUri) throws IllegalArgumentException;
-
-    /**
-     * Register a connection provider for a URI scheme.
-     *
      * @param uriScheme the URI scheme
-     * @param provider the provider
+     * @param providerFactory the provider factory
      * @return a handle which may be used to remove the registration
      */
-    EndpointConnectionAcceptor addConnectionProvider(String uriScheme, ConnectionProvider<?> provider);
+    void addConnectionProvider(String uriScheme, ConnectionProviderFactory providerFactory);
 
     /**
-     * Get the type of resource specified by the given URI.  If the type cannot be determined, returns {@link org.jboss.remoting3.ResourceType#UNKNOWN UNKNOWN}.
-     *
-     * @param uri the connection URI
-     * @return the resource type
-     */
-    ResourceType getResourceType(URI uri);
-
-    /**
      * Flags which can be passed in to listener registration methods.
      */
     enum ListenerFlag {

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,15 +22,14 @@
 
 package org.jboss.remoting3;
 
-import java.io.Closeable;
 import java.io.IOException;
-import java.lang.ref.WeakReference;
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Map;
 import java.util.Queue;
 import java.util.Set;
@@ -42,18 +41,18 @@
 import java.util.concurrent.locks.ReentrantLock;
 import org.jboss.remoting3.spi.AbstractHandleableCloseable;
 import org.jboss.remoting3.spi.AbstractSimpleCloseable;
+import org.jboss.remoting3.spi.Cancellable;
+import org.jboss.remoting3.spi.ConnectionHandler;
+import org.jboss.remoting3.spi.ConnectionHandlerFactory;
 import org.jboss.remoting3.spi.ConnectionProvider;
-import org.jboss.remoting3.spi.Handle;
+import org.jboss.remoting3.spi.ConnectionProviderContext;
+import org.jboss.remoting3.spi.ConnectionProviderFactory;
 import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.RequestHandlerSource;
-import org.jboss.remoting3.spi.Cancellable;
-import org.jboss.remoting3.spi.EndpointConnection;
-import org.jboss.remoting3.spi.EndpointConnectionAcceptor;
-import org.jboss.remoting3.spi.AbstractEndpointConnectionAcceptor;
+import org.jboss.remoting3.spi.RequestHandlerConnector;
+import org.jboss.remoting3.spi.Result;
 import org.jboss.xnio.IoFuture;
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.WeakCloseable;
-import org.jboss.xnio.AbstractIoFuture;
 import org.jboss.xnio.log.Logger;
 
 /**
@@ -82,6 +81,10 @@
         return new ConcurrentLinkedQueue<T>();
     }
 
+    static <T> List<T> arrayList() {
+        return new ArrayList<T>();
+    }
+
     private static final Logger log = Logger.getLogger("org.jboss.remoting.endpoint");
 
     private final String name;
@@ -92,23 +95,17 @@
      */
     private final Lock serviceRegistrationLock = new ReentrantLock();
 
-    /**
-     * 
-     */
-    private final Queue<Registration<ServiceRegistrationListener>> serviceListenerRegistrations = concurrentLinkedQueue();
+    private final Set<Registration<ServiceRegistrationListener>> serviceListenerRegistrations = hashSet();
+    private final Map<String, ServiceRegistration> registeredLocalServices = hashMap();
 
-    private final ConcurrentMap<String, ServiceRegistration> registeredLocalServices = concurrentHashMap();
+    private final ConcurrentMap<String, ConnectionProvider> connectionProviders = concurrentHashMap();
 
-    private final ConcurrentMap<String, ConnectionProvider<?>> connectionProviders = concurrentHashMap();
-
-    private final ConcurrentMap<Object, Object> endpointMap = concurrentHashMap();
-
     private static final EndpointPermission CREATE_ENDPOINT_PERM = new EndpointPermission("createEndpoint");
     private static final EndpointPermission CREATE_REQUEST_HANDLER_PERM = new EndpointPermission("createRequestHandler");
     private static final EndpointPermission REGISTER_SERVICE_PERM = new EndpointPermission("registerService");
     private static final EndpointPermission CREATE_CLIENT_PERM = new EndpointPermission("createClient");
-    private static final EndpointPermission CREATE_CLIENT_SOURCE_PERM = new EndpointPermission("createClientSource");
     private static final EndpointPermission ADD_SERVICE_LISTENER_PERM = new EndpointPermission("addServiceListener");
+    private static final EndpointPermission CONNECT_PERM = new EndpointPermission("connect");
     private static final EndpointPermission ADD_CONNECTION_PROVIDER_PERM = new EndpointPermission("addConnectionProvider");
 
     public EndpointImpl(final Executor executor, final String name) {
@@ -117,7 +114,6 @@
         if (sm != null) {
             sm.checkPermission(CREATE_ENDPOINT_PERM);
         }
-        connectionProviders.put("jrs", new JrsConnectionProvider());
         this.executor = executor;
         this.name = name;
     }
@@ -138,21 +134,21 @@
         return name;
     }
 
-    public ConcurrentMap<Object, Object> getAttributes() {
-        return endpointMap;
-    }
-
-    public <I, O> Handle<RequestHandler> createLocalRequestHandler(final RequestListener<I, O> requestListener, final Class<I> requestClass, final Class<O> replyClass) throws IOException {
+    public <I, O> RequestHandler createLocalRequestHandler(final RequestListener<I, O> requestListener, final Class<I> requestClass, final Class<O> replyClass) throws IOException {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(CREATE_REQUEST_HANDLER_PERM);
         }
-        LocalRequestHandler.Config<I, O> config = new LocalRequestHandler.Config<I, O>(requestClass, replyClass);
-        config.setExecutor(executor);
-        config.setRequestListener(requestListener);
-        config.setClientContext(new ClientContextImpl(executor));
-        final LocalRequestHandler<I, O> localRequestHandler = new LocalRequestHandler<I, O>(config);
+        checkOpen();
+        final ClientContextImpl clientContext = new ClientContextImpl(executor, loopbackConnection);
+        final LocalRequestHandler<I, O> localRequestHandler = new LocalRequestHandler<I, O>(executor,
+                requestListener, clientContext, requestClass, replyClass);
         final WeakCloseable lrhCloseable = new WeakCloseable(localRequestHandler);
+        clientContext.addCloseHandler(new CloseHandler<ClientContext>() {
+            public void handleClose(final ClientContext closed) {
+                IoUtils.safeClose(localRequestHandler);
+            }
+        });
         final Key key = addCloseHandler(new CloseHandler<Endpoint>() {
             public void handleClose(final Endpoint closed) {
                 IoUtils.safeClose(lrhCloseable);
@@ -163,15 +159,17 @@
                 key.remove();
             }
         });
-        localRequestHandler.open();
-        return localRequestHandler.getHandle();
+        return localRequestHandler;
     }
 
-    public <I, O> Handle<RequestHandlerSource> registerService(final LocalServiceConfiguration<I, O> configuration) throws IOException {
+    public <I, O> SimpleCloseable registerService(final LocalServiceConfiguration<I, O> configuration) throws IOException {
         SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(REGISTER_SERVICE_PERM);
         }
+        if (configuration == null) {
+            throw new NullPointerException("configuration is null");
+        }
         final String serviceType = configuration.getServiceType();
         final String groupName = configuration.getGroupName();
         final int metric = configuration.getMetric();
@@ -180,58 +178,91 @@
         }
         ServiceURI.validateServiceType(serviceType);
         ServiceURI.validateGroupName(groupName);
+        checkOpen();
         final String serviceKey = serviceType.toLowerCase() + ":" + groupName.toLowerCase();
-        final LocalRequestHandlerSource.Config<I, O> config = new LocalRequestHandlerSource.Config<I,O>(configuration.getRequestClass(), configuration.getReplyClass());
-        config.setRequestListener(configuration.getRequestListener());
-        config.setExecutor(executor);
-        final LocalRequestHandlerSource<I, O> localRequestHandlerSource = new LocalRequestHandlerSource<I, O>(config);
-        final ServiceRegistration registration = new ServiceRegistration(serviceType, groupName, name, localRequestHandlerSource);
+        final Class<I> requestClass = configuration.getRequestClass();
+        final Class<O> replyClass = configuration.getReplyClass();
+        final ClientListener<I, O> clientListener = configuration.getClientListener();
+        final Executor executor = this.executor;
+        final Map<String, ServiceRegistration> registeredLocalServices = this.registeredLocalServices;
+        final RequestHandlerConnector requestHandlerConnector = new RequestHandlerConnector() {
+            public Cancellable createRequestHandler(final Result<RequestHandler> result) throws SecurityException {
+                try {
+                    final ClientContextImpl clientContext = new ClientContextImpl(executor, loopbackConnection);
+                    final RequestListener<I, O> requestListener = clientListener.handleClientOpen(clientContext);
+                    final RequestHandler localRequestHandler = createLocalRequestHandler(requestListener, requestClass, replyClass);
+                    clientContext.addCloseHandler(new CloseHandler<ClientContext>() {
+                        public void handleClose(final ClientContext closed) {
+                            IoUtils.safeClose(localRequestHandler);
+                        }
+                    });
+                    result.setResult(localRequestHandler);
+                } catch (IOException e) {
+                    result.setException(e);
+                }
+                return Cancellable.NULL_CANCELLABLE;
+            }
+        };
+        final ServiceRegistration registration = new ServiceRegistration(serviceType, groupName, name, requestHandlerConnector);
+        // this handle is used to remove the service registration
         final AbstractSimpleCloseable newHandle = new AbstractSimpleCloseable(executor) {
             protected void closeAction() throws IOException {
-                // todo fix
-                registeredLocalServices.remove(serviceKey);
+                final Lock lock = serviceRegistrationLock;
+                lock.lock();
+                try {
+                    registeredLocalServices.remove(serviceKey);
+                } finally {
+                    lock.unlock();
+                }
             }
         };
         registration.setHandle(newHandle);
+        final List<Registration<ServiceRegistrationListener>> serviceListenerRegistrations;
         final Lock lock = serviceRegistrationLock;
+        // actually register the service, and while we have the lock, snag a copy of the registration listener list
         lock.lock();
         try {
-            if (registeredLocalServices.putIfAbsent(serviceKey, registration) != null) {
+            if (registeredLocalServices.containsKey(serviceKey)) {
                 throw new ServiceRegistrationException("Registration of service of type \"" + serviceType + "\" in group \"" + groupName + "\" duplicates an already-registered service's specification");
             }
+            registeredLocalServices.put(serviceKey, registration);
+            serviceListenerRegistrations = new ArrayList<Registration<ServiceRegistrationListener>>(this.serviceListenerRegistrations);
         } finally {
             lock.unlock();
         }
-        final WeakCloseable lrhCloseable = new WeakCloseable(localRequestHandlerSource);
-        final Key key = addCloseHandler(new CloseHandler<Endpoint>() {
-            public void handleClose(final Endpoint closed) {
+        // this registration closes the service registration when the endpoint is closed
+        final WeakCloseable lrhCloseable = new WeakCloseable(newHandle);
+        final Key key = addCloseHandler(new CloseHandler<Object>() {
+            public void handleClose(final Object closed) {
                 IoUtils.safeClose(lrhCloseable);
             }
         });
-        localRequestHandlerSource.addCloseHandler(new CloseHandler<RequestHandlerSource>() {
-            public void handleClose(final RequestHandlerSource closed) {
+        // this registration removes the prior registration if the service registration is closed
+        newHandle.addCloseHandler(new CloseHandler<Object>() {
+            public void handleClose(final Object closed) {
                 key.remove();
             }
         });
-        localRequestHandlerSource.open();
-        for (Registration<ServiceRegistrationListener> slr : serviceListenerRegistrations) {
-            final ServiceRegistrationListener registrationListener = slr.getResource();
-            try {
-                final ServiceRegistrationListener.ServiceInfo serviceInfo = new ServiceRegistrationListener.ServiceInfo();
-                serviceInfo.setGroupName(groupName);
-                serviceInfo.setServiceType(serviceType);
-                serviceInfo.setMetric(metric);
-                serviceInfo.setRegistrationHandle(newHandle);
-                serviceInfo.setRequestHandlerSource(localRequestHandlerSource);
-                registrationListener.serviceRegistered(slr, serviceInfo);
-            } catch (VirtualMachineError vme) {
-                // panic!
-                throw vme;
-            } catch (Throwable t) {
-                logListenerError(t);
+        // notify all service listener registrations that were registered at the time the service was created
+        final ServiceRegistrationListener.ServiceInfo serviceInfo = new ServiceRegistrationListener.ServiceInfo();
+        serviceInfo.setGroupName(groupName);
+        serviceInfo.setServiceType(serviceType);
+        serviceInfo.setMetric(metric);
+        serviceInfo.setRegistrationHandle(newHandle);
+        serviceInfo.setRequestHandlerConnector(requestHandlerConnector);
+        executor.execute(new Runnable() {
+            public void run() {
+                for (final Registration<ServiceRegistrationListener> slr : serviceListenerRegistrations) {
+                    final ServiceRegistrationListener registrationListener = slr.getResource();
+                    try {
+                        registrationListener.serviceRegistered(slr, serviceInfo.clone());
+                    } catch (Throwable t) {
+                        logListenerError(t);
+                    }
+                }
             }
-        }
-        return localRequestHandlerSource.getHandle();
+        });
+        return newHandle;
     }
 
     private static void logListenerError(final Throwable t) {
@@ -243,196 +274,40 @@
         if (sm != null) {
             sm.checkPermission(CREATE_CLIENT_PERM);
         }
-        boolean ok = false;
-        final Handle<RequestHandler> handle = requestHandler.getHandle();
-        try {
-            final ClientImpl<I, O> client = ClientImpl.create(handle, executor, requestType, replyType);
-            final WeakCloseable lrhCloseable = new WeakCloseable(new WeakReference<Closeable>(client));
-            final Key key = addCloseHandler(new CloseHandler<Endpoint>() {
-                public void handleClose(final Endpoint closed) {
-                    IoUtils.safeClose(lrhCloseable);
-                }
-            });
-            client.addCloseHandler(new CloseHandler<Client>() {
-                public void handleClose(final Client closed) {
-                    key.remove();
-                }
-            });
-            ok = true;
-            return client;
-        } finally {
-            if (! ok) {
-                IoUtils.safeClose(handle);
-            }
+        if (requestHandler == null) {
+            throw new NullPointerException("requestHandler is null");
         }
-    }
-
-    public <I, O> ClientSource<I, O> createClientSource(final RequestHandlerSource requestHandlerSource, final Class<I> requestClass, final Class<O> replyClass) throws IOException {
-        SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            sm.checkPermission(CREATE_CLIENT_SOURCE_PERM);
+        if (requestType == null) {
+            throw new NullPointerException("requestType is null");
         }
-        boolean ok = false;
-        final Handle<RequestHandlerSource> handle = requestHandlerSource.getHandle();
-        try {
-            final ClientSourceImpl<I, O> clientSource = ClientSourceImpl.create(handle, this, requestClass, replyClass);
-            final WeakCloseable lrhCloseable = new WeakCloseable(new WeakReference<Closeable>(clientSource));
-            final Key key = addCloseHandler(new CloseHandler<Endpoint>() {
-                public void handleClose(final Endpoint closed) {
-                    IoUtils.safeClose(lrhCloseable);
-                }
-            });
-            clientSource.addCloseHandler(new CloseHandler<ClientSource>() {
-                public void handleClose(final ClientSource closed) {
-                    key.remove();
-                }
-            });
-            ok = true;
-            return clientSource;
-        } finally {
-            if (! ok) {
-                IoUtils.safeClose(handle);
-            }
+        if (replyType == null) {
+            throw new NullPointerException("replyType is null");
         }
-    }
-
-    public <I, O> IoFuture<ClientSource<I, O>> openClientSource(final URI uri, final Class<I> requestClass, final Class<O> replyClass) throws IllegalArgumentException {
-        final ConnectionProvider<RequestHandlerSource> cp = getConnectionProvider(uri);
-        if (cp.getResourceType() != ResourceType.CLIENT_SOURCE) {
-            throw new IllegalArgumentException("URI can not be used to open a client source");
-        }
-        final FutureResult<ClientSource<I, O>> futureClientSource = new FutureResult<ClientSource<I, O>>();
-        cp.connect(uri, new ConnectionProvider.Result<RequestHandlerSource>() {
-            public void setResult(final RequestHandlerSource result) {
-                final ClientSource<I, O> clientSource;
-                try {
-                    clientSource = createClientSource(result, requestClass, replyClass);
-                } catch (IOException e) {
-                    IoUtils.safeClose(result);
-                    futureClientSource.setException(e);
-                    return;
-                }
-                futureClientSource.setResult(clientSource);
+        checkOpen();
+        final ClientImpl<I, O> client = ClientImpl.create(requestHandler, executor, requestType, replyType);
+        final WeakCloseable lrhCloseable = new WeakCloseable(client);
+        // this registration closes the client when the endpoint is closed
+        final Key key = addCloseHandler(new CloseHandler<Endpoint>() {
+            public void handleClose(final Endpoint closed) {
+                IoUtils.safeClose(lrhCloseable);
             }
-
-            public void setException(final IOException exception) {
-                futureClientSource.setException(exception);
-            }
-
-            public void setCancelled() {
-                futureClientSource.finishCancel();
-            }
         });
-        return futureClientSource;
-    }
-
-    public <I, O> IoFuture<? extends Client<I, O>> openClient(final URI uri, final Class<I> requestClass, final Class<O> replyClass) throws IllegalArgumentException {
-        final ConnectionProvider<RequestHandler> cp = getConnectionProvider(uri);
-        if (cp.getResourceType() != ResourceType.CLIENT) {
-            throw new IllegalArgumentException("URI can not be used to open a client");
-        }
-        final FutureResult<Client<I, O>> futureClient = new FutureResult<Client<I, O>>();
-        cp.connect(uri, new ConnectionProvider.Result<RequestHandler>() {
-            public void setResult(final RequestHandler result) {
-                final Client<I, O> client;
-                try {
-                    client = createClient(result, requestClass, replyClass);
-                } catch (IOException e) {
-                    IoUtils.safeClose(result);
-                    futureClient.setException(e);
-                    return;
-                }
-                futureClient.setResult(client);
+        // this registration removes the prior registration if the client is closed
+        client.addCloseHandler(new CloseHandler<Client>() {
+            public void handleClose(final Client closed) {
+                IoUtils.safeClose(requestHandler);
+                key.remove();
             }
-
-            public void setException(final IOException exception) {
-                futureClient.setException(exception);
-            }
-
-            public void setCancelled() {
-                futureClient.finishCancel();
-            }
         });
-        return futureClient;
+        return client;
     }
 
-    public IoFuture<? extends Closeable> openEndpointConnection(final URI endpointUri) throws IllegalArgumentException {
-        final ConnectionProvider<EndpointConnection> cp = getConnectionProvider(endpointUri);
-        if (cp.getResourceType() != ResourceType.CLIENT) {
-            throw new IllegalArgumentException("URI can not be used to open an endpoint connection");
-        }
-        final FutureResult<SimpleCloseable> futureEndpointConn = new FutureResult<SimpleCloseable>();
-        cp.connect(endpointUri, new ConnectionProvider.Result<EndpointConnection>() {
-            public void setResult(final EndpointConnection result) {
-                if (futureEndpointConn.setResult(new AbstractSimpleCloseable(executor) {
-                    protected void closeAction() throws IOException {
-                        result.close();
-                    }
-                })) {
-                    // todo - add the endpoint connection to the endpoint registry; notify listeners; etc.
-                }
-            }
-
-            public void setException(final IOException exception) {
-                futureEndpointConn.setException(exception);
-            }
-
-            public void setCancelled() {
-                futureEndpointConn.finishCancel();
-            }
-        });
-        return futureEndpointConn;
-    }
-
-    public EndpointConnectionAcceptor addConnectionProvider(final String uriScheme, final ConnectionProvider<?> provider) {
-        final SecurityManager sm = System.getSecurityManager();
-        if (sm != null) {
-            sm.checkPermission(ADD_CONNECTION_PROVIDER_PERM);
-        }
-        final String key = uriScheme.toLowerCase();
-        if (connectionProviders.putIfAbsent(key, provider) != null) {
-            throw new IllegalArgumentException("Provider already registered for scheme \"" + uriScheme + "\"");
-        }
-        return new AbstractEndpointConnectionAcceptor(executor) {
-            protected void closeAction() throws IOException {
-                connectionProviders.remove(key, provider);
-            }
-
-            public void accept(final EndpointConnection connection) {
-                // todo - add the endpoint connection to the endpoint registry; notify listeners; etc.
-            }
-        };
-    }
-
-    public ResourceType getResourceType(final URI uri) {
-        final String scheme = uri.getScheme().toLowerCase();
-        final ConnectionProvider<?> provider = connectionProviders.get(scheme);
-        return provider != null ? provider.getResourceType() : ResourceType.UNKNOWN;
-    }
-
-    @SuppressWarnings({ "unchecked" })
-    private <T> ConnectionProvider<T> getConnectionProvider(final URI uri) {
-        if (uri == null) {
-            throw new NullPointerException("serviceUri is null");
-        }
-        final String scheme = uri.getScheme();
-        // this cast is checked later, indirectly
-        final ConnectionProvider<T> cp = (ConnectionProvider<T>) connectionProviders.get(scheme);
-        if (cp == null) {
-            throw new IllegalArgumentException("No connection providers available for URI scheme \"" + scheme + "\"");
-        }
-        if (! ServiceURI.isRemotingServiceUri(uri)) {
-            throw new IllegalArgumentException("Not a valid remoting service URI");
-        }
-        return cp;
-    }
-
     public SimpleCloseable addServiceRegistrationListener(final ServiceRegistrationListener listener, final Set<ListenerFlag> flags) {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(ADD_SERVICE_LISTENER_PERM);
         }
-        final Registration<ServiceRegistrationListener> registration = new Registration<ServiceRegistrationListener>(executor, listener, serviceListenerRegistrations);
+        final Registration<ServiceRegistrationListener> registration = new Registration<ServiceRegistrationListener>(listener);
         final Lock lock = serviceRegistrationLock;
         final Collection<ServiceRegistration> services;
         lock.lock();
@@ -451,7 +326,7 @@
             serviceInfo.setGroupName(service.getGroupName());
             serviceInfo.setMetric(service.getMetric());
             serviceInfo.setRegistrationHandle(service.getHandle());
-            serviceInfo.setRequestHandlerSource(service.getHandlerSource());
+            serviceInfo.setRequestHandlerConnector(service.getConnector());
             serviceInfo.setServiceType(service.getServiceType());
             listener.serviceRegistered(registration, serviceInfo);
             if (! registration.isOpen()) {
@@ -461,18 +336,108 @@
         return registration;
     }
 
-    private static final class Registration<T> extends AbstractSimpleCloseable {
+    public IoFuture<? extends Connection> connect(final URI destination) throws IOException {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(CONNECT_PERM);
+        }
+        final ConnectionProvider connectionProvider = connectionProviders.get(destination.getScheme());
+        final FutureResult<Connection, ConnectionHandlerFactory> futureResult = new FutureResult<Connection, ConnectionHandlerFactory>() {
+            protected Connection translate(final ConnectionHandlerFactory result) {
+                return new ConnectionImpl(result);
+            }
+        };
+        connectionProvider.connect(destination, futureResult.getResult());
+        return futureResult;
+    }
+
+    public void addConnectionProvider(final String uriScheme, final ConnectionProviderFactory providerFactory) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(ADD_CONNECTION_PROVIDER_PERM);
+        }
+        final ConnectionProviderContextImpl context = new ConnectionProviderContextImpl(executor, LOOPBACK_CONNECTION_HANDLER);
+        final ConnectionProvider provider = providerFactory.createInstance(context);
+        if (connectionProviders.putIfAbsent(uriScheme, provider) != null) {
+            IoUtils.safeClose(context);
+            throw new IllegalArgumentException("URI scheme '" + uriScheme + "' is already registered to a provider");
+        }
+        context.addCloseHandler(new CloseHandler<ConnectionProviderContext>() {
+            public void handleClose(final ConnectionProviderContext closed) {
+                connectionProviders.remove(uriScheme, provider);
+            }
+        });
+    }
+
+    public String toString() {
+        return "endpoint \"" + name + "\" <" + Integer.toHexString(hashCode()) + ">";
+    }
+
+    private <I, O> IoFuture<? extends Client<I, O>> doOpenClient(final ConnectionHandler connectionHandler, final String serviceType, final String groupName, final Class<I> requestClass, final Class<O> replyClass) {
+        final FutureResult<Client<I, O>, RequestHandler> futureResult = new FutureResult<Client<I, O>, RequestHandler>() {
+            protected Client<I, O> translate(final RequestHandler result) throws IOException {
+                return createClient(result, requestClass, replyClass);
+            }
+        };
+        connectionHandler.open(serviceType, groupName, futureResult.getResult());
+        return futureResult;
+    }
+
+    private class ConnectionImpl extends AbstractHandleableCloseable<Connection> implements Connection {
+        private final ConnectionHandler connectionHandler;
+
+        private ConnectionImpl(final ConnectionHandlerFactory connectionHandler) {
+            super(EndpointImpl.this.executor);
+            this.connectionHandler = connectionHandler.createInstance(LOOPBACK_CONNECTION_HANDLER);
+        }
+
+        public <I, O> IoFuture<? extends Client<I, O>> openClient(final String serviceType, final String groupName, final Class<I> requestClass, final Class<O> replyClass) {
+            return doOpenClient(connectionHandler, serviceType, groupName, requestClass, replyClass);
+        }
+
+        public <I, O> ClientConnector<I, O> createClientConnector(final RequestListener<I, O> listener, final Class<I> requestClass, final Class<O> replyClass) throws IOException {
+            final RequestHandler localRequestHandler = createLocalRequestHandler(listener, requestClass, replyClass);
+            final RequestHandlerConnector connector = connectionHandler.createConnector(localRequestHandler);
+            final ClientContextImpl context = new ClientContextImpl(executor, this);
+            context.addCloseHandler(new CloseHandler<ClientContext>() {
+                public void handleClose(final ClientContext closed) {
+                    IoUtils.safeClose(localRequestHandler);
+                }
+            });
+            return new ClientConnectorImpl<I, O>(connector, EndpointImpl.this, requestClass, replyClass, context);
+        }
+    }
+
+    private static final class ConnectionProviderContextImpl extends AbstractHandleableCloseable<ConnectionProviderContext> implements ConnectionProviderContext {
+
+        private final ConnectionHandler localConnectionHandler;
+
+        private ConnectionProviderContextImpl(final Executor executor, final ConnectionHandler localConnectionHandler) {
+            super(executor);
+            this.localConnectionHandler = localConnectionHandler;
+        }
+
+        public void accept(final ConnectionHandlerFactory connectionHandlerFactory) {
+            connectionHandlerFactory.createInstance(localConnectionHandler);
+        }
+    }
+
+    private final class Registration<T> extends AbstractSimpleCloseable {
         private final T resource;
-        private final Queue<Registration<T>> resourceQueue;
 
-        private Registration(final Executor executor, final T resource, final Queue<Registration<T>> resourceQueue) {
+        private Registration(final T resource) {
             super(executor);
             this.resource = resource;
-            this.resourceQueue = resourceQueue;
         }
 
         protected void closeAction() throws IOException {
-            resourceQueue.remove(this);
+            final Lock lock = serviceRegistrationLock;
+            lock.lock();
+            try {
+                serviceListenerRegistrations.remove(this);
+            } finally {
+                lock.unlock();
+            }
         }
 
         protected boolean isOpen() {
@@ -484,47 +449,47 @@
         }
     }
 
-    public String toString() {
-        return "endpoint \"" + name + "\" <" + Integer.toHexString(hashCode()) + ">";
-    }
-
-    final class JrsConnectionProvider implements ConnectionProvider<RequestHandlerSource> {
-
-        public Cancellable connect(final URI uri, final Result<RequestHandlerSource> requestHandlerSourceResult) throws IllegalArgumentException {
-            final ServiceSpecification spec = ServiceSpecification.fromUri(uri);
-            for (ServiceRegistration sr : registeredLocalServices.values()) {
-                if (sr.matches(spec)) {
-                    requestHandlerSourceResult.setResult(sr.getHandlerSource());
-                }
+    private final ConnectionHandler LOOPBACK_CONNECTION_HANDLER = new ConnectionHandler() {
+        public Cancellable open(final String serviceName, final String groupName, final Result<RequestHandler> result) {
+            // the loopback connection opens a local service
+            // local services are registered as RequestHandlerConnectors
+            final ServiceRegistration registration = registeredLocalServices.get(serviceName + ":" + groupName);
+            if (registration != null) {
+                return registration.getConnector().createRequestHandler(result);
             }
-            // todo - iterate through discovered services as well
+            result.setException(new ServiceNotFoundException(ServiceURI.create(serviceName, groupName, name), "No such service located"));
             return Cancellable.NULL_CANCELLABLE;
         }
 
-        public URI getConnectionUri(final URI uri) {
-            return uri;
+        public RequestHandlerConnector createConnector(final RequestHandler localHandler) {
+            // the loopback connection just returns the local handler directly as no forwarding is involved
+            return new RequestHandlerConnector() {
+                public Cancellable createRequestHandler(final Result<RequestHandler> result) throws SecurityException {
+                    result.setResult(localHandler);
+                    return Cancellable.NULL_CANCELLABLE;
+                }
+            };
         }
 
-        public ResourceType getResourceType() {
-            return ResourceType.CLIENT_SOURCE;
+        public void close() {
+            // not closeable
         }
-    }
+    };
 
-    /**
-     *
-     */
-    static final class FutureResult<T> extends AbstractIoFuture<T> {
+    private final Connection loopbackConnection = new Connection() {
+        public <I, O> IoFuture<? extends Client<I, O>> openClient(final String serviceType, final String groupName, final Class<I> requestClass, final Class<O> replyClass) {
+            return null;
+        }
 
-        protected boolean setException(final IOException exception) {
-            return super.setException(exception);
+        public <I, O> ClientConnector<I, O> createClientConnector(final RequestListener<I, O> listener, final Class<I> requestClass, final Class<O> replyClass) {
+            return null;
         }
 
-        protected boolean setResult(final T result) {
-            return super.setResult(result);
+        public void close() throws IOException {
         }
 
-        protected boolean finishCancel() {
-            return super.finishCancel();
+        public Key addCloseHandler(final CloseHandler<? super Connection> closeHandler) {
+            return null;
         }
-    }
+    };
 }

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureResult.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureResult.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureResult.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3;
+
+import org.jboss.xnio.AbstractIoFuture;
+import org.jboss.remoting3.spi.Result;
+import java.io.IOException;
+
+abstract class FutureResult<T, X> extends AbstractIoFuture<T> {
+    private final Result<X> result = new Result<X>() {
+        public void setResult(final X result) {
+            try {
+                FutureResult.this.setResult(translate(result));
+            } catch (IOException e) {
+                FutureResult.this.setException(e);
+            }
+        }
+
+        public void setException(final IOException exception) {
+            FutureResult.this.setException(exception);
+        }
+
+        public void setCancelled() {
+            finishCancel();
+        }
+    };
+
+    abstract protected T translate(X result) throws IOException;
+
+    Result<X> getResult() {
+        return result;
+    }
+
+    protected boolean setException(final IOException exception) {
+        return super.setException(exception);
+    }
+
+    protected boolean setResult(final T result) {
+        return super.setResult(result);
+    }
+
+    protected boolean finishCancel() {
+        return super.finishCancel();
+    }
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/IndeterminateOutcomeException.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/IndeterminateOutcomeException.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/IndeterminateOutcomeException.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,3 +1,25 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
 package org.jboss.remoting3;
 
 /**

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandler.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandler.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -44,12 +44,12 @@
 
     private static final Logger log = Logger.getLogger("org.jboss.remoting.listener");
 
-    LocalRequestHandler(Config<I, O> config) {
-        super(config.getExecutor());
-        requestListener = config.getRequestListener();
-        clientContext = config.getClientContext();
-        requestClass = config.getRequestClass();
-        replyClass = config.getReplyClass();
+    LocalRequestHandler(final Executor executor, final RequestListener<I, O> requestListener, final ClientContextImpl clientContext, final Class<I> requestClass, final Class<O> replyClass) {
+        super(executor);
+        this.requestListener = requestListener;
+        this.clientContext = clientContext;
+        this.requestClass = requestClass;
+        this.replyClass = replyClass;
     }
 
     public RemoteRequestContext receiveRequest(final Object request, final ReplyHandler replyHandler) {
@@ -86,69 +86,13 @@
 
     protected void closeAction() throws IOException {
         try {
-            requestListener.handleClientClose(clientContext);
+            requestListener.handleClose();
         } catch (Throwable t) {
-            log.error(t, "Unexpected exception in request listener client close handler method");
+            log.error(t, "Unexpected exception in request listener handleClose() method");
         }
     }
 
-    void open() throws IOException {
-        try {
-            requestListener.handleClientOpen(clientContext);
-        } catch (Throwable t) {
-            final IOException ioe = new IOException("Failed to open client context");
-            ioe.initCause(t);
-            throw ioe;
-        }
-    }
-
     public String toString() {
         return "local request handler <" + Integer.toHexString(hashCode()) + "> (request listener = " + String.valueOf(requestListener) + ")";
     }
-
-    static class Config<I, O> {
-        private final Class<I> requestClass;
-        private final Class<O> replyClass;
-
-        private Executor executor;
-        private RequestListener<I, O> requestListener;
-        private ClientContextImpl clientContext;
-
-        Config(final Class<I> requestClass, final Class<O> replyClass) {
-            this.requestClass = requestClass;
-            this.replyClass = replyClass;
-        }
-
-        public Class<I> getRequestClass() {
-            return requestClass;
-        }
-
-        public Class<O> getReplyClass() {
-            return replyClass;
-        }
-
-        public Executor getExecutor() {
-            return executor;
-        }
-
-        public void setExecutor(final Executor executor) {
-            this.executor = executor;
-        }
-
-        public RequestListener<I, O> getRequestListener() {
-            return requestListener;
-        }
-
-        public void setRequestListener(final RequestListener<I, O> requestListener) {
-            this.requestListener = requestListener;
-        }
-
-        public ClientContextImpl getClientContext() {
-            return clientContext;
-        }
-
-        public void setClientContext(final ClientContextImpl clientContext) {
-            this.clientContext = clientContext;
-        }
-    }
 }

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandlerSource.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandlerSource.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandlerSource.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,131 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-import java.io.IOException;
-import java.util.concurrent.Executor;
-import org.jboss.remoting3.spi.AbstractAutoCloseable;
-import org.jboss.remoting3.spi.Handle;
-import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.RequestHandlerSource;
-import org.jboss.xnio.log.Logger;
-
-/**
- *
- */
-final class LocalRequestHandlerSource<I, O> extends AbstractAutoCloseable<RequestHandlerSource> implements RequestHandlerSource {
-
-    private final RequestListener<I, O> requestListener;
-    private final ServiceContextImpl serviceContext;
-    private final Executor executor;
-    private final Class<I> requestClass;
-    private final Class<O> replyClass;
-
-    private static final Logger log = Logger.getLogger("org.jboss.remoting.listener-source");
-
-    LocalRequestHandlerSource(final Config<I, O> config) {
-        super(config.getExecutor());
-        requestClass = config.getRequestClass();
-        replyClass = config.getReplyClass();
-        requestListener = config.getRequestListener();
-        executor = config.getExecutor();
-        serviceContext = new ServiceContextImpl(executor);
-    }
-
-    public Handle<RequestHandler> createRequestHandler() throws IOException {
-        if (isOpen()) {
-            final LocalRequestHandler.Config<I, O> config = new LocalRequestHandler.Config<I, O>(requestClass, replyClass);
-            config.setExecutor(executor);
-            config.setRequestListener(requestListener);
-            config.setClientContext(new ClientContextImpl(serviceContext));
-            final LocalRequestHandler<I, O> localRequestHandler = new LocalRequestHandler<I, O>(config);
-            localRequestHandler.open();
-            return localRequestHandler.getHandle();
-        } else {
-            throw new IOException("LocalRequestHandlerSource is closed");
-        }
-    }
-
-    void open() throws IOException {
-        try {
-            requestListener.handleServiceOpen(serviceContext);
-            addCloseHandler(new CloseHandler<RequestHandlerSource>() {
-                public void handleClose(final RequestHandlerSource closed) {
-                    try {
-                        requestListener.handleServiceClose(serviceContext);
-                    } catch (Throwable t) {
-                        log.error(t, "Unexpected exception in request listener client close handler method");
-                    }
-                }
-            });
-        } catch (Throwable t) {
-            final IOException ioe = new IOException("Failed to open client context");
-            ioe.initCause(t);
-            throw ioe;
-        }
-    }
-
-    ServiceContextImpl getServiceContext() {
-        return serviceContext;
-    }
-
-    public String toString() {
-        return "local request handler source <" + Integer.toHexString(hashCode()) + "> (request listener = " + String.valueOf(requestListener) + ")";
-    }
-
-    static class Config<I, O> {
-        private final Class<I> requestClass;
-        private final Class<O> replyClass;
-        private Executor executor;
-        private RequestListener<I, O> requestListener;
-
-        Config(final Class<I> requestClass, final Class<O> replyClass) {
-            this.requestClass = requestClass;
-            this.replyClass = replyClass;
-        }
-
-        public Class<I> getRequestClass() {
-            return requestClass;
-        }
-
-        public Class<O> getReplyClass() {
-            return replyClass;
-        }
-
-        public Executor getExecutor() {
-            return executor;
-        }
-
-        public void setExecutor(final Executor executor) {
-            this.executor = executor;
-        }
-
-        public RequestListener<I, O> getRequestListener() {
-            return requestListener;
-        }
-
-        public void setRequestListener(final RequestListener<I, O> requestListener) {
-            this.requestListener = requestListener;
-        }
-    }
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalServiceConfiguration.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalServiceConfiguration.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalServiceConfiguration.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -28,7 +28,7 @@
  * @apiviz.exclude
  */
 public final class LocalServiceConfiguration<I, O> {
-    private final RequestListener<I, O> requestListener;
+    private final ClientListener<I, O> clientListener;
     private final Class<I> requestClass;
     private final Class<O> replyClass;
     private String serviceType;
@@ -38,12 +38,12 @@
     /**
      * Construct a new instance.
      *
-     * @param requestListener the request listener
+     * @param clientListener the client listener
      * @param requestClass the request class
      * @param replyClass the reply class
      */
-    public LocalServiceConfiguration(final RequestListener<I, O> requestListener, final Class<I> requestClass, final Class<O> replyClass) {
-        this.requestListener = requestListener;
+    public LocalServiceConfiguration(final ClientListener<I, O> clientListener, final Class<I> requestClass, final Class<O> replyClass) {
+        this.clientListener = clientListener;
         this.requestClass = requestClass;
         this.replyClass = replyClass;
     }
@@ -53,8 +53,8 @@
      *
      * @return the request listener
      */
-    public RequestListener<I, O> getRequestListener() {
-        return requestListener;
+    public ClientListener<I, O> getClientListener() {
+        return clientListener;
     }
 
     /**

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/NotOpenException.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/NotOpenException.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/NotOpenException.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3;
+
+import java.io.IOException;
+
+/**
+ * The resource is not open.
+ */
+public class NotOpenException extends IOException {
+
+    private static final long serialVersionUID = 8918460812305000601L;
+
+    /**
+     * Constructs a {@code NotOpenException} with no detail message. The cause is not initialized, and may subsequently be
+     * initialized by a call to {@link #initCause(Throwable) initCause}.
+     */
+    public NotOpenException() {
+    }
+
+    /**
+     * Constructs a {@code NotOpenException} with the specified detail message. The cause is not initialized, and may
+     * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+     *
+     * @param msg the detail message
+     */
+    public NotOpenException(final String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a {@code NotOpenException} with the specified cause. The detail message is set to:
+     * <pre>(cause == null ? null : cause.toString())</pre>
+     * (which typically contains the class and detail message of {@code cause}).
+     *
+     * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+     */
+    public NotOpenException(final Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a {@code NotOpenException} with the specified detail message and cause.
+     *
+     * @param msg the detail message
+     * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+     */
+    public NotOpenException(final String msg, final Throwable cause) {
+        super(msg, cause);
+    }
+
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemoteExecutionException.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemoteExecutionException.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemoteExecutionException.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,3 +1,25 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
 package org.jboss.remoting3;
 
 /**

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Remoting.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Remoting.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Remoting.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -29,9 +29,7 @@
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
-import org.jboss.remoting3.spi.Handle;
 import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.RequestHandlerSource;
 import org.jboss.xnio.CloseableExecutor;
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.log.Logger;
@@ -126,34 +124,15 @@
      * @throws IOException if an error occurs
      */
     public static <I, O> Client<I, O> createLocalClient(final Endpoint endpoint, final RequestListener<I, O> requestListener, final Class<I> requestClass, final Class<O> replyClass) throws IOException {
-        final Handle<RequestHandler> handle = endpoint.createLocalRequestHandler(requestListener, requestClass, replyClass);
+        final RequestHandler requestHandler = endpoint.createLocalRequestHandler(requestListener, requestClass, replyClass);
         try {
-            return endpoint.createClient(handle.getResource(), requestClass, replyClass);
+            return endpoint.createClient(requestHandler, requestClass, replyClass);
         } finally {
-            IoUtils.safeClose(handle);
+            IoUtils.safeClose(requestHandler);
         }
     }
 
     /**
-     * Create a local client source from a local service configuration.  The client source will be registered on the endpoint.
-     *
-     * @param endpoint the endpoint to bind the service to
-     * @param config the service configuration
-     * @param <I> the request type
-     * @param <O> the reply type
-     * @return a new client source
-     * @throws IOException if an error occurs
-     */
-    public static <I, O> ClientSource<I, O> createLocalClientSource(final Endpoint endpoint, final LocalServiceConfiguration<I, O> config) throws IOException {
-        final Handle<RequestHandlerSource> handle = endpoint.registerService(config);
-        try {
-            return endpoint.createClientSource(handle.getResource(), config.getRequestClass(), config.getReplyClass());
-        } finally {
-            IoUtils.safeClose(handle);
-        }
-    }
-
-    /**
      * An exception indicating that there was a problem creating an endpoint.
      *
      * @apiviz.exclude

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RequestListener.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RequestListener.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RequestListener.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -32,20 +32,6 @@
  */
 public interface RequestListener<I, O> {
     /**
-     * Handle the opening of a client.
-     *
-     * @param context the client context
-     */
-    void handleClientOpen(ClientContext context);
-
-    /**
-     * Handle the opening of a service.
-     *
-     * @param context the service context
-     */
-    void handleServiceOpen(ServiceContext context);
-
-    /**
      * Handle a request.  If this method throws {@code RemoteExecutionException}, then that exception is passed
      * back to the caller and the request is marked as complete.  Otherwise, the request
      * listener must send back either a reply (using the {@code sendReply()} method on the {@code RequestContext}) or
@@ -59,16 +45,8 @@
     void handleRequest(RequestContext<O> context, I request) throws RemoteExecutionException;
 
     /**
-     * Handle the close of a service.
-     *
-     * @param context the service context
+     * Handle the client closing.  Free up any resources.  This method is called after the close has occurred,
+     * so exceptions thrown will be ignored.
      */
-    void handleServiceClose(ServiceContext context);
-
-    /**
-     * Handle the close of a client.
-     *
-     * @param context the client context
-     */
-    void handleClientClose(ClientContext context);
+    void handleClose();
 }

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ResourceType.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ResourceType.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ResourceType.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,51 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-/**
- * The type of resource supported by a specific connection manager.
- *
- * @apiviz.excluded
- */
-public enum ResourceType {
-
-    /**
-     * An unknown resource.  Such a resource cannot be opened by an endpoint.
-     */
-    UNKNOWN,
-    /**
-     * A client resource.  Use {@link Endpoint#openClient(java.net.URI, Class, Class) Endpoint.openClient(*)} to open
-     * a client resource URI.
-     */
-    CLIENT,
-    /**
-     * A client source resource.  Use {@link Endpoint#openClientSource(java.net.URI, Class, Class) Endpoint.openClientSource(*)} to open
-     * a client source resource URI.
-     */
-    CLIENT_SOURCE,
-    /**
-     * An endpoint resource.  Use {@link Endpoint#openEndpointConnection(java.net.URI) Endpoint.openEndpointConnection(*)} to open
-     * an endpoint resource URI.
-     */
-    ENDPOINT,
-}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceContext.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceContext.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceContext.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,41 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * The server-side context of a service.  Used to hold state relating to a service (known as a {@code ContextSource} on
- * the client side).
- *
- * @apiviz.exclude
- */
-public interface ServiceContext extends HandleableCloseable<ServiceContext> {
-
-    /**
-     * Get an attribute map which can be used to cache arbitrary state on the server side.
-     *
-     * @return the attribute map
-     */
-    ConcurrentMap<Object, Object> getAttributes();
-}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceContextImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceContextImpl.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceContextImpl.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,41 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3;
-
-import java.util.concurrent.Executor;
-import org.jboss.xnio.log.Logger;
-
-/**
- *
- */
-final class ServiceContextImpl extends AbstractContextImpl<ServiceContext> implements ServiceContext {
-    private static final Logger log = Logger.getLogger("org.jboss.remoting.service-context");
-
-    protected ServiceContextImpl(final Executor executor) {
-        super(executor);
-    }
-
-    public String toString() {
-        return "service context instance <" + Integer.toHexString(hashCode()) + ">";
-    }
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceNotFoundException.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceNotFoundException.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceNotFoundException.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -27,7 +27,7 @@
 /**
  * Service not found.  This exception is thrown when a service is looked up which is not registered anywhere.
  */
-public final class ServiceNotFoundException extends RemotingException {
+public class ServiceNotFoundException extends RemotingException {
 
     private static final long serialVersionUID = -998858276817298658L;
 

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,7 +22,7 @@
 
 package org.jboss.remoting3;
 
-import org.jboss.remoting3.spi.RequestHandlerSource;
+import org.jboss.remoting3.spi.RequestHandlerConnector;
 
 /**
  *
@@ -33,25 +33,25 @@
     private final String groupName;
     private final String endpointName;
     private final int metric;
-    private final RequestHandlerSource handlerSource;
+    private final RequestHandlerConnector connector;
     private volatile SimpleCloseable handle;
 
-    ServiceRegistration(final String serviceType, final String groupName, final String endpointName, final int metric, final RequestHandlerSource handlerSource) {
+    ServiceRegistration(final String serviceType, final String groupName, final String endpointName, final int metric, final RequestHandlerConnector connector) {
         remote = true;
         this.serviceType = serviceType;
         this.groupName = groupName;
         this.endpointName = endpointName;
         this.metric = metric;
-        this.handlerSource = handlerSource;
+        this.connector = connector;
     }
 
-    ServiceRegistration(final String serviceType, final String groupName, final String endpointName, final RequestHandlerSource handlerSource) {
+    ServiceRegistration(final String serviceType, final String groupName, final String endpointName, final RequestHandlerConnector connector) {
         remote = false;
         metric = 0;
         this.serviceType = serviceType;
         this.groupName = groupName;
         this.endpointName = endpointName;
-        this.handlerSource = handlerSource;
+        this.connector = connector;
     }
 
     public boolean matches(final String serviceType, final String groupName, final String endpointName) {
@@ -87,8 +87,8 @@
         return metric;
     }
 
-    public RequestHandlerSource getHandlerSource() {
-        return handlerSource;
+    public RequestHandlerConnector getConnector() {
+        return connector;
     }
 
     public SimpleCloseable getHandle() {

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationListener.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationListener.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationListener.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,7 +22,7 @@
 
 package org.jboss.remoting3;
 
-import org.jboss.remoting3.spi.RequestHandlerSource;
+import org.jboss.remoting3.spi.RequestHandlerConnector;
 
 /**
  * A listener for watching service registrations on an endpoint.
@@ -44,11 +44,11 @@
      *
      * @apiviz.exclude
      */
-    final class ServiceInfo {
+    final class ServiceInfo implements Cloneable {
         private String serviceType;
         private String groupName;
         private int metric;
-        private RequestHandlerSource requestHandlerSource;
+        private RequestHandlerConnector requestHandlerConnector;
         private SimpleCloseable registrationHandle;
 
         /**
@@ -116,17 +116,17 @@
          *
          * @return the request handler source
          */
-        public RequestHandlerSource getRequestHandlerSource() {
-            return requestHandlerSource;
+        public RequestHandlerConnector getRequestHandlerConnector() {
+            return requestHandlerConnector;
         }
 
         /**
          * Set the request handler source.
          *
-         * @param requestHandlerSource the request handler source
+         * @param requestHandlerConnector the request handler source
          */
-        public void setRequestHandlerSource(final RequestHandlerSource requestHandlerSource) {
-            this.requestHandlerSource = requestHandlerSource;
+        public void setRequestHandlerConnector(final RequestHandlerConnector requestHandlerConnector) {
+            this.requestHandlerConnector = requestHandlerConnector;
         }
 
         /**
@@ -146,5 +146,18 @@
         public void setRegistrationHandle(final SimpleCloseable registrationHandle) {
             this.registrationHandle = registrationHandle;
         }
+
+        /**
+         * Create a shallow clone.
+         *
+         * @return the clone
+         */
+        public ServiceInfo clone() {
+            try {
+                return (ServiceInfo) super.clone();
+            } catch (CloneNotSupportedException e) {
+                throw new IllegalStateException(e);
+            }
+        }
     }
 }

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/UnknownURISchemeException.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/UnknownURISchemeException.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/UnknownURISchemeException.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,70 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3;
+
+/**
+ * Unknown URI scheme.  Thrown when attempting to open a connection or client with a URI whose scheme is not associated
+ * with any registered providers.
+ */
+public class UnknownURISchemeException extends RemotingException {
+
+    private static final long serialVersionUID = 4880830942189310924L;
+
+    /**
+     * Constructs a {@code UnknownURISchemeException} with no detail message. The cause is not initialized, and may
+     * subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+     */
+    public UnknownURISchemeException() {
+    }
+
+    /**
+     * Constructs a {@code UnknownURISchemeException} with the specified detail message. The cause is not initialized, and
+     * may subsequently be initialized by a call to {@link #initCause(Throwable) initCause}.
+     *
+     * @param msg the detail message
+     */
+    public UnknownURISchemeException(final String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a {@code UnknownURISchemeException} with the specified cause. The detail message is set to:
+     * <pre>(cause == null ? null : cause.toString())</pre>
+     * (which typically contains the class and detail message of {@code cause}).
+     *
+     * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+     */
+    public UnknownURISchemeException(final Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a {@code UnknownURISchemeException} with the specified detail message and cause.
+     *
+     * @param msg the detail message
+     * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method)
+     */
+    public UnknownURISchemeException(final String msg, final Throwable cause) {
+        super(msg, cause);
+    }
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/package-info.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/package-info.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/package-info.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,6 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
 /**
  * The base Remoting 3 API package.
+ * <p/>
+ * The main flow of client requests works like this:
+ * <p/>
+ * {@websequence.show mainflow}
+ * <p/>
  *
  * @apiviz.exclude org.jboss.remoting.transporter
+ *
+ * @websequence.diagram mainflow
+ * participant "User code" as user
+ * participant "IoFuture<Reply>" as fr
+ * participant "Client\n(endpoint A)" as client
+ * participant "Protocol's\nRequest Handler" as rh1
+ * participant "~~~\n~~~"
+ * participant "Local Request\nHandler (endpoint B)" as rh2
+ * participant "RequestListener\n(endpoint B)" as rl
+ * loop
+ * user->client: "client.send(request);"
+ * activate client
+ * client->rh1: "requestHandler\n.receiveRequest();"
+ * activate rh1
+ * client->fr: "...creates..."
+ * activate fr
+ * deactivate client
+ * fr->user: "return\nfutureReply;"
+ * deactivate fr
+ * activate user
+ * rh1-->rh2: Marshalled request
+ * deactivate rh1
+ * activate rh2
+ * rh2->rl: listener\n.handleRequest()
+ * deactivate rh2
+ * activate rl
+ * rl->rh2: context\n.sendReply()
+ * activate rh2
+ * deactivate rl
+ * rh2-->rh1: Marshalled reply
+ * deactivate rh2
+ * activate rh1
+ * rh1->fr: replyHandler.handleReply()
+ * deactivate rh1
+ * activate fr
+ * fr->user: invoke notifiers\n(async)
+ * deactivate fr
+ * user->fr: futureReply.get();
+ * deactivate user
+ * activate fr
+ * fr->user: reply
+ * destroy fr
+ * activate user
+ * end
  */
 package org.jboss.remoting3;
\ No newline at end of file

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractAutoCloseable.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractAutoCloseable.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractAutoCloseable.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -29,6 +29,7 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import org.jboss.remoting3.CloseHandler;
 import org.jboss.remoting3.RemotingException;
+import org.jboss.remoting3.HandleableCloseable;
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.WeakCloseable;
 import org.jboss.xnio.log.Logger;
@@ -37,7 +38,7 @@
  * A closeable implementation that supports reference counting.  Since the initial reference count is zero, implementors
  * must be careful to ensure that the first operation invoked is a call to {@link #getHandle()}.
  */
-public abstract class AbstractAutoCloseable<T> extends AbstractHandleableCloseable<T> implements AutoCloseable<T> {
+public abstract class AbstractAutoCloseable<T extends HandleableCloseable<T>> extends AbstractHandleableCloseable<T> implements AutoCloseable<T> {
 
     private static final Logger log = Logger.getLogger("org.jboss.remoting.resource");
 

Copied: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractConnectionProviderContext.java (from rev 5050, remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractEndpointConnectionAcceptor.java)
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractConnectionProviderContext.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractConnectionProviderContext.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.spi;
+
+import java.util.concurrent.Executor;
+
+public abstract class AbstractConnectionProviderContext extends AbstractHandleableCloseable<ConnectionProviderContext> implements ConnectionProviderContext {
+
+    /**
+     * Basic constructor.
+     *
+     * @param executor the executor used to execute the close notification handlers
+     */
+    protected AbstractConnectionProviderContext(final Executor executor) {
+        super(executor);
+    }
+}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractEndpointConnectionAcceptor.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractEndpointConnectionAcceptor.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractEndpointConnectionAcceptor.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,37 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3.spi;
-
-import java.util.concurrent.Executor;
-
-public abstract class AbstractEndpointConnectionAcceptor extends AbstractHandleableCloseable<EndpointConnectionAcceptor> implements EndpointConnectionAcceptor {
-
-    /**
-     * Basic constructor.
-     *
-     * @param executor the executor used to execute the close notification handlers
-     */
-    protected AbstractEndpointConnectionAcceptor(final Executor executor) {
-        super(executor);
-    }
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -25,13 +25,13 @@
 import java.io.IOException;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.IdentityHashMap;
+import java.util.Map;
 import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
-import java.util.concurrent.atomic.AtomicBoolean;
 import org.jboss.remoting3.CloseHandler;
 import org.jboss.remoting3.HandleableCloseable;
+import org.jboss.remoting3.NotOpenException;
 import org.jboss.remoting3.RemotingException;
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.log.Logger;
@@ -40,18 +40,18 @@
  * A basic implementation of a closeable resource.  Use as a convenient base class for your closeable resources.
  * Ensures that the {@code close()} method is idempotent; implements the registry of close handlers.
  */
-public abstract class AbstractHandleableCloseable<T> implements HandleableCloseable<T> {
+public abstract class AbstractHandleableCloseable<T extends HandleableCloseable<T>> implements HandleableCloseable<T> {
 
     private static final Logger log = Logger.getLogger("org.jboss.remoting.resource");
+    private static final boolean LEAK_DEBUGGING;
 
-    protected final Executor executor;
+    private final Executor executor;
+    private final StackTraceElement[] backtrace;
+
     private final Object closeLock = new Object();
-    private final AtomicBoolean closed = new AtomicBoolean();
-    private Set<CloseHandler<? super T>> closeHandlers;
+    private boolean closed;
+    private Map<Key, CloseHandler<? super T>> closeHandlers = null;
 
-    private static final boolean LEAK_DEBUGGING;
-    private final StackTraceElement[] backtrace;
-
     static {
         boolean b = false;
         try {
@@ -86,7 +86,9 @@
      * @return {@code true} if the resource is still open
      */
     protected boolean isOpen() {
-        return ! closed.get();
+        synchronized (closeLock) {
+            return ! closed;
+        }
     }
 
     /**
@@ -99,24 +101,21 @@
     /**
      * {@inheritDoc}
      */
-    @SuppressWarnings({ "unchecked" })
     public final void close() throws IOException {
-        if (! closed.getAndSet(true)) {
+        final Map<Key, CloseHandler<? super T>> closeHandlers;
+        synchronized (closeLock) {
+            if (closed) {
+                return;
+            }
+            closed = true;
+            closeHandlers = this.closeHandlers;
+            this.closeHandlers = null;
+        }
+        if (closeHandlers != null) {
             log.trace("Closed %s", this);
-            synchronized (closeLock) {
-                if (closeHandlers != null) {
-                    for (final CloseHandler<? super T> handler : closeHandlers) {
-                        try {
-                            executor.execute(new Runnable() {
-                                public void run() {
-                                    SpiUtils.safeHandleClose(handler, (T) AbstractHandleableCloseable.this);
-                                }
-                            });
-                        } catch (RejectedExecutionException ree) {
-                            SpiUtils.safeHandleClose(handler, (T) AbstractHandleableCloseable.this);
-                        }
-                    }
-                    closeHandlers = null;
+            if (closeHandlers != null) {
+                for (final CloseHandler<? super T> handler : closeHandlers.values()) {
+                    runCloseTask(new CloseHandlerTask<T>(handler));
                 }
             }
             closeAction();
@@ -127,21 +126,56 @@
      * {@inheritDoc}
      */
     public Key addCloseHandler(final CloseHandler<? super T> handler) {
+        if (handler == null) {
+            throw new NullPointerException("handler is null");
+        }
         synchronized (closeLock) {
-            if (closeHandlers == null) {
-                closeHandlers = new HashSet<CloseHandler<? super T>>();
+            if (! closed) {
+                final Key key = new KeyImpl<T>(this);
+                final Map<Key, CloseHandler<? super T>> closeHandlers = this.closeHandlers;
+                if (closeHandlers == null) {
+                    final IdentityHashMap<Key, CloseHandler<? super T>> newMap = new IdentityHashMap<Key, CloseHandler<? super T>>();
+                    this.closeHandlers = newMap;
+                    newMap.put(key, handler);
+                } else {
+                    closeHandlers.put(key, handler);
+                }
+                return key;
             }
-            closeHandlers.add(handler);
-            return new Key() {
-                public void remove() {
-                    synchronized (closeLock) {
-                        final Set<CloseHandler<? super T>> closeHandlers = AbstractHandleableCloseable.this.closeHandlers;
-                        if (closeHandlers != null) {
-                            closeHandlers.remove(handler);
-                        }
-                    }
+        }
+        runCloseTask(new CloseHandlerTask<T>(handler));
+        return new NullKey();
+    }
+
+    private void runCloseTask(final CloseHandlerTask<T> task) {
+        try {
+            executor.execute(task);
+        } catch (RejectedExecutionException ree) {
+            task.run();
+        }
+    }
+
+    private static final class NullKey implements Key {
+        public void remove() {
+        }
+    }
+
+    private static final class KeyImpl<T extends HandleableCloseable<T>> implements Key {
+
+        private final AbstractHandleableCloseable<T> instance;
+
+        private KeyImpl(final AbstractHandleableCloseable<T> instance) {
+            this.instance = instance;
+        }
+
+        public void remove() {
+            synchronized (instance.closeLock) {
+                final Map<Key, CloseHandler<? super T>> closeHandlers = instance.closeHandlers;
+
+                if (closeHandlers != null) {
+                    closeHandlers.remove(this);
                 }
-            };
+            }
         }
     }
 
@@ -161,7 +195,7 @@
         try {
             super.finalize();
         } finally {
-            if (isOpen()) {
+            if (! isOpen()) {
                 if (LEAK_DEBUGGING) {
                     final Throwable t = new LeakThrowable();
                     t.setStackTrace(backtrace);
@@ -174,6 +208,19 @@
         }
     }
 
+    /**
+     * Check if open, throwing an exception if it is not.
+     *
+     * @throws org.jboss.remoting3.NotOpenException if not open
+     */
+    protected void checkOpen() throws NotOpenException {
+        synchronized (closeLock) {
+            if (closed) {
+                throw new NotOpenException(toString() + " is not open");
+            }
+        }
+    }
+
     @SuppressWarnings({ "serial" })
     private static final class LeakThrowable extends Throwable {
 
@@ -184,4 +231,18 @@
             return "a leaked reference";
         }
     }
+
+    private final class CloseHandlerTask<T extends HandleableCloseable<T>> implements Runnable {
+
+        private final CloseHandler<? super T> handler;
+
+        private CloseHandlerTask(final CloseHandler<? super T> handler) {
+            this.handler = handler;
+        }
+
+        @SuppressWarnings({ "unchecked" })
+        public void run() {
+            SpiUtils.safeHandleClose(handler, (T) AbstractHandleableCloseable.this);
+        }
+    }
 }

Copied: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandler.java (from rev 5032, remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnection.java)
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandler.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,49 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.spi;
+
+import java.io.Closeable;
+
+/**
+ * A connection to a foreign endpoint.  This interface is implemented by the protocol implementation.
+ */
+public interface ConnectionHandler extends Closeable {
+
+    /**
+     * Open a request handler.
+     *
+     * @param serviceName the service name
+     * @param groupName the group name
+     * @param result the result for the connected request handler
+     * @return a handle which may be used to cancel the pending operation
+     */
+    Cancellable open(String serviceName, String groupName, Result<RequestHandler> result);
+
+    /**
+     * Create a connector which may be used to communicate with the given local RequestHandler.  The connector
+     * should only produce a result once it has passed to the remote side of this connection.
+     *
+     * @return the connector
+     */
+    RequestHandlerConnector createConnector(RequestHandler localHandler);
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandlerFactory.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandlerFactory.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandlerFactory.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,38 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.spi;
+
+/**
+ *
+ */
+public interface ConnectionHandlerFactory {
+
+    /**
+     * Create a connection handler instance.  The provided connection handler is the handler for the next hop of
+     * the local connection; typically this will be the endpoint loopback connection but it may not be.
+     *
+     * @param localConnectionHandler the local connection handler for incoming requests
+     * @return the connection handler for outgoing requests
+     */
+    ConnectionHandler createInstance(ConnectionHandler localConnectionHandler);
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProvider.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProvider.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProvider.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,25 +22,15 @@
 
 package org.jboss.remoting3.spi;
 
-import java.io.IOException;
 import java.net.URI;
-import org.jboss.remoting3.ResourceType;
 
 /**
+ * A connection provider.  Used to establish connections with remote systems.
  *
+ * @remoting.implement
  */
-public interface ConnectionProvider<T> {
-    Cancellable connect(URI uri, Result<T> result) throws IllegalArgumentException;
+public interface ConnectionProvider {
+    Cancellable connect(URI uri, Result<ConnectionHandlerFactory> result) throws IllegalArgumentException;
 
     URI getConnectionUri(URI uri);
-
-    ResourceType getResourceType();
-
-    interface Result<T> {
-        void setResult(T result);
-
-        void setException(IOException exception);
-
-        void setCancelled();
-    }
 }

Copied: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java (from rev 5050, remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnectionAcceptor.java)
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,32 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.spi;
+
+import org.jboss.remoting3.HandleableCloseable;
+
+/**
+ *
+ */
+public interface ConnectionProviderContext extends HandleableCloseable<ConnectionProviderContext> {
+    void accept(ConnectionHandlerFactory connectionHandlerFactory);
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderFactory.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderFactory.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderFactory.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,30 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.spi;
+
+/**
+ *
+ */
+public interface ConnectionProviderFactory {
+    ConnectionProvider createInstance(ConnectionProviderContext context);
+}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnection.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnection.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnection.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,38 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3.spi;
-
-import java.io.Closeable;
-
-/**
- * A connection to a foreign endpoint.
- */
-public interface EndpointConnection extends Closeable {
-    String getEndpointName();
-
-    int getMetric();
-
-    ConnectionProvider<RequestHandler> getRequestHandlerConnectionProvider();
-
-    ConnectionProvider<RequestHandlerSource> getRequestHandlerSourceConnectionProvider();
-}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnectionAcceptor.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnectionAcceptor.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/EndpointConnectionAcceptor.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,32 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2009, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3.spi;
-
-import org.jboss.remoting3.HandleableCloseable;
-
-/**
- *
- */
-public interface EndpointConnectionAcceptor extends HandleableCloseable<EndpointConnectionAcceptor> {
-    void accept(EndpointConnection connection);
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandler.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandler.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,15 +22,16 @@
 
 package org.jboss.remoting3.spi;
 
+import org.jboss.remoting3.HandleableCloseable;
+
 /**
- * A request handler, which can be passed to remote endpoints.  Remote systems can then use the handler
- * to make invocations, or they may forward a handler on to other remote systems.
+ * A request handler.
  * <p>
  * This is an internal Remoting interface, intended to be implemented only by Remoting internals and protocol implementations.
- * It should not be implemented by end-users, as members may be added without notice.  Applications should instead use
+ * It should not be used or implemented by end-users.  Members may be added without notice.  Applications should instead use
  * the {@link org.jboss.remoting3.Client Client} and {@link org.jboss.remoting3.RequestListener RequestListener} interfaces.
  */
-public interface RequestHandler extends AutoCloseable<RequestHandler> {
+public interface RequestHandler extends HandleableCloseable<RequestHandler> {
 
     /**
      * Receive a request from a remote system.  This method is intended to be called by protocol handlers.  If the

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandlerConnector.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandlerConnector.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandlerConnector.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,39 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.spi;
+
+/**
+ *
+ */
+public interface RequestHandlerConnector {
+
+    /**
+     * Get the request handler.  If this connector was forwarded, this method may only be called once;
+     * further attempts to call it should result in a {@code SecurityException}.
+     *
+     * @param result the result of the connection
+     * @return the cancellation handle
+     * @throws SecurityException if this is a forwarding connector, thrown if the connector was not forwarded or if this method is called more than one time
+     */
+    Cancellable createRequestHandler(Result<RequestHandler> result) throws SecurityException;
+}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandlerSource.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandlerSource.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandlerSource.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -1,42 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source
- * Copyright 2008, JBoss Inc., and individual contributors as indicated
- * by the @authors tag. See the copyright.txt in the distribution for a
- * full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-
-package org.jboss.remoting3.spi;
-
-import java.io.IOException;
-
-/**
- * A request handler source, which can be passed to remote endpoints.  Remote systems can then use the handler source
- * to acquire request handlers, or they may pass it on to other systems.  Acquiring a request handler using this method
- * has the advantage that a round trip to the remote side is not necessary; the local side can spawn a request handler
- * and simply notify the remote side of the change.
- */
-public interface RequestHandlerSource extends AutoCloseable<RequestHandlerSource> {
-
-    /**
-     * Create a request handler for the service corresponding to this request handler source.
-     *
-     * @return a request handler
-     * @throws IOException if a client could not be opened
-     */
-    Handle<RequestHandler> createRequestHandler() throws IOException;
-}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/Result.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/Result.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/Result.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -0,0 +1,33 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, JBoss Inc., and individual contributors as indicated
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+
+package org.jboss.remoting3.spi;
+
+import java.io.IOException;
+
+public interface Result<T> {
+    void setResult(T result);
+
+    void setException(IOException exception);
+
+    void setCancelled();
+}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/InputStreamHandlerFactory.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/InputStreamHandlerFactory.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/InputStreamHandlerFactory.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,13 +22,14 @@
 
 package org.jboss.remoting3.stream;
 
+import java.io.IOException;
 import java.io.InputStream;
-import java.io.IOException;
 import java.nio.ByteBuffer;
-import org.jboss.xnio.channels.StreamChannel;
+import java.nio.channels.Channel;
+import org.jboss.xnio.IoFuture;
 import org.jboss.xnio.IoHandler;
 import org.jboss.xnio.IoUtils;
-import org.jboss.xnio.IoFuture;
+import org.jboss.xnio.channels.StreamChannel;
 import org.jboss.xnio.log.Logger;
 
 /**
@@ -73,7 +74,7 @@
             };
         }
 
-        public IoHandler<StreamChannel> getRemoteHandler() {
+        public IoHandler<Channel> getRemoteHandler() {
             return IoUtils.nullHandler();
         }
 

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/OutputStreamHandlerFactory.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/OutputStreamHandlerFactory.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/OutputStreamHandlerFactory.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,21 +22,22 @@
 
 package org.jboss.remoting3.stream;
 
-import java.io.OutputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
 import java.io.InterruptedIOException;
-import java.io.InputStreamReader;
+import java.io.OutputStream;
+import static java.lang.Math.min;
+import static java.lang.Thread.currentThread;
 import java.nio.ByteBuffer;
+import java.nio.channels.Channel;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
-import static java.lang.Math.min;
-import static java.lang.Thread.currentThread;
-import org.jboss.xnio.channels.StreamChannel;
-import org.jboss.xnio.channels.ChannelInputStream;
+import org.jboss.xnio.IoFuture;
 import org.jboss.xnio.IoHandler;
-import org.jboss.xnio.IoFuture;
+import static org.jboss.xnio.IoUtils.nullHandler;
 import static org.jboss.xnio.IoUtils.safeClose;
-import static org.jboss.xnio.IoUtils.nullHandler;
+import org.jboss.xnio.channels.ChannelInputStream;
+import org.jboss.xnio.channels.StreamChannel;
 
 /**
  * A handler factory for automatic forwarding of output streams.
@@ -62,7 +63,7 @@
             return new LocalHandler(localInstance);
         }
 
-        public IoHandler<StreamChannel> getRemoteHandler() {
+        public IoHandler<Channel> getRemoteHandler() {
             return nullHandler();
         }
 

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/StreamHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/StreamHandler.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/stream/StreamHandler.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -44,7 +44,7 @@
      *
      * @return the local XNIO handler
      */
-    IoHandler<C> getLocalHandler();
+    IoHandler<? super C> getLocalHandler();
 
     /**
      * Get the remote XNIO handler for this stream.  The remote handler should not be instantiated until the
@@ -52,7 +52,7 @@
      *
      * @return the remote XNIO handler
      */
-    IoHandler<C> getRemoteHandler();
+    IoHandler<? super C> getRemoteHandler();
 
     /**
      * Get the remote proxy instance for this stream.  The remote proxy should not be instantiated until the

Modified: remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/EndpointTestCase.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/EndpointTestCase.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/EndpointTestCase.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -22,22 +22,12 @@
 
 package org.jboss.remoting3;
 
-import junit.framework.TestCase;
-import java.util.concurrent.Executors;
 import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
-import java.io.IOException;
-import org.jboss.remoting3.AbstractRequestListener;
-import org.jboss.remoting3.RequestContext;
-import org.jboss.remoting3.RemoteExecutionException;
-import org.jboss.remoting3.CloseHandler;
-import org.jboss.remoting3.Client;
-import org.jboss.remoting3.IndeterminateOutcomeException;
-import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.Handle;
+import junit.framework.TestCase;
 import org.jboss.xnio.IoUtils;
-import org.jboss.xnio.IoFuture;
 import org.jboss.xnio.log.Logger;
 
 /**
@@ -68,47 +58,6 @@
             final Object requestObj = new Object();
             final Object replyObj = new Object();
             try {
-                final Handle<RequestHandler> handle = endpoint.createLocalRequestHandler(new AbstractRequestListener<Object, Object>() {
-                    public void handleRequest(final RequestContext<Object> context, final Object request) throws RemoteExecutionException {
-                        assertEquals(request, requestObj);
-                        try {
-                            context.sendReply(replyObj);
-                        } catch (IOException e) {
-                            log.error(e, "Error sending reply!");
-                        }
-                    }
-                }, Object.class, Object.class);
-                try {
-                    final RequestHandler requestHandler = handle.getResource();
-                    try {
-                        requestHandler.addCloseHandler(new CloseHandler<RequestHandler>() {
-                            public void handleClose(final RequestHandler closed) {
-                                clientEndpointClosed.set(true);
-                            }
-                        });
-                        final Client<Object,Object> client = endpoint.createClient(requestHandler, Object.class, Object.class);
-                        try {
-                            client.addCloseHandler(new CloseHandler<Client<Object, Object>>() {
-                                public void handleClose(final Client<Object, Object> closed) {
-                                    clientClosed.set(true);
-                                }
-                            });
-                            handle.close();
-                            assertEquals(replyObj, client.invoke(requestObj));
-                            client.close();
-                            executorService.shutdown();
-                            assertTrue(executorService.awaitTermination(1L, TimeUnit.SECONDS));
-                            assertTrue(clientEndpointClosed.get());
-                            assertTrue(clientClosed.get());
-                        } finally {
-                            IoUtils.safeClose(client);
-                        }
-                    } finally {
-                        IoUtils.safeClose(requestHandler);
-                    }
-                } finally {
-                    IoUtils.safeClose(handle);
-                }
             } finally {
                 IoUtils.safeClose(endpoint);
             }
@@ -124,51 +73,6 @@
         try {
             final EndpointImpl endpoint = new EndpointImpl(executorService, "test-endpoint");
             try {
-                final Object requestObj = new Object();
-                final Object replyObj = new Object();
-                final Handle<RequestHandler> handle = endpoint.createLocalRequestHandler(new AbstractRequestListener<Object, Object>() {
-                    public void handleRequest(final RequestContext<Object> context, final Object request) throws RemoteExecutionException {
-                        assertEquals(request, requestObj);
-                        try {
-                            context.sendReply(replyObj);
-                        } catch (IOException e) {
-                            log.error(e, "Error sending reply!");
-                        }
-                    }
-                }, Object.class, Object.class);
-                try {
-                    final RequestHandler requestHandler = handle.getResource();
-                    try {
-                        requestHandler.addCloseHandler(new CloseHandler<RequestHandler>() {
-                            public void handleClose(final RequestHandler closed) {
-                                clientEndpointClosed.set(true);
-                            }
-                        });
-                        final Client<Object,Object> client = endpoint.createClient(requestHandler, Object.class, Object.class);
-                        try {
-                            client.addCloseHandler(new CloseHandler<Client<Object, Object>>() {
-                                public void handleClose(final Client<Object, Object> closed) {
-                                    clientClosed.set(true);
-                                }
-                            });
-                            handle.close();
-                            final IoFuture<? extends Object> futureReply = client.send(requestObj);
-                            assertEquals(IoFuture.Status.DONE, futureReply.await(1L, TimeUnit.SECONDS));
-                            assertEquals(replyObj, futureReply.get());
-                            client.close();
-                            executorService.shutdown();
-                            assertTrue(executorService.awaitTermination(1L, TimeUnit.SECONDS));
-                            assertTrue(clientEndpointClosed.get());
-                            assertTrue(clientClosed.get());
-                        } finally {
-                            IoUtils.safeClose(client);
-                        }
-                    } finally {
-                        IoUtils.safeClose(requestHandler);
-                    }
-                } finally {
-                    IoUtils.safeClose(handle);
-                }
             } finally {
                 IoUtils.safeClose(endpoint);
             }
@@ -182,30 +86,6 @@
         try {
             final EndpointImpl endpoint = new EndpointImpl(executorService, "test-endpoint");
             try {
-                final Object requestObj = new Object();
-                final Handle<RequestHandler> handle = endpoint.createLocalRequestHandler(new AbstractRequestListener<Object, Object>() {
-                    public void handleRequest(final RequestContext<Object> context, final Object request) throws RemoteExecutionException {
-                        assertEquals(request, requestObj);
-                        // don't send a reply!!
-                    }
-                }, Object.class, Object.class);
-                try {
-                    final RequestHandler requestHandler = handle.getResource();
-                    try {
-                        final Client<Object,Object> client = endpoint.createClient(requestHandler, Object.class, Object.class);
-                        try {
-                            final IoFuture<? extends Object> futureReply = client.send(requestObj);
-                            assertEquals(IoFuture.Status.FAILED, futureReply.await(500L, TimeUnit.MILLISECONDS));
-                            assertTrue(futureReply.getException() instanceof IndeterminateOutcomeException);
-                        } finally {
-                            IoUtils.safeClose(client);
-                        }
-                    } finally {
-                        IoUtils.safeClose(requestHandler);
-                    }
-                } finally {
-                    IoUtils.safeClose(handle);
-                }
             } finally {
                 IoUtils.safeClose(endpoint);
             }
@@ -219,50 +99,6 @@
         try {
             final EndpointImpl endpoint = new EndpointImpl(executorService, "test-endpoint");
             try {
-                final Object requestObj = new Object();
-                final Handle<RequestHandler> handle = endpoint.createLocalRequestHandler(new AbstractRequestListener<Object, Object>() {
-                    public void handleRequest(final RequestContext<Object> context, final Object request) throws RemoteExecutionException {
-                        assertEquals(request, requestObj);
-                        context.execute(new Runnable() {
-                            public void run() {
-                                context.execute(new Runnable() {
-                                    public void run() {
-                                        context.execute(new Runnable() {
-                                            public void run() {
-                                            }
-                                        });
-                                    }
-                                });
-                                context.execute(new Runnable() {
-                                    public void run() {
-                                    }
-                                });
-                            }
-                        });
-                        context.execute(new Runnable() {
-                            public void run() {
-                            }
-                        });
-                        // don't send a reply!!
-                    }
-                }, Object.class, Object.class);
-                try {
-                    final RequestHandler requestHandler = handle.getResource();
-                    try {
-                        final Client<Object,Object> client = endpoint.createClient(requestHandler, Object.class, Object.class);
-                        try {
-                            final IoFuture<? extends Object> futureReply = client.send(requestObj);
-                            assertEquals(IoFuture.Status.FAILED, futureReply.await(500L, TimeUnit.MILLISECONDS));
-                            assertTrue(futureReply.getException() instanceof IndeterminateOutcomeException);
-                        } finally {
-                            IoUtils.safeClose(client);
-                        }
-                    } finally {
-                        IoUtils.safeClose(requestHandler);
-                    }
-                } finally {
-                    IoUtils.safeClose(handle);
-                }
             } finally {
                 IoUtils.safeClose(endpoint);
             }

Modified: remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/spi/CloseableTestCase.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/spi/CloseableTestCase.java	2009-04-30 22:49:46 UTC (rev 5098)
+++ remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/spi/CloseableTestCase.java	2009-04-30 22:50:24 UTC (rev 5099)
@@ -46,7 +46,7 @@
         try {
             final AtomicBoolean closed = new AtomicBoolean();
             final CountDownLatch latch = new CountDownLatch(1);
-            final AbstractHandleableCloseable<Object> closeable = new AbstractHandleableCloseable<Object>(executorService) {
+            final AbstractSimpleCloseable closeable = new AbstractSimpleCloseable(executorService) {
                 // empty
             };
             try {
@@ -75,12 +75,12 @@
         try {
             final AtomicBoolean closed = new AtomicBoolean();
             final CountDownLatch latch = new CountDownLatch(1);
-            final AbstractAutoCloseable<Object> closeable = new AbstractAutoCloseable<Object>(executorService) {
+            final AbstractAutoCloseable closeable = new AbstractAutoCloseable(executorService) {
                 // empty
             };
-            final Handle<Object> rootHandle = closeable.getHandle();
+            final Handle rootHandle = closeable.getHandle();
             try {
-                closeable.addCloseHandler(new CloseHandler<Object>() {
+                closeable.addCloseHandler(new CloseHandler() {
                     public void handleClose(final Object x) {
                         closed.set(true);
                         latch.countDown();
@@ -105,7 +105,7 @@
         try {
             final AtomicBoolean closed = new AtomicBoolean();
             final CountDownLatch latch = new CountDownLatch(1);
-            final AbstractAutoCloseable<Object> closeable = new AbstractAutoCloseable<Object>(executorService) {
+            final AbstractAutoCloseable closeable = new AbstractAutoCloseable(executorService) {
                 // empty
             };
             final Handle<Object> rootHandle = closeable.getHandle();
@@ -141,7 +141,7 @@
         try {
             final AtomicBoolean closed = new AtomicBoolean();
             final CountDownLatch latch = new CountDownLatch(1);
-            final AbstractAutoCloseable<Object> closeable = new AbstractAutoCloseable<Object>(executorService) {
+            final AbstractAutoCloseable closeable = new AbstractAutoCloseable(executorService) {
                 // empty
             };
             final Handle<Object> rootHandle = closeable.getHandle();
@@ -183,7 +183,7 @@
     public void testHandlerRemoval() throws Throwable {
         final AtomicBoolean handlerCalled = new AtomicBoolean();
         final Executor executor = IoUtils.directExecutor();
-        final AbstractAutoCloseable<Object> closeable = new AbstractAutoCloseable<Object>(executor) {
+        final AbstractAutoCloseable closeable = new AbstractAutoCloseable(executor) {
             // empty
         };
         final Handle<Object> rootHandle = closeable.getHandle();




More information about the jboss-remoting-commits mailing list