[jboss-remoting-commits] JBoss Remoting SVN: r5755 - in remoting3/trunk: compat/src/main/java/org/jboss/remoting3/compat and 15 other directories.

jboss-remoting-commits at lists.jboss.org jboss-remoting-commits at lists.jboss.org
Tue Feb 23 18:49:42 EST 2010


Author: david.lloyd at jboss.com
Date: 2010-02-23 18:49:39 -0500 (Tue, 23 Feb 2010)
New Revision: 5755

Added:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Attachable.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Attachments.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AttachmentsImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ConnectionImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalConnectionHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalConnectionProvider.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemoteClassTable.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RequestHandlerFactory.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationInfo.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/InetAddressPrincipal.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/RemotingPermission.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/SimpleClientCallbackHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/Services.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/ClassLookupRequest.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/ClassLookupResponse.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/package-info.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/ServiceReply.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/ServiceRequest.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/package-info.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/package-info.java
   remoting3/trunk/jboss-remoting/src/test/resources/
   remoting3/trunk/jboss-remoting/src/test/resources/logging.properties
Removed:
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointPermission.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/SimpleCloseable.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractSimpleCloseable.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RemoteRequestContext.java
Modified:
   remoting3/trunk/compat/src/main/java/org/jboss/remoting3/compat/UnwrappingRequestHandler.java
   remoting3/trunk/compat/src/main/java/org/jboss/remoting3/compat/WrappingRequestHandler.java
   remoting3/trunk/jboss-remoting/pom.xml
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnectorImpl.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/Connection.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/FutureReplyImpl.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Registration.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Remoting.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationListener.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceURI.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/TypedRequest.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Version.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/ConnectionHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandlerContext.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/RequestHandler.java
   remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/SpiUtils.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
   remoting3/trunk/pom.xml
   remoting3/trunk/samples/pom.xml
   remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/client/SocketClientConnectionHandler.java
   remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/client/SocketClientRequestHandler.java
   remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/server/SocketServerConnectionHandler.java
   remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/server/SocketServerRequestHandler.java
   remoting3/trunk/taglet/pom.xml
Log:
Move to slot-based service location; update samples to reflect change

Modified: remoting3/trunk/compat/src/main/java/org/jboss/remoting3/compat/UnwrappingRequestHandler.java
===================================================================
--- remoting3/trunk/compat/src/main/java/org/jboss/remoting3/compat/UnwrappingRequestHandler.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/compat/src/main/java/org/jboss/remoting3/compat/UnwrappingRequestHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -23,10 +23,10 @@
 package org.jboss.remoting3.compat;
 
 import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.RemoteRequestContext;
 import org.jboss.remoting3.spi.ReplyHandler;
-import org.jboss.remoting3.spi.SpiUtils;
 import org.jboss.remoting3.RemoteRequestException;
+import org.jboss.xnio.Cancellable;
+import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.log.Logger;
 import java.util.concurrent.Executor;
 import java.util.Map;
@@ -53,7 +53,7 @@
         this.next = next;
     }
 
-    public RemoteRequestContext receiveRequest(final Object request, final ReplyHandler replyHandler) {
+    public Cancellable receiveRequest(final Object request, final ReplyHandler replyHandler) {
         if (request instanceof CompatabilityInvocationRequest) {
             final CompatabilityInvocationRequest invocationRequest = (CompatabilityInvocationRequest) request;
             final Map<Object,Object> map = invocationRequest.getRequestPayload();
@@ -69,7 +69,7 @@
                 log.error(e, "Failed to forward an exception to the requesting party");
                 log.error(nex, "The original exception follows");
             }
-            return SpiUtils.getBlankRemoteRequestContext();
+            return IoUtils.nullCancellable();
         }
     }
 }

Modified: remoting3/trunk/compat/src/main/java/org/jboss/remoting3/compat/WrappingRequestHandler.java
===================================================================
--- remoting3/trunk/compat/src/main/java/org/jboss/remoting3/compat/WrappingRequestHandler.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/compat/src/main/java/org/jboss/remoting3/compat/WrappingRequestHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -23,9 +23,9 @@
 package org.jboss.remoting3.compat;
 
 import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.RemoteRequestContext;
 import org.jboss.remoting3.spi.ReplyHandler;
 import java.util.concurrent.Executor;
+import org.jboss.xnio.Cancellable;
 
 /**
  * A request handler which wraps a Remoting 3-style plain request (or an instance of {@link org.jboss.remoting3.compat.Request Request}
@@ -40,7 +40,7 @@
         this.next = next;
     }
 
-    public RemoteRequestContext receiveRequest(final Object obj, final ReplyHandler replyHandler) {
+    public Cancellable receiveRequest(final Object obj, final ReplyHandler replyHandler) {
         final CompatabilityInvocationRequest cir = new CompatabilityInvocationRequest();
         if (obj instanceof Request) {
             final Request request = (Request) obj;

Modified: remoting3/trunk/jboss-remoting/pom.xml
===================================================================
--- remoting3/trunk/jboss-remoting/pom.xml	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/pom.xml	2010-02-23 23:49:39 UTC (rev 5755)
@@ -29,6 +29,10 @@
     <name>JBoss Remoting</name>
     <description>JBoss Remoting</description>
 
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
     <groupId>org.jboss.remoting</groupId>
     <artifactId>jboss-remoting</artifactId>
     <packaging>jar</packaging>
@@ -43,7 +47,7 @@
         <dependency>
             <groupId>org.jboss.marshalling</groupId>
             <artifactId>marshalling-api</artifactId>
-            <version>1.2.0.CR5-SNAPSHOT</version>
+            <version>1.3.0.CR1-SNAPSHOT</version>
             <scope>compile</scope>
         </dependency>
         <dependency>
@@ -52,11 +56,30 @@
             <version>3.8.2</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.jboss.logmanager</groupId>
+            <artifactId>jboss-logmanager</artifactId>
+            <version>1.1.1.GA</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
     <build>
         <plugins>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <forkMode>always</forkMode>
+                    <systemProperties>
+                        <property>
+                            <name>java.util.logging.manager</name>
+                            <value>org.jboss.logmanager.LogManager</value>
+                        </property>
+                    </systemProperties>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-compiler-plugin</artifactId>
                 <version>2.0.2</version>
                 <configuration>
@@ -77,6 +100,32 @@
                 </executions>
             </plugin>
             <plugin>
+                <groupId>org.jboss.maven.plugins</groupId>
+                <artifactId>maven-injection-plugin</artifactId>
+                <version>1.0.2</version>
+                <executions>
+                    <execution>
+                        <phase>compile</phase>
+                        <goals>
+                            <goal>bytecode</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <bytecodeInjections>
+                        <bytecodeInjection>
+                            <expression>${version}</expression>
+                            <targetMembers>
+                                <methodBodyReturn>
+                                    <className>org.jboss.remoting3.Version</className>
+                                    <methodName>getVersionString</methodName>
+                                </methodBodyReturn>
+                            </targetMembers>
+                        </bytecodeInjection>
+                    </bytecodeInjections>
+                </configuration>
+            </plugin>
+            <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-javadoc-plugin</artifactId>
                 <version>2.6.1</version>

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Attachable.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Attachable.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Attachable.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,36 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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;
+
+/**
+ * An entity which can hold attachments.
+ */
+public interface Attachable {
+
+    /**
+     * Get the attachments for this entity.
+     *
+     * @return the attachments
+     */
+    Attachments getAttachments();
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Attachments.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Attachments.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Attachments.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,61 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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;
+
+/**
+ *
+ */
+public interface Attachments {
+
+    /**
+     * Attach a value to this object.
+     *
+     * @param key the attachment key
+     * @param value the attachment value
+     * @param <T> the type of the attachment
+     * @returns the old value, if any
+     */
+    <T> T attach(Key<T> key, T value);
+
+    <T> T attachIfAbsent(Key<T> key, T value);
+
+    <T> boolean replaceAttachment(Key<T> key, T expect, T replacement);
+
+    <T> T removeAttachment(Key<T> key);
+
+    <T> boolean removeAttachment(Key<T> key, T value);
+
+    <T> T getAttachment(Key<T> key);
+
+    final class Key<T> {
+        private final Class<T> type;
+
+        public Key(final Class<T> type) {
+            this.type = type;
+        }
+
+        public Class<T> getType() {
+            return type;
+        }
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AttachmentsImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AttachmentsImpl.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/AttachmentsImpl.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.IdentityHashMap;
+import java.util.Map;
+
+final class AttachmentsImpl implements Attachments {
+    private final Map<Key<?>, Object> map = new IdentityHashMap<Key<?>, Object>();
+
+    public <T> T attach(final Key<T> key, final T value) {
+        final Map<Key<?>, Object> map = this.map;
+        synchronized (map) {
+            final Class<T> type = key.getType();
+            return type.cast(map.put(key, type.cast(value)));
+        }
+    }
+
+    public <T> T attachIfAbsent(final Key<T> key, final T value) {
+        final Map<Key<?>, Object> map = this.map;
+        synchronized (map) {
+            final Object old = map.get(key);
+            if (old != null) {
+                return key.getType().cast(old);
+            } else {
+                map.put(key, key.getType().cast(value));
+                return null;
+            }
+        }
+    }
+
+    public <T> boolean replaceAttachment(final Key<T> key, final T expect, final T replacement) {
+        final Map<Key<?>, Object> map = this.map;
+        synchronized (map) {
+            final Object old = map.get(key);
+            if (expect == old || expect != null && expect.equals(old)) {
+                map.put(key, key.getType().cast(replacement));
+                return true;
+            } else {
+                return false;
+            }
+        }
+    }
+
+    public <T> T removeAttachment(final Key<T> key) {
+        final Map<Key<?>, Object> map = this.map;
+        synchronized (map) {
+            return key.getType().cast(map.remove(key));
+        }
+    }
+
+    public <T> boolean removeAttachment(final Key<T> key, final T value) {
+        final Map<Key<?>, Object> map = this.map;
+        synchronized (map) {
+            final Object old = map.get(key);
+            if (value == old || value != null && value.equals(old)) {
+                map.remove(key);
+                return false;
+            }
+            return true;
+        }
+    }
+
+    public <T> T getAttachment(final Key<T> key) {
+        final Map<Key<?>, Object> map = this.map;
+        synchronized (map) {
+            return key.getType().cast(map.get(key));
+        }
+    }
+}

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Client.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -39,7 +39,7 @@
  *
  * @apiviz.landmark
  */
-public interface Client<I, O> extends HandleableCloseable<Client<I, O>> {
+public interface Client<I, O> extends HandleableCloseable<Client<I, O>>, Attachable {
     /**
      * Send a request and block until a reply is received.  If the remote side manipulates a stream, the
      * current thread may be used to handle it.

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnectorImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnectorImpl.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientConnectorImpl.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -68,6 +68,4 @@
         }
         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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContext.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -29,12 +29,12 @@
  *
  * @apiviz.exclude
  */
-public interface ClientContext extends HandleableCloseable<ClientContext> {
+public interface ClientContext extends HandleableCloseable<ClientContext>, Attachable {
 
     /**
-     * Get the connection associated with this client context.
+     * Get the connection associated with this client context.  If the client is local, {@code null} is returned.
      *
-     * @return the connection
+     * @return the connection, or {@code null} if there is none
      */
     Connection getConnection();
 

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientContextImpl.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -34,6 +34,7 @@
     @SuppressWarnings({ "UnusedDeclaration" })
     private static final Logger log = Logger.getLogger("org.jboss.remoting.client-context");
 
+    private final Attachments attachments = new AttachmentsImpl();
     private final Connection connection;
 
     ClientContextImpl(final Executor executor, final Connection connection) {
@@ -41,6 +42,10 @@
         this.connection = connection;
     }
 
+    public Attachments getAttachments() {
+        return attachments;
+    }
+
     protected Executor getExecutor() {
         return super.getExecutor();
     }

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ClientImpl.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -25,10 +25,10 @@
 import java.io.IOException;
 import java.util.concurrent.Executor;
 import java.util.concurrent.CancellationException;
-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.Cancellable;
 import org.jboss.xnio.IoFuture;
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.log.Logger;
@@ -43,6 +43,7 @@
     private final RequestHandler handler;
     private final Class<I> requestClass;
     private final Class<O> replyClass;
+    private final Attachments attachments = new AttachmentsImpl();
 
     private ClientImpl(final RequestHandler handler, final Executor executor, final Class<I> requestClass, final Class<O> replyClass) {
         super(executor);
@@ -61,6 +62,10 @@
         return ci;
     }
 
+    public Attachments getAttachments() {
+        return attachments;
+    }
+
     protected void closeAction() throws IOException {
         handler.close();
     }
@@ -78,7 +83,7 @@
        final QueueExecutor executor = new QueueExecutor();
        final FutureReplyImpl<T> futureReply = new FutureReplyImpl<T>(executor, replyClass);
        final ReplyHandler replyHandler = futureReply.getReplyHandler();
-       final RemoteRequestContext requestContext = handler.receiveRequest(actualRequest, replyHandler);
+       final Cancellable requestContext = handler.receiveRequest(actualRequest, replyHandler);
        futureReply.setRemoteRequestContext(requestContext);
        futureReply.addNotifier(IoUtils.attachmentClosingNotifier(), executor);
        executor.runQueue();
@@ -97,7 +102,30 @@
     }
 
     public <T extends O> T invokeTyped(final TypedRequest<? extends I, T> typedRequest) throws IOException, CancellationException {
-        return invoke(requestClass.cast(typedRequest), typedRequest.getReplyClass());
+        if (! isOpen()) {
+            throw new IOException("Client is not open");
+        }
+        log.trace("Client.invoke() sending request \"%s\"", typedRequest);
+        final I actualRequest = castRequest(typedRequest);
+        final QueueExecutor executor = new QueueExecutor();
+        final FutureReplyImpl<T> futureReply = new FutureReplyImpl<T>(executor, typedRequest);
+        final ReplyHandler replyHandler = futureReply.getReplyHandler();
+        final Cancellable requestContext = handler.receiveRequest(actualRequest, replyHandler);
+        futureReply.setRemoteRequestContext(requestContext);
+        futureReply.addNotifier(IoUtils.attachmentClosingNotifier(), executor);
+        executor.runQueue();
+        try {
+            final T reply = futureReply.getInterruptibly();
+            log.trace("Client.invoke() received reply \"%s\"", reply);
+            return reply;
+        } catch (InterruptedException e) {
+            try {
+                futureReply.cancel();
+                throw new IndeterminateOutcomeException("The current thread was interrupted before the result could be read");
+            } finally {
+                Thread.currentThread().interrupt();
+            }
+        }
     }
 
     public IoFuture<? extends O> send(final I request) throws IOException {
@@ -112,13 +140,22 @@
         final I actualRequest = castRequest(request);
         final FutureReplyImpl<T> futureReply = new FutureReplyImpl<T>(getExecutor(), replyClass);
         final ReplyHandler replyHandler = futureReply.getReplyHandler();
-        final RemoteRequestContext requestContext = handler.receiveRequest(actualRequest, replyHandler);
+        final Cancellable requestContext = handler.receiveRequest(actualRequest, replyHandler);
         futureReply.setRemoteRequestContext(requestContext);
         return futureReply;
     }
 
     public <T extends O> IoFuture<? extends T> sendTyped(final TypedRequest<? extends I, T> typedRequest) throws IOException {
-        return send(requestClass.cast(typedRequest), typedRequest.getReplyClass());
+        if (! isOpen()) {
+            throw new IOException("Client is not open");
+        }
+        log.trace("Client.send() sending request \"%s\"", typedRequest);
+        final I actualRequest = castRequest(typedRequest);
+        final FutureReplyImpl<T> futureReply = new FutureReplyImpl<T>(getExecutor(), typedRequest);
+        final ReplyHandler replyHandler = futureReply.getReplyHandler();
+        final Cancellable requestContext = handler.receiveRequest(actualRequest, replyHandler);
+        futureReply.setRemoteRequestContext(requestContext);
+        return futureReply;
     }
 
     /**

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Connection.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Connection.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Connection.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -24,17 +24,43 @@
 
 import org.jboss.xnio.IoFuture;
 import java.io.IOException;
+import org.jboss.xnio.OptionMap;
 
 /**
  * A connection to a remote peer.
  * <p/>
  * @remoting.consume
  */
-public interface Connection extends HandleableCloseable<Connection> {
+public interface Connection extends HandleableCloseable<Connection>, Attachable {
 
     /**
-     * Open a client on the remote side of this connection.
+     * Open a client to a well-known service on the remote endpoint via this connection.
      *
+     * @param serviceSlot the service slot to connect to
+     * @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(int serviceSlot, Class<I> requestClass, Class<O> replyClass);
+
+    /**
+     * Open a client to a well-known service on the remote endpoint via this connection.
+     *
+     * @param serviceSlot the service slot to connect to
+     * @param requestClass the request class
+     * @param replyClass the reply class
+     * @param optionMap the option map
+     * @param <I> the request type
+     * @param <O> the reply type
+     * @return the future client
+     */
+    <I, O> IoFuture<? extends Client<I, O>> openClient(int serviceSlot, Class<I> requestClass, Class<O> replyClass, OptionMap optionMap);
+
+    /**
+     * Locate and 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
@@ -46,6 +72,20 @@
     <I, O> IoFuture<? extends Client<I, O>> openClient(String serviceType, String groupName, Class<I> requestClass, Class<O> replyClass);
 
     /**
+     * Locate and 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 optionMap the option map
+     * @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, OptionMap optionMap);
+
+    /**
      * Create a client connector which may <b>only</b> transmitted to the remote side of this connection, allowing
      * it to use the included service.
      *
@@ -57,4 +97,18 @@
      * @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;
+
+    /**
+     * 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 optionMap the option map
+     * @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, OptionMap optionMap) throws IOException;
 }

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ConnectionImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ConnectionImpl.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ConnectionImpl.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,186 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.net.URI;
+import org.jboss.remoting3.security.RemotingPermission;
+import org.jboss.remoting3.service.Services;
+import org.jboss.remoting3.service.locator.ServiceReply;
+import org.jboss.remoting3.service.locator.ServiceRequest;
+import org.jboss.remoting3.spi.AbstractHandleableCloseable;
+import org.jboss.remoting3.spi.ConnectionHandler;
+import org.jboss.remoting3.spi.ConnectionHandlerFactory;
+import org.jboss.remoting3.spi.ConnectionProviderContext;
+import org.jboss.remoting3.spi.RequestHandler;
+import org.jboss.remoting3.spi.RequestHandlerConnector;
+import org.jboss.xnio.FailedIoFuture;
+import org.jboss.xnio.FutureResult;
+import org.jboss.xnio.IoFuture;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.TranslatingResult;
+
+class ConnectionImpl extends AbstractHandleableCloseable<Connection> implements Connection {
+
+    private final Attachments attachments = new AttachmentsImpl();
+
+    private final EndpointImpl endpoint;
+    private final ConnectionHandler connectionHandler;
+    private final IoFuture<? extends Client<ServiceRequest, ServiceReply>> serviceLocator;
+    private final String name;
+
+    ConnectionImpl(final EndpointImpl endpoint, final ConnectionHandlerFactory connectionHandlerFactory, final ConnectionProviderContext connectionProviderContext, final String name) {
+        super(endpoint.getExecutor());
+        this.endpoint = endpoint;
+        this.name = name;
+        connectionHandler = connectionHandlerFactory.createInstance(endpoint.new LocalConnectionContext(connectionProviderContext, this));
+        serviceLocator = doOpenClient(Services.LOCATE_SERVICE, ServiceRequest.class, ServiceReply.class);
+    }
+
+    protected void closeAction() throws IOException {
+        connectionHandler.close();
+    }
+
+    public <I, O> IoFuture<? extends Client<I, O>> openClient(final int serviceSlot, final Class<I> requestClass, final Class<O> replyClass) {
+        return openClient(serviceSlot, requestClass, replyClass, OptionMap.EMPTY);
+    }
+
+    public <I, O> IoFuture<? extends Client<I, O>> openClient(final int serviceSlot, final Class<I> requestClass, final Class<O> replyClass, final OptionMap optionMap) {
+        final SecurityManager sm = System.getSecurityManager();
+        if (sm != null) {
+            sm.checkPermission(new RemotingPermission("openClientByID"));
+        }
+        return doOpenClient(serviceSlot, requestClass, replyClass);
+    }
+
+    private <I, O> IoFuture<? extends Client<I, O>> doOpenClient(final int serviceSlot, final Class<I> requestClass, final Class<O> replyClass) {
+        final FutureResult<Client<I, O>> futureResult = new FutureResult<Client<I, O>>();
+        futureResult.addCancelHandler(connectionHandler.open(serviceSlot, new ClientWrapper<I, O>(endpoint, futureResult, requestClass, replyClass)));
+        return futureResult.getIoFuture();
+    }
+
+    public <I, O> IoFuture<? extends Client<I, O>> openClient(final String serviceType, final String groupName, final Class<I> requestClass, final Class<O> replyClass) {
+        return openClient(serviceType, groupName, requestClass, replyClass, OptionMap.EMPTY);
+    }
+
+    public <I, O> IoFuture<? extends Client<I, O>> openClient(final String serviceType, final String groupName, final Class<I> requestClass, final Class<O> replyClass, final OptionMap optionMap) {
+        final Client<ServiceRequest, ServiceReply> locator;
+        try {
+            locator = serviceLocator.get();
+        } catch (IOException e) {
+            return new FailedIoFuture<Client<I, O>>(e);
+        }
+        final FutureResult<Client<I, O>> futureClientResult = new FutureResult<Client<I, O>>();
+        try {
+            final IoFuture<? extends ServiceReply<I, O>> futureServiceReply = locator.sendTyped(new ServiceRequest<I, O>(serviceType, groupName, requestClass, replyClass));
+            futureServiceReply.addNotifier(new ServiceReplyNotifier<I, O>(requestClass, replyClass), futureClientResult);
+            futureClientResult.addCancelHandler(futureServiceReply);
+        } catch (IOException e) {
+            return new FailedIoFuture<Client<I, O>>(e);
+        }
+        return futureClientResult.getIoFuture();
+    }
+
+    public <I, O> ClientConnector<I, O> createClientConnector(final RequestListener<I, O> listener, final Class<I> requestClass, final Class<O> replyClass) throws IOException {
+        return createClientConnector(listener, requestClass, replyClass, OptionMap.EMPTY);
+    }
+
+    public <I, O> ClientConnector<I, O> createClientConnector(final RequestListener<I, O> listener, final Class<I> requestClass, final Class<O> replyClass, final OptionMap optionMap) throws IOException {
+        final RequestHandler localRequestHandler = endpoint.createLocalRequestHandler(listener, requestClass, replyClass);
+        final RequestHandlerConnector connector = connectionHandler.createConnector(localRequestHandler);
+        final ClientContextImpl context = new ClientContextImpl(getExecutor(), this);
+        context.addCloseHandler(new CloseHandler<ClientContext>() {
+            public void handleClose(final ClientContext closed) {
+                IoUtils.safeClose(localRequestHandler);
+            }
+        });
+        return new ClientConnectorImpl<I, O>(connector, endpoint, requestClass, replyClass, context);
+    }
+
+    public Attachments getAttachments() {
+        return attachments;
+    }
+
+    public String toString() {
+        return "Connection to " + name;
+    }
+
+    private static class ClientWrapper<I, O> extends TranslatingResult<RequestHandler, Client<I, O>> {
+
+        private final Class<I> requestClass;
+        private final Class<O> replyClass;
+        private EndpointImpl endpoint;
+
+        public ClientWrapper(final EndpointImpl endpoint, final FutureResult<Client<I, O>> futureResult, final Class<I> requestClass, final Class<O> replyClass) {
+            super(futureResult);
+            this.requestClass = requestClass;
+            this.replyClass = replyClass;
+            this.endpoint = endpoint;
+        }
+
+        protected Client<I, O> translate(final RequestHandler input) throws IOException {
+            return endpoint.createClient(input, requestClass, replyClass);
+        }
+    }
+
+    private class ServiceReplyNotifier<I, O> extends IoFuture.HandlingNotifier<ServiceReply<I, O>, FutureResult<Client<I, O>>> {
+        private final Class<?> expectedRequestClass;
+        private final Class<?> expectedReplyClass;
+
+        private ServiceReplyNotifier(final Class<?> expectedRequestClass, final Class<?> expectedReplyClass) {
+            this.expectedRequestClass = expectedRequestClass;
+            this.expectedReplyClass = expectedReplyClass;
+        }
+
+        public void handleCancelled(final FutureResult<Client<I, O>> attachment) {
+            attachment.setCancelled();
+        }
+
+        public void handleFailed(final IOException exception, final FutureResult<Client<I, O>> attachment) {
+            if (exception instanceof RemoteExecutionException) {
+                final Throwable cause = exception.getCause();
+                if (cause instanceof IOException) {
+                    attachment.setException((IOException) cause);
+                    return;
+                }
+            }
+            attachment.setException(exception);
+        }
+
+        public void handleDone(final ServiceReply<I, O> data, final FutureResult<Client<I, O>> attachment) {
+            final Class<I> actualRequestClass = data.getActualRequestClass();
+            final Class<O> actualReplyClass = data.getActualReplyClass();
+            try {
+                actualRequestClass.asSubclass(expectedRequestClass);
+                expectedReplyClass.asSubclass(actualReplyClass);
+            } catch (ClassCastException e) {
+                attachment.setException(new ServiceOpenException("Incorrect type specified", e));
+                return;
+            }
+            final IoFuture<? extends Client<I, O>> futureClient = doOpenClient(data.getSlot(), actualRequestClass, actualReplyClass);
+            futureClient.addNotifier(IoUtils.<Client<I, O>>resultNotifier(), attachment);
+            attachment.addCancelHandler(futureClient);
+        }
+    }
+}

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Endpoint.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -21,7 +21,7 @@
  *
  * @apiviz.landmark
  */
-public interface Endpoint extends HandleableCloseable<Endpoint> {
+public interface Endpoint extends HandleableCloseable<Endpoint>, Attachable {
 
     /**
      * Get the name of this endpoint.
@@ -31,25 +31,22 @@
     String getName();
 
     /**
-     * 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 EndpointPermission createRequestHandler EndpointPermission} to invoke this method.
+     * Get a new service builder which can be used to register a service.
      *
-     * @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 the request handler
-     * @throws IOException if an error occurs
+     * @return a new service builder
      */
-    <I, O> RequestHandler createLocalRequestHandler(RequestListener<? super I, ? extends O> requestListener, Class<I> requestClass, Class<O> replyClass) throws IOException;
+    ServiceBuilder<?, ?> serviceBuilder();
 
     /**
      * Get a new service builder which can be used to register a service.
      *
+     * @param requestClass the request class
+     * @param replyClass the reply class
+     * @param <I> the request type
+     * @param <O> the reply type
      * @return a new service builder
      */
-    ServiceBuilder<?, ?> serviceBuilder();
+    <I, O> ServiceBuilder<I, O> serviceBuilder(Class<I> requestClass, Class<O> replyClass);
 
     /**
      * A service builder for new service registration.
@@ -132,7 +129,7 @@
         /**
          * Register the service.
          * <p/>
-         * You must have the {@link EndpointPermission registerService EndpointPermission} to invoke this method.
+         * You must have the {@link org.jboss.remoting3.security.RemotingPermission registerService EndpointPermission} to invoke this method.
          *
          * @return a registration handle
          * @throws IOException if a problem occurs with registration
@@ -143,7 +140,7 @@
     /**
      * Add a service registration listener which is called whenever a local service is registered.
      * <p/>
-     * You must have the {@link EndpointPermission addServiceListener EndpointPermission} to invoke this method.
+     * You must have the {@link org.jboss.remoting3.security.RemotingPermission addServiceListener EndpointPermission} to invoke this method.
      *
      * @param listener the listener
      * @param flags the flags to apply to the listener
@@ -152,9 +149,25 @@
     Registration addServiceRegistrationListener(ServiceRegistrationListener listener, Set<ListenerFlag> flags);
 
     /**
+     * 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.security.RemotingPermission createRequestHandler EndpointPermission} to invoke this method.
+     *
+     * @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
+     * @param <I> the request type
+     * @param <O> the reply type
+     * @return the request handler
+     * @throws IOException if an error occurs
+     */
+    <I, O> RequestHandler createLocalRequestHandler(RequestListener<? super I, ? extends O> requestListener, Class<I> requestClass, Class<O> replyClass) throws IOException;
+
+    /**
      * Create a client that uses the given request handler to handle its requests.
      * <p/>
-     * You must have the {@link EndpointPermission createClient EndpointPermission} to invoke this method.
+     * You must have the {@link org.jboss.remoting3.security.RemotingPermission createClient EndpointPermission} to invoke this method.
      *
      * @param <I> the request type
      * @param <O> the reply type
@@ -170,7 +183,7 @@
      * Open a connection with a peer.  Returns a future connection which may be used to cancel the connection attempt.
      * This method does not block; use the return value to wait for a result if you wish to block.
      * <p/>
-     * You must have the {@link EndpointPermission connect EndpointPermission} to invoke this method.
+     * You must have the {@link org.jboss.remoting3.security.RemotingPermission connect EndpointPermission} to invoke this method.
      *
      * @param destination the destination
      * @param connectOptions options to configure this connection
@@ -184,7 +197,7 @@
      * The given callback handler is used to retrieve local authentication information, if the protocol demands it.
      * This method does not block; use the return value to wait for a result if you wish to block.
      * <p/>
-     * You must have the {@link EndpointPermission connect EndpointPermission} to invoke this method.
+     * You must have the {@link org.jboss.remoting3.security.RemotingPermission connect EndpointPermission} to invoke this method.
      *
      * @param destination the destination
      * @param connectOptions options to configure this connection
@@ -196,16 +209,17 @@
 
     /**
      * Open a connection with a peer.  Returns a future connection which may be used to cancel the connection attempt.
-     * The given user name and password is used as retrieve local authentication information, if the protocol demands it.
+     * The given user name and password is used as local authentication information, if the protocol demands it.
      * This method does not block; use the return value to wait for a result if you wish to block.
      * <p/>
-     * You must have the {@link EndpointPermission connect EndpointPermission} to invoke this method.
+     * You must have the {@link org.jboss.remoting3.security.RemotingPermission connect EndpointPermission} to invoke this method.
      *
      * @param destination the destination
      * @param connectOptions options to configure this connection
      * @param userName the user name to authenticate as, or {@code null} if it is unspecified
      * @param realmName the user realm to authenticate with, or {@code null} if it is unspecified
-     * @param password the password to send  @return the future connection, or {@code null} if it is unspecified
+     * @param password the password to send, or {@code null} if it is unspecified
+     * @return the future connection
      * @throws IOException if an error occurs while starting the connect attempt
      */
     IoFuture<? extends Connection> connect(URI destination, OptionMap connectOptions, String userName, String realmName, char[] password) throws IOException;
@@ -214,7 +228,7 @@
      * 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.
      * <p/>
-     * You must have the {@link EndpointPermission addConnectionProvider EndpointPermission} to invoke this method.
+     * You must have the {@link org.jboss.remoting3.security.RemotingPermission addConnectionProvider EndpointPermission} to invoke this method.
      *
      * @param uriScheme the URI scheme
      * @param providerFactory the provider factory
@@ -226,7 +240,7 @@
     /**
      * Get the interface for a connection provider.
      * <p/>
-     * You must have the {@link EndpointPermission getConnectionProviderInterface EndpointPermission} to invoke this method.
+     * You must have the {@link org.jboss.remoting3.security.RemotingPermission getConnectionProviderInterface EndpointPermission} to invoke this method.
      *
      * @param uriScheme the URI scheme of the registered connection provider
      * @param expectedType the expected type of the interface

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointImpl.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -31,43 +31,38 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Queue;
+import java.util.Random;
 import java.util.Set;
 import java.util.Iterator;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.Executor;
-import java.util.concurrent.atomic.AtomicReference;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.jboss.marshalling.util.IntKeyMap;
+import org.jboss.remoting3.security.RemotingPermission;
+import org.jboss.remoting3.security.SimpleClientCallbackHandler;
+import org.jboss.remoting3.service.Services;
+import org.jboss.remoting3.service.locator.ServiceReply;
+import org.jboss.remoting3.service.locator.ServiceRequest;
 import org.jboss.remoting3.spi.AbstractHandleableCloseable;
-import org.jboss.remoting3.spi.ConnectionHandler;
 import org.jboss.remoting3.spi.ConnectionHandlerFactory;
 import org.jboss.remoting3.spi.ConnectionProvider;
 import org.jboss.remoting3.spi.ConnectionProviderContext;
 import org.jboss.remoting3.spi.ConnectionProviderFactory;
 import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.remoting3.spi.RequestHandlerConnector;
 import org.jboss.remoting3.spi.ConnectionProviderRegistration;
 import org.jboss.remoting3.spi.ConnectionHandlerContext;
 import org.jboss.remoting3.spi.ProtocolServiceType;
 import org.jboss.xnio.log.Logger;
-import org.jboss.xnio.Cancellable;
-import org.jboss.xnio.FailedIoFuture;
-import org.jboss.xnio.FinishedIoFuture;
 import org.jboss.xnio.FutureResult;
 import org.jboss.xnio.IoFuture;
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.OptionMap;
-import org.jboss.xnio.Result;
 import org.jboss.xnio.TranslatingResult;
 import org.jboss.xnio.WeakCloseable;
 
 import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.TextOutputCallback;
-import javax.security.sasl.RealmCallback;
-import javax.security.sasl.RealmChoiceCallback;
 
 /**
  *
@@ -113,25 +108,27 @@
 
     private static final Logger log = Logger.getLogger("org.jboss.remoting.endpoint");
 
+    private final Attachments attachments = new AttachmentsImpl();
+
     /**
      * The name of this endpoint.
      */
     private final String name;
 
-    /**
-     * Snapshot lock.  Hold this lock while reading or updating {@link #serviceListenerRegistrations} or while updating
-     * {@link #registeredLocalServices}.  Allows atomic snapshot of existing service registrations and listener add.
-     */
-    private final Object serviceRegistrationLock = new Object();
+    private final OptionMap optionMap;
 
+    private final Lock serviceWriteLock;
+    private final Lock serviceReadLock;
+
     /**
-     * The currently registered service listeners.  Protected by {@link #serviceRegistrationLock}.
+     * The currently registered service listeners.  Protected by {@link #serviceWriteLock}.
      */
-    private final ConcurrentMap<Registration, ServiceRegistrationListener> serviceListenerRegistrations = concurrentIdentityMap(serviceRegistrationLock);
+    private final Map<Registration, ServiceRegistrationListener> serviceListenerRegistrations = hashMap();
     /**
-     * The currently registered services.  Protected by {@link #serviceRegistrationLock}.
+     * The currently registered services.  Protected by {@link #serviceWriteLock}.
      */
-    private final ConcurrentMap<String, ConcurrentMap<String, ServiceRegistration>> registeredLocalServices = concurrentMap(serviceRegistrationLock);
+    private final Map<String, Map<String, ServiceRegistrationInfo>> localServiceIndex = hashMap();
+    private final IntKeyMap<ServiceRegistrationInfo> localServiceTable = new IntKeyMap<ServiceRegistrationInfo>();
     /**
      * The currently registered connection providers.
      */
@@ -140,46 +137,41 @@
      * The provider maps for the different protocol service types.
      */
     private final ConcurrentMap[] providerMaps = new ConcurrentMap[ProtocolServiceType.getServiceTypes().length];
-
     /**
      * The single per-endpoint connection provider context instance.
      */
     private final ConnectionProviderContext connectionProviderContext;
-    /**
-     * The special connection handler instance corresponding to {@link #loopbackConnection}.
-     */
-    private final ConnectionHandler loopbackConnectionHandler;
-    /**
-     * The special loopback connection instance for local request handlers which are created via {@link #createLocalRequestHandler(RequestListener, Class, Class)} and
-     * not tied to a service.  This connection cannot be closed.
-     */
-    private final Connection loopbackConnection;
-    /**
-     * The special connection handler context corresponding to {@link #loopbackConnectionHandler}.
-     */
-    private final ConnectionHandlerContext localConnectionContext;
 
-    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 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");
-    private static final EndpointPermission ADD_MARSHALLING_PROTOCOL_PERM = new EndpointPermission("addMarshallingProtocol");
-    private static final EndpointPermission GET_CONNECTION_PROVIDER_INTERFACE_PERM = new EndpointPermission("getConnectionProviderInterface");
+    private static final RemotingPermission CREATE_REQUEST_HANDLER_PERM = new RemotingPermission("createRequestHandler");
+    private static final RemotingPermission REGISTER_SERVICE_PERM = new RemotingPermission("registerService");
+    private static final RemotingPermission CREATE_CLIENT_PERM = new RemotingPermission("createClient");
+    private static final RemotingPermission ADD_SERVICE_LISTENER_PERM = new RemotingPermission("addServiceListener");
+    private static final RemotingPermission CONNECT_PERM = new RemotingPermission("connect");
+    private static final RemotingPermission ADD_CONNECTION_PROVIDER_PERM = new RemotingPermission("addConnectionProvider");
+    private static final RemotingPermission ADD_MARSHALLING_PROTOCOL_PERM = new RemotingPermission("addMarshallingProtocol");
+    private static final RemotingPermission GET_CONNECTION_PROVIDER_INTERFACE_PERM = new RemotingPermission("getConnectionProviderInterface");
 
-    EndpointImpl(final Executor executor, final String name) {
+    EndpointImpl(final Executor executor, final String name, final OptionMap optionMap) throws IOException {
         super(executor);
+        final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+        serviceWriteLock = rwl.writeLock();
+        serviceReadLock = rwl.readLock();
         for (int i = 0; i < providerMaps.length; i++) {
             providerMaps[i] = concurrentMap();
         }
         this.executor = executor;
         this.name = name;
-        connectionProviders.put("local", new LocalConnectionProvider());
         connectionProviderContext = new ConnectionProviderContextImpl();
-        loopbackConnectionHandler = new LoopbackConnectionHandler();
-        loopbackConnection = new LoopbackConnection();
-        localConnectionContext = new LocalConnectionContext(null, loopbackConnection);
+        // add local connection provider
+        connectionProviders.put("local", new LocalConnectionProvider(connectionProviderContext));
+        // add default services
+        serviceBuilder(ServiceRequest.class, ServiceReply.class)
+                .setOptionMap(OptionMap.builder().set(RemotingOptions.FIXED_SERVICE_ID, Services.LOCATE_SERVICE).getMap())
+                .setClientListener(new ServiceLocationListener())
+                .setServiceType("org.jboss.remoting.service.locate")
+                .setGroupName("default")
+                .register();
+        this.optionMap = optionMap;
     }
 
     private final Executor executor;
@@ -192,6 +184,10 @@
         return executor;
     }
 
+    public Attachments getAttachments() {
+        return attachments;
+    }
+
     @SuppressWarnings({ "unchecked" })
     private <T> ConcurrentMap<String, T> getMapFor(ProtocolServiceType<T> type) {
         return (ConcurrentMap<String, T>)providerMaps[type.getIndex()];
@@ -201,13 +197,19 @@
         return name;
     }
 
+    public void close() throws IOException {
+        if (! optionMap.contains(Remoting.UNCLOSEABLE)) {
+            super.close();
+        }
+    }
+
     public <I, O> RequestHandler createLocalRequestHandler(final RequestListener<? super I, ? extends 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);
         }
         checkOpen();
-        final ClientContextImpl clientContext = new ClientContextImpl(executor, loopbackConnection);
+        final ClientContextImpl clientContext = new ClientContextImpl(executor, null);
         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>() {
@@ -232,6 +234,10 @@
         return new ServiceBuilderImpl<Void, Void>();
     }
 
+    public <I, O> ServiceBuilder<I, O> serviceBuilder(final Class<I> requestClass, final Class<O> replyClass) {
+        return serviceBuilder().setRequestType(requestClass).setReplyType(replyClass);
+    }
+
     private final class ServiceBuilderImpl<I, O> implements ServiceBuilder<I, O> {
         private String groupName;
         private String serviceType;
@@ -321,92 +327,135 @@
             ServiceURI.validateServiceType(serviceType);
             ServiceURI.validateGroupName(groupName);
             checkOpen();
-            final String canonServiceType = serviceType.toLowerCase();
-            final String canonGroupName = groupName.toLowerCase();
-            final Executor executor = EndpointImpl.this.executor;
-            final ConcurrentMap<String, ConcurrentMap<String, ServiceRegistration>> registeredLocalServices = EndpointImpl.this.registeredLocalServices;
-            final RequestHandlerConnector requestHandlerConnector = new Connector();
-            final ServiceRegistration registration = new ServiceRegistration(serviceType, groupName, name, optionMap, requestHandlerConnector);
-            // this handle is used to remove the service registration
-            final Registration handle = new Registration() {
-                public void close() {
-                    synchronized (serviceRegistrationLock) {
-                        final ConcurrentMap<String, ServiceRegistration> submap = registeredLocalServices.get(serviceType);
-                        if (submap != null) {
-                            submap.remove(groupName, registration);
+            Lock lock = serviceWriteLock;
+            lock.lock();
+            try {
+                final int slot;
+                final Integer fixedServiceId = optionMap.get(RemotingOptions.FIXED_SERVICE_ID);
+                if (fixedServiceId != null) {
+                    slot = fixedServiceId.intValue();
+                    if (slot < 0) {
+                        throw new IllegalArgumentException("fixed service ID must be greater than or equal to zero");
+                    }
+                    // todo - check permission for fixed service ID
+                    if (localServiceTable.containsKey(slot)) {
+                        throw new DuplicateRegistrationException("A service with slot ID " + slot + " is already registered");
+                    }
+                } else {
+                    int id;
+                    do {
+                        id = getRandomSlotID();
+                    } while (localServiceTable.containsKey(id));
+                    slot = id;
+                }
+                log.trace("Registering a service type '%s' group name '%s' with ID %d", serviceType, groupName, Integer.valueOf(slot));
+                final String canonServiceType = serviceType.toLowerCase();
+                final String canonGroupName = groupName.toLowerCase();
+                final Executor executor = EndpointImpl.this.executor;
+                final Map<String, Map<String, ServiceRegistrationInfo>> registeredLocalServices = localServiceIndex;
+                final RequestHandlerFactory<I, O> handlerFactory = RequestHandlerFactory.create(executor, clientListener, requestType, replyType);
+                final ServiceRegistrationInfo registration = new ServiceRegistrationInfo(serviceType, groupName, name, optionMap, handlerFactory, slot);
+                // this handle is used to remove the service registration
+                class ServiceRegistration extends AbstractHandleableCloseable<Registration> implements Registration {
+
+                    ServiceRegistration() {
+                        super(executor);
+                    }
+
+                    protected void closeAction() {
+                        final Lock lock = serviceWriteLock;
+                        lock.lock();
+                        try {
+                            final Map<String, ServiceRegistrationInfo> submap = localServiceIndex.get(serviceType);
+                            if (submap != null) {
+                                final ServiceRegistrationInfo oldReg = submap.get(groupName);
+                                if (oldReg == registration) {
+                                    submap.remove(groupName);
+                                }
+                            }
+                            final int regSlot = slot;
+                            final ServiceRegistrationInfo oldReg = localServiceTable.get(regSlot);
+                            if (oldReg == registration) {
+                                localServiceTable.remove(regSlot);
+                            }
+                            log.trace("Removed service type '%s' group name '%s' with ID %d", serviceType, groupName, Integer.valueOf(slot));
+                        } finally {
+                            lock.unlock();
                         }
                     }
+
+                    public void close() {
+                        try {
+                            super.close();
+                        } catch (IOException e) {
+                            throw new IllegalStateException(e);
+                        }
+                    }
                 }
-            };
-            registration.setHandle(handle);
-            final Iterator<Map.Entry<Registration,ServiceRegistrationListener>> serviceListenerRegistrations;
-            final Object lock = serviceRegistrationLock;
-            synchronized (lock) {
+                final Registration handle = new ServiceRegistration();
+                registration.setHandle(handle);
                 // actually register the service, and while we have the lock, snag a copy of the registration listener list
-                final ConcurrentMap<String, ServiceRegistration> submap;
+                final Map<String, ServiceRegistrationInfo> submap;
                 if (registeredLocalServices.containsKey(canonServiceType)) {
                     submap = registeredLocalServices.get(canonServiceType);
                     if (submap.containsKey(canonGroupName)) {
                         throw new ServiceRegistrationException("ListenerRegistration of service of type \"" + serviceType + "\" in group \"" + groupName + "\" duplicates an already-registered service's specification");
                     }
                 } else {
-                    submap = concurrentMap(lock);
+                    submap = hashMap();
                     registeredLocalServices.put(canonServiceType, submap);
                 }
                 submap.put(canonGroupName, registration);
+                localServiceTable.put(slot, registration);
+                // downgrade safely to read lock
+                final Lock readLock = serviceReadLock;
+                //noinspection LockAcquiredButNotSafelyReleased
+                readLock.lock();
+                try {
+                    lock.unlock();
+                } finally {
+                    lock = readLock;
+                }
                 // snapshot
+                final Iterator<Map.Entry<Registration,ServiceRegistrationListener>> serviceListenerRegistrations;
                 serviceListenerRegistrations = EndpointImpl.this.serviceListenerRegistrations.entrySet().iterator();
-            }
-            // 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.setOptionMap(optionMap);
-            serviceInfo.setRegistrationHandle(handle);
-            serviceInfo.setRequestHandlerConnector(requestHandlerConnector);
-            serviceInfo.setRequestClass(requestType);
-            serviceInfo.setReplyClass(replyType);
-            final ClassLoader classLoader = this.classLoader;
-            serviceInfo.setServiceClassLoader(classLoader == null ? clientListener.getClass().getClassLoader() : classLoader);
-            executor.execute(new Runnable() {
-                public void run() {
-                    final Iterator<Map.Entry<Registration,ServiceRegistrationListener>> iter = serviceListenerRegistrations;
-                    while (iter.hasNext()) {
-                        final Map.Entry<Registration,ServiceRegistrationListener> slr = iter.next();
-                        try {
-                            slr.getValue().serviceRegistered(slr.getKey(), serviceInfo.clone());
-                        } 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.setOptionMap(optionMap);
+                serviceInfo.setRegistrationHandle(handle);
+                serviceInfo.setSlot(slot);
+                serviceInfo.setRequestClass(requestType);
+                serviceInfo.setReplyClass(replyType);
+                final ClassLoader classLoader = this.classLoader;
+                serviceInfo.setServiceClassLoader(classLoader == null ? clientListener.getClass().getClassLoader() : classLoader);
+                executor.execute(new Runnable() {
+                    public void run() {
+                        final Iterator<Map.Entry<Registration,ServiceRegistrationListener>> iter = serviceListenerRegistrations;
+                        while (iter.hasNext()) {
+                            final Map.Entry<Registration,ServiceRegistrationListener> slr = iter.next();
+                            try {
+                                slr.getValue().serviceRegistered(slr.getKey(), serviceInfo.clone());
+                            } catch (Throwable t) {
+                                logListenerError(t);
+                            }
                         }
                     }
-                }
-            });
-            return handle;
-        }
-
-        private class Connector implements RequestHandlerConnector {
-
-            Connector() {
+                });
+                return handle;
+            } finally {
+                lock.unlock();
             }
-
-            public Cancellable createRequestHandler(final Result<RequestHandler> result) throws SecurityException {
-                try {
-                    final ClientContextImpl clientContext = new ClientContextImpl(executor, loopbackConnection);
-                    final RequestHandler localRequestHandler = createLocalRequestHandler(clientListener.handleClientOpen(clientContext), requestType, replyType);
-                    clientContext.addCloseHandler(new CloseHandler<ClientContext>() {
-                        public void handleClose(final ClientContext closed) {
-                            IoUtils.safeClose(localRequestHandler);
-                        }
-                    });
-                    result.setResult(localRequestHandler);
-                } catch (IOException e) {
-                    result.setException(e);
-                }
-                return IoUtils.nullCancellable();
-            }
         }
     }
 
+    private int getRandomSlotID() {
+        final Random random = new Random();
+        int id = random.nextInt() & 0x7fffffff;
+        return id;
+    }
+
     private static void logListenerError(final Throwable t) {
         log.error(t, "Service listener threw an exception");
     }
@@ -449,50 +498,74 @@
         if (sm != null) {
             sm.checkPermission(ADD_SERVICE_LISTENER_PERM);
         }
-        final List<ServiceRegistration> services;
-        final Registration registration = new Registration() {
+        class ServiceListenerRegistration extends AbstractHandleableCloseable<Registration> implements Registration {
+
+            ServiceListenerRegistration() {
+                super(executor);
+            }
+
+            protected void closeAction() {
+                Lock lock = serviceWriteLock;
+                lock.lock();
+                try {
+                    serviceListenerRegistrations.remove(this);
+                } finally {
+                    lock.unlock();
+                }
+            }
+
             public void close() {
-                serviceListenerRegistrations.remove(this);
+                try {
+                    super.close();
+                } catch (IOException e) {
+                    throw new IllegalStateException(e);
+                }
             }
-        };
-        synchronized (serviceRegistrationLock) {
+        }
+        final Registration registration = new ServiceListenerRegistration();
+        Lock lock = serviceWriteLock;
+        lock.lock();
+        try {
             serviceListenerRegistrations.put(registration, listener);
             if (flags == null || ! flags.contains(ListenerFlag.INCLUDE_OLD)) {
-                // need to make a copy of the whole list
-                services = new ArrayList<ServiceRegistration>();
-                for (Map.Entry<String, ConcurrentMap<String, ServiceRegistration>> entry : registeredLocalServices.entrySet()) {
-                    for (Map.Entry<String, ServiceRegistration> subEntry : entry.getValue().entrySet()) {
-                        services.add(subEntry.getValue());
+                final Lock readLock = serviceReadLock;
+                // safe downgrade
+                //noinspection LockAcquiredButNotSafelyReleased
+                readLock.lock();
+                try {
+                    lock.unlock();
+                } finally {
+                    lock = readLock;
+                }
+                final Executor executor = this.executor;
+                for (final Map.Entry<String, Map<String, ServiceRegistrationInfo>> entry : localServiceIndex.entrySet()) {
+                    for (final ServiceRegistrationInfo service : entry.getValue().values()) {
+                        executor.execute(new Runnable() {
+                            public void run() {
+                                final ServiceRegistrationListener.ServiceInfo serviceInfo = new ServiceRegistrationListener.ServiceInfo();
+                                serviceInfo.setGroupName(service.getGroupName());
+                                serviceInfo.setOptionMap(service.getOptionMap());
+                                serviceInfo.setRegistrationHandle(service.getHandle());
+                                serviceInfo.setSlot(service.getSlot());
+                                serviceInfo.setServiceType(service.getServiceType());
+                                try {
+                                    listener.serviceRegistered(registration, serviceInfo);
+                                } catch (Throwable t) {
+                                    logListenerError(t);
+                                }
+                            }
+                        });
                     }
                 }
-            } else {
-                services = null;
             }
+        } finally {
+            lock.unlock();
         }
-        if (services != null) {
-            executor.execute(new Runnable() {
-                public void run() {
-                    for (ServiceRegistration service : services) {
-                        final ServiceRegistrationListener.ServiceInfo serviceInfo = new ServiceRegistrationListener.ServiceInfo();
-                        serviceInfo.setGroupName(service.getGroupName());
-                        serviceInfo.setOptionMap(service.getOptionMap());
-                        serviceInfo.setRegistrationHandle(service.getHandle());
-                        serviceInfo.setRequestHandlerConnector(service.getRequestHandlerConnector());
-                        serviceInfo.setServiceType(service.getServiceType());
-                        try {
-                            listener.serviceRegistered(registration, serviceInfo);
-                        } catch (Throwable t) {
-                            logListenerError(t);
-                        }
-                    }
-                }
-            });
-        }
         return registration;
     }
 
     public IoFuture<? extends Connection> connect(final URI destination, final OptionMap connectOptions) throws IOException {
-        return connect(destination, connectOptions, new DefaultCallbackHandler(connectOptions.get(RemotingOptions.AUTH_USER_NAME), connectOptions.get(RemotingOptions.AUTH_REALM), null));
+        return connect(destination, connectOptions, new SimpleClientCallbackHandler(connectOptions.get(RemotingOptions.AUTH_USER_NAME), connectOptions.get(RemotingOptions.AUTH_REALM), null));
     }
 
     public IoFuture<? extends Connection> connect(final URI destination, final OptionMap connectOptions, final CallbackHandler callbackHandler) throws IOException {
@@ -508,7 +581,7 @@
         final FutureResult<Connection> futureResult = new FutureResult<Connection>(executor);
         futureResult.addCancelHandler(connectionProvider.connect(destination, connectOptions, new TranslatingResult<ConnectionHandlerFactory, Connection>(futureResult) {
             protected Connection translate(final ConnectionHandlerFactory input) {
-                return new ConnectionImpl(input, connectionProviderContext);
+                return new ConnectionImpl(EndpointImpl.this, input, connectionProviderContext, destination.toString());
             }
         }, callbackHandler));
         return futureResult.getIoFuture();
@@ -517,7 +590,7 @@
     public IoFuture<? extends Connection> connect(final URI destination, final OptionMap connectOptions, final String userName, final String realmName, final char[] password) throws IOException {
         final String actualUserName = userName != null ? userName : connectOptions.get(RemotingOptions.AUTH_USER_NAME);
         final String actualUserRealm = realmName != null ? realmName : connectOptions.get(RemotingOptions.AUTH_REALM);
-        return connect(destination, connectOptions, new DefaultCallbackHandler(actualUserName, actualUserRealm, password));
+        return connect(destination, connectOptions, new SimpleClientCallbackHandler(actualUserName, actualUserRealm, password));
     }
 
     public <T> ConnectionProviderRegistration<T> addConnectionProvider(final String uriScheme, final ConnectionProviderFactory<T> providerFactory) {
@@ -528,28 +601,9 @@
         final ConnectionProviderContextImpl context = new ConnectionProviderContextImpl();
         final ConnectionProvider<T> provider = providerFactory.createInstance(context);
         if (connectionProviders.putIfAbsent(uriScheme, provider) != null) {
-            IoUtils.safeClose(context);
             throw new DuplicateRegistrationException("URI scheme '" + uriScheme + "' is already registered to a provider");
         }
-        context.addCloseHandler(new CloseHandler<ConnectionProviderContext>() {
-            public void handleClose(final ConnectionProviderContext closed) {
-                connectionProviders.remove(uriScheme, provider);
-            }
-        });
-        final ConnectionProviderRegistration<T> handle = new ConnectionProviderRegistration<T>() {
-            public void close() {
-                IoUtils.safeClose(context);
-            }
-
-            public T getProviderInterface() {
-                return provider.getProviderInterface();
-            } 
-        };
-        context.addCloseHandler(new CloseHandler<ConnectionProviderContext>() {
-            public void handleClose(final ConnectionProviderContext closed) {
-                IoUtils.safeClose(handle);
-            }
-        });
+        final ConnectionProviderRegistration<T> handle = new ConnectionProviderRegistrationImpl<T>(uriScheme, provider);
         return handle;
     }
 
@@ -587,33 +641,33 @@
         return "endpoint \"" + name + "\" <" + Integer.toHexString(hashCode()) + ">";
     }
 
-    private static class MapRegistration<T> implements Registration {
-        private static final class Info<T> {
-            private final ConcurrentMap<String, T> map;
-            private final String key;
-            private final T value;
+    private class MapRegistration<T> extends AbstractHandleableCloseable<Registration> implements Registration {
 
-            private Info(final ConcurrentMap<String, T> map, final String key, final T value) {
-                this.map = map;
-                this.key = key;
-                this.value = value;
-            }
-        }
-        private final AtomicReference<Info<T>> infoRef = new AtomicReference<Info<T>>();
+        private final ConcurrentMap<String, T> map;
+        private final String key;
+        private final T value;
 
         private MapRegistration(final ConcurrentMap<String, T> map, final String key, final T value) {
-            infoRef.set(new Info<T>(map, key, value));
+            super(executor);
+            this.map = map;
+            this.key = key;
+            this.value = value;
         }
 
+        protected void closeAction() {
+            map.remove(key, value);
+        }
+
         public void close() {
-            final Info<T> info = infoRef.getAndSet(null);
-            if (info != null) {
-                info.map.remove(info.key, info.value);
+            try {
+                super.close();
+            } catch (IOException e) {
+                throw new IllegalStateException(e);
             }
         }
     }
 
-    private final class LocalConnectionContext implements ConnectionHandlerContext {
+    final class LocalConnectionContext implements ConnectionHandlerContext {
         private final ConnectionProviderContext connectionProviderContext;
         private final Connection connection;
 
@@ -626,47 +680,17 @@
             return connectionProviderContext;
         }
 
-        public void openService(final String serviceType, final String groupName, final OptionMap optionMap, final ServiceResult serviceResult) {
-            final String canonServiceType = serviceType.toLowerCase();
-            final String canonGroupName = groupName.toLowerCase();
-            final ConcurrentMap<String, ServiceRegistration> submap = registeredLocalServices.get(canonServiceType);
-            if (submap == null) {
-                serviceResult.notFound();
-                return;
-            }
-            final ServiceRegistration registration;
-            if (canonGroupName.equals("*")) {
-                final Iterator<Map.Entry<String, ServiceRegistration>> iter = submap.entrySet().iterator();
-                if (! iter.hasNext()) {
-                    serviceResult.notFound();
-                    return;
+        public RequestHandler openService(final int slotId, final OptionMap optionMap) throws ServiceOpenException {
+            serviceReadLock.lock();
+            try {
+                final ServiceRegistrationInfo info = localServiceTable.get(slotId);
+                if (info == null) {
+                    throw new ServiceOpenException("No service with ID of " + slotId);
                 }
-                registration = iter.next().getValue();
-            } else {
-                registration = submap.get(canonGroupName);
-                if (registration == null) {
-                    serviceResult.notFound();
-                    return;
-                }
+                return info.getRequestHandlerFactory().createRequestHandler(connection);
+            } finally {
+                serviceReadLock.unlock();
             }
-            registration.getRequestHandlerConnector().createRequestHandler(new Result<RequestHandler>() {
-                public boolean setResult(final RequestHandler result) {
-                    serviceResult.opened(result, registration.getOptionMap());
-                    return true;
-                }
-
-                public boolean setException(final IOException exception) {
-                    log.warn(exception, "Unexpected exception on service lookup");
-                    serviceResult.notFound();
-                    return true;
-                }
-
-                public boolean setCancelled() {
-                    log.warn("Unexpected cancellation on service lookup");
-                    serviceResult.notFound();
-                    return true;
-                }
-            });
         }
 
         public void remoteClosed() {
@@ -674,53 +698,17 @@
         }
     }
 
-    private class ConnectionImpl extends AbstractHandleableCloseable<Connection> implements Connection {
-        private final ConnectionHandler connectionHandler;
+    private final class ConnectionProviderContextImpl implements ConnectionProviderContext {
 
-        private ConnectionImpl(final ConnectionHandlerFactory connectionHandlerFactory, final ConnectionProviderContext connectionProviderContext) {
-            super(EndpointImpl.this.executor);
-            connectionHandler = connectionHandlerFactory.createInstance(new LocalConnectionContext(connectionProviderContext, this));
-        }
-
-        protected void closeAction() throws IOException {
-            connectionHandler.close();
-        }
-
-        public <I, O> IoFuture<? extends Client<I, O>> openClient(final String serviceType, final String groupName, final Class<I> requestClass, final Class<O> replyClass) {
-            final FutureResult<Client<I, O>> futureResult = new FutureResult<Client<I, O>>();
-            futureResult.addCancelHandler(connectionHandler.open(serviceType, groupName, new TranslatingResult<RequestHandler, Client<I, O>>(futureResult) {
-                protected Client<I, O> translate(final RequestHandler input) throws IOException {
-                    return createClient(input, requestClass, replyClass);
-                }
-            }));
-            return futureResult.getIoFuture();
-        }
-
-        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 final class ConnectionProviderContextImpl extends AbstractHandleableCloseable<ConnectionProviderContext> implements ConnectionProviderContext {
-
         private ConnectionProviderContextImpl() {
-            super(executor);
         }
 
         public Executor getExecutor() {
-            return super.getExecutor();
+            return executor;
         }
 
         public void accept(final ConnectionHandlerFactory connectionHandlerFactory) {
-            connectionHandlerFactory.createInstance(localConnectionContext);
+            connectionHandlerFactory.createInstance(new LocalConnectionContext(connectionProviderContext, new ConnectionImpl(EndpointImpl.this, connectionHandlerFactory, this, "client")));
         }
 
         public <T> Iterable<Map.Entry<String, T>> getProtocolServiceProviders(final ProtocolServiceType<T> serviceType) {
@@ -732,159 +720,79 @@
         }
     }
 
-    private final class LocalConnectionProvider implements ConnectionProvider<Void> {
+    private class ConnectionProviderRegistrationImpl<T> extends AbstractHandleableCloseable<Registration> implements ConnectionProviderRegistration<T> {
 
-        public Cancellable connect(final URI uri, final OptionMap connectOptions, final Result<ConnectionHandlerFactory> result, final CallbackHandler callbackHandler) throws IllegalArgumentException {
-            result.setResult(new ConnectionHandlerFactory() {
-                public ConnectionHandler createInstance(final ConnectionHandlerContext context) {
-                    return loopbackConnectionHandler;
-                }
-            });
-            return IoUtils.nullCancellable();
-        }
+        private final String uriScheme;
+        private final ConnectionProvider<T> provider;
 
-        public Void getProviderInterface() {
-            return null;
+        public ConnectionProviderRegistrationImpl(final String uriScheme, final ConnectionProvider<T> provider) {
+            super(executor);
+            this.uriScheme = uriScheme;
+            this.provider = provider;
         }
-    }
 
-    private class LoopbackConnection implements Connection {
-
-        public <I, O> IoFuture<? extends Client<I, O>> openClient(final String serviceType, final String groupName, final Class<I> requestClass, final Class<O> replyClass) {
-            final FutureResult<Client<I,O>> futureResult = new FutureResult<Client<I, O>>(executor);
-            futureResult.addCancelHandler(loopbackConnectionHandler.open(serviceType, groupName, new TranslatingResult<RequestHandler, Client<I, O>>(futureResult) {
-                protected Client<I, O> translate(final RequestHandler input) throws IOException {
-                    return ClientImpl.create(input, executor, requestClass, replyClass);
-                }
-            }));
-            return futureResult.getIoFuture();
+        protected void closeAction() {
+            connectionProviders.remove(uriScheme, provider);
         }
 
-        public <I, O> ClientConnector<I, O> createClientConnector(final RequestListener<I, O> listener, final Class<I> requestClass, final Class<O> replyClass) {
-            final Client<I, O> client;
-            final ClientContextImpl context = new ClientContextImpl(executor, LoopbackConnection.this);
+        public void close() {
             try {
-                client = createClient(createLocalRequestHandler(listener, requestClass, replyClass), requestClass, replyClass);
-                context.addCloseHandler(new CloseHandler<ClientContext>() {
-                    public void handleClose(final ClientContext closed) {
-                        IoUtils.safeClose(client);
-                    }
-                });
-                return new LoopbackClientConnector<I, O>(new FinishedIoFuture<Client<I, O>>(client), context);
+                super.close();
             } catch (IOException e) {
-                return new LoopbackClientConnector<I, O>(new FailedIoFuture<Client<I, O>>(e), context);
+                // not possible
+                throw new IllegalStateException(e);
             }
         }
 
-        public void close() {
-            // ignored
+        public T getProviderInterface() {
+            return provider.getProviderInterface();
         }
-
-        public Key addCloseHandler(final CloseHandler<? super Connection> closeHandler) {
-            return EndpointImpl.this.addCloseHandler(new CloseHandler<Endpoint>() {
-                public void handleClose(final Endpoint closed) {
-                    closeHandler.handleClose(LoopbackConnection.this);
-                }
-            });
-        }
     }
 
-    private static class LoopbackClientConnector<I, O> implements ClientConnector<I, O> {
-
-        private final IoFuture<Client<I, O>> ioFuture;
-        private final ClientContextImpl context;
-
-        public LoopbackClientConnector(final IoFuture<Client<I, O>> ioFuture, final ClientContextImpl context) {
-            this.ioFuture = ioFuture;
-            this.context = context;
-        }
-
-        public IoFuture<? extends Client<I, O>> getFutureClient() throws SecurityException {
-            return ioFuture;
-        }
-
-        public ClientContext getClientContext() throws SecurityException {
-            return context;
-        }
-    }
-
-    private class LoopbackConnectionHandler implements ConnectionHandler {
-
-        public Cancellable open(final String serviceType, final String groupName, final org.jboss.xnio.Result<RequestHandler> result) {
-            localConnectionContext.openService(serviceType, groupName, OptionMap.EMPTY, new ConnectionHandlerContext.ServiceResult() {
-                public void opened(final RequestHandler requestHandler, final OptionMap optionMap) {
-                    result.setResult(requestHandler);
-                }
-
-                public void notFound() {
-                    result.setException(new ServiceNotFoundException(ServiceURI.create(serviceType, groupName, name), "No such service located"));
-                }
-            });
-            return IoUtils.nullCancellable();
-        }
-
-        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 org.jboss.xnio.Result<RequestHandler> result) throws SecurityException {
-                    result.setResult(localHandler);
-                    return IoUtils.nullCancellable();
-                }
-            };
-        }
-
-        public void close() {
-            // not closeable
-        }
-    }
-
-    private static class DefaultCallbackHandler implements CallbackHandler {
-
-        private final String actualUserName;
-        private final String actualUserRealm;
-        private final char[] password;
-
-        private DefaultCallbackHandler(final String actualUserName, final String actualUserRealm, final char[] password) {
-            this.actualUserName = actualUserName;
-            this.actualUserRealm = actualUserRealm;
-            this.password = password;
-        }
-
-        public void handle(final Callback[] callbacks) throws IOException, UnsupportedCallbackException {
-            MAIN: for (Callback callback : callbacks) {
-                if (callback instanceof NameCallback && actualUserName != null) {
-                    final NameCallback nameCallback = (NameCallback) callback;
-                    nameCallback.setName(actualUserName);
-                } else if (callback instanceof RealmCallback && actualUserRealm != null) {
-                    final RealmCallback realmCallback = (RealmCallback) callback;
-                    realmCallback.setText(actualUserRealm);
-                } else if (callback instanceof RealmChoiceCallback && actualUserRealm != null) {
-                    final RealmChoiceCallback realmChoiceCallback = (RealmChoiceCallback) callback;
-                    final String[] choices = realmChoiceCallback.getChoices();
-                    for (int i = 0; i < choices.length; i++) {
-                        if (choices[i].equals(actualUserRealm)) {
-                            realmChoiceCallback.setSelectedIndex(i);
-                            continue MAIN;
+    final class ServiceLocationListener implements ClientListener<ServiceRequest, ServiceReply> {
+        private final RequestListener<ServiceRequest, ServiceReply> requestListener = new RequestListener<ServiceRequest, ServiceReply>() {
+            public void handleRequest(final RequestContext<ServiceReply> context, final ServiceRequest request) throws RemoteExecutionException {
+                final String requestGroupName = request.getGroupName();
+                final String requestServiceType = request.getServiceType();
+                final Lock lock = serviceReadLock;
+                lock.lock();
+                try {
+                    final Map<String, ServiceRegistrationInfo> submap = localServiceIndex.get(requestServiceType);
+                    if (submap != null) {
+                        final ServiceRegistrationInfo info;
+                        if (requestGroupName == null || "*".equals(requestGroupName)) {
+                            final Iterator<Map.Entry<String,ServiceRegistrationInfo>> i = submap.entrySet().iterator();
+                            if (i.hasNext()) {
+                                final Map.Entry<String, ServiceRegistrationInfo> entry = i.next();
+                                info = entry.getValue();
+                            } else {
+                                info = null;
+                            }
+                        } else {
+                            info = submap.get(requestGroupName);
                         }
+                        if (info != null) {
+                            try {
+                                context.sendReply(ServiceReply.create(info.getSlot(), info.getRequestHandlerFactory().getRequestClass(), info.getRequestHandlerFactory().getReplyClass()));
+                            } catch (IOException e) {
+                                log.trace("Failed to send service reply: %s", e);
+                                // reply failed
+                            }
+                            return;
+                        }
                     }
-                    throw new UnsupportedCallbackException(callback, "No realm choices match realm '" + actualUserRealm + "'");
-                } else if (callback instanceof TextOutputCallback) {
-                    final TextOutputCallback textOutputCallback = (TextOutputCallback) callback;
-                    final String kind;
-                    switch (textOutputCallback.getMessageType()) {
-                        case TextOutputCallback.ERROR: kind = "ERROR"; break;
-                        case TextOutputCallback.INFORMATION: kind = "INFORMATION"; break;
-                        case TextOutputCallback.WARNING: kind = "WARNING"; break;
-                        default: kind = "UNKNOWN"; break;
-                    }
-                    log.debug("Authentication layer produced a %s message: %s", kind, textOutputCallback.getMessage());
-                } else if (callback instanceof PasswordCallback && password != null) {
-                    final PasswordCallback passwordCallback = (PasswordCallback) callback;
-                    passwordCallback.setPassword(password);
-                } else {
-                    throw new UnsupportedCallbackException(callback);
+                    throw new RemoteExecutionException(new ServiceNotFoundException(ServiceURI.create(requestServiceType, requestGroupName, null)));
+                } finally {
+                    lock.unlock();
                 }
             }
+
+            public void handleClose() {
+            }
+        };
+
+        public RequestListener<ServiceRequest, ServiceReply> handleClientOpen(final ClientContext clientContext) {
+            return requestListener;
         }
     }
 }

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointPermission.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointPermission.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointPermission.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -1,61 +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.security.BasicPermission;
-
-/**
- * This class is for permissions relating to Remoting endpoints.
- */
-public class EndpointPermission extends BasicPermission {
-
-    private static final long serialVersionUID = 4984517897378387571L;
-
-    /**
-     * Creates a new {@code EndpointPermission} object with the specified name.
-     * The name is the symbolic name of the {@code EndpointPermission}.
-     *
-     * @param name the name of the {@code EndpointPermission}
-     *
-     * @throws NullPointerException if {@code name} is {@code null}
-     * @throws IllegalArgumentException if {@code name} is empty
-     */
-    public EndpointPermission(String name) throws NullPointerException, IllegalArgumentException {
-        super(name);
-    }
-
-    /**
-     * Creates a new {@code EndpointPermission} object with the specified name.
-     * The name is the symbolic name of the {@code EndpointPermission}, and the
-     * actions string is currently unused.
-     *
-     * @param name the name of the {@code EndpointPermission}
-     * @param actions ignored
-     *
-     * @throws NullPointerException if {@code name} is {@code null}
-     * @throws IllegalArgumentException if {@code name} is empty
-     */
-    public EndpointPermission(String name, String actions) throws NullPointerException, IllegalArgumentException {
-        super(name, actions);
-    }
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureReplyImpl.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureReplyImpl.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/FutureReplyImpl.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -24,9 +24,9 @@
 
 import java.io.IOException;
 import java.util.concurrent.Executor;
-import org.jboss.remoting3.spi.RemoteRequestContext;
 import org.jboss.remoting3.spi.ReplyHandler;
 import org.jboss.xnio.AbstractIoFuture;
+import org.jboss.xnio.Cancellable;
 import org.jboss.xnio.IoFuture;
 
 /**
@@ -35,16 +35,32 @@
 final class FutureReplyImpl<O> extends AbstractIoFuture<O> {
 
     private final Executor executor;
-    private final Class<? extends O> replyType;
+    private final Checker<? extends O> checker;
     private final ReplyHandler replyHandler = new Handler();
-    private volatile RemoteRequestContext remoteRequestContext;
+    private volatile Cancellable remoteRequestContext;
 
-    FutureReplyImpl(final Executor executor, final Class<? extends O> replyType) {
+    FutureReplyImpl(final Executor executor, final Checker<? extends O> checker) {
         this.executor = executor;
-        this.replyType = replyType;
+        this.checker = checker;
     }
 
-    void setRemoteRequestContext(final RemoteRequestContext remoteRequestContext) {
+    FutureReplyImpl(final Executor executor, final Class<? extends O> expectedType) {
+        this(executor, new Checker<O>() {
+            public O cast(final Object input) {
+                return expectedType.cast(input);
+            }
+        });
+    }
+
+    FutureReplyImpl(final Executor executor, final TypedRequest<?, ? extends O> typedRequest) {
+        this(executor, new Checker<O>() {
+            public O cast(final Object input) {
+                return typedRequest.castReply(input);
+            }
+        });
+    }
+
+    void setRemoteRequestContext(final Cancellable remoteRequestContext) {
         this.remoteRequestContext = remoteRequestContext;
     }
 
@@ -62,25 +78,20 @@
         return replyHandler;
     }
 
+    interface Checker<O> {
+        O cast(Object input);
+    }
+
     private final class Handler implements ReplyHandler {
 
         public void handleReply(final Object reply) {
-            final Class<? extends O> replyType = FutureReplyImpl.this.replyType;
+            final Checker<? extends O> checker = FutureReplyImpl.this.checker;
             final O actualReply;
             try {
-                actualReply = replyType.cast(reply);
+                actualReply = checker.cast(reply);
             } catch (ClassCastException e) {
                 // reply can't be null, else we wouldn't be here...
-                final Class<? extends Object> actualReplyType = reply.getClass();
-                final String actualReplyTypeName = actualReplyType.getName();
-                final String replyTypeName = replyType.getName();
-                final ReplyException replyException;
-                if (actualReplyTypeName.equals(replyTypeName)) {
-                    replyException = new ReplyException("Reply appears to be of the right type (" + replyTypeName + "), but from the wrong classloader (the reply is from classloader " + actualReplyType.getClassLoader() + " but the client expected it to be classloader " + replyType.getClassLoader() + ")");
-                } else {
-                    replyException = new ReplyException("Reply was of the wrong type (got a " + actualReplyTypeName + "; expected a " + replyTypeName + ")");
-                }
-                setException(replyException);
+                setException(new ReplyException("Reply was of unexpected type " + reply.getClass().getName()));
                 return;
             }
             setResult(actualReply);

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalConnectionHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalConnectionHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalConnectionHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.ConnectionHandler;
+import org.jboss.remoting3.spi.ConnectionHandlerContext;
+import org.jboss.remoting3.spi.RequestHandler;
+import org.jboss.remoting3.spi.RequestHandlerConnector;
+import org.jboss.xnio.Cancellable;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.Result;
+
+public final class LocalConnectionHandler implements ConnectionHandler {
+
+    private final ConnectionHandlerContext connectionHandlerContext;
+
+    public LocalConnectionHandler(final ConnectionHandlerContext connectionHandlerContext) {
+        this.connectionHandlerContext = connectionHandlerContext;
+    }
+
+    public Cancellable open(final int slot, final Result<RequestHandler> result) {
+        try {
+            // todo: support for call-by-value
+            final RequestHandler handler = connectionHandlerContext.openService(slot, OptionMap.EMPTY);
+            result.setResult(handler);
+        } catch (IOException e) {
+            result.setException(e);
+        }
+        return IoUtils.nullCancellable();
+    }
+
+    public RequestHandlerConnector createConnector(final RequestHandler localHandler) {
+        return new RequestHandlerConnector() {
+            public Cancellable createRequestHandler(final Result<RequestHandler> result) throws SecurityException {
+                result.setResult(localHandler);
+                return IoUtils.nullCancellable();
+            }
+        };
+    }
+
+    public void close() throws IOException {
+        connectionHandlerContext.remoteClosed();
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalConnectionProvider.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalConnectionProvider.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalConnectionProvider.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,93 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.net.URI;
+import org.jboss.remoting3.spi.ConnectionHandler;
+import org.jboss.remoting3.spi.ConnectionHandlerContext;
+import org.jboss.remoting3.spi.ConnectionHandlerFactory;
+import org.jboss.remoting3.spi.ConnectionProvider;
+import org.jboss.remoting3.spi.ConnectionProviderContext;
+import org.jboss.xnio.Cancellable;
+import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.OptionMap;
+import org.jboss.xnio.Result;
+
+import javax.security.auth.callback.CallbackHandler;
+
+public final class LocalConnectionProvider implements ConnectionProvider<Void> {
+    private final ConnectionProviderContext providerContext;
+
+    public LocalConnectionProvider(final ConnectionProviderContext providerContext) {
+        this.providerContext = providerContext;
+    }
+
+    public Cancellable connect(final URI uri, final OptionMap connectOptions, final Result<ConnectionHandlerFactory> result, final CallbackHandler callbackHandler) throws IllegalArgumentException {
+        result.setResult(new ConnectionHandlerFactory() {
+            public ConnectionHandler createInstance(final ConnectionHandlerContext outboundContext) {
+                final Holder h = new Holder();
+                providerContext.accept(new ConnectionHandlerFactory() {
+                    public ConnectionHandler createInstance(final ConnectionHandlerContext inboundContext) {
+                        final LocalConnectionHandler inboundHandler = new LocalConnectionHandler(inboundContext);
+                        h.set(inboundHandler);
+                        return new LocalConnectionHandler(outboundContext);
+                    }
+                });
+                return h.get(); // outbound connection handler
+            }
+        });
+        return IoUtils.nullCancellable();
+    }
+
+    public Void getProviderInterface() {
+        return null;
+    }
+
+    private static final class Holder {
+        private ConnectionHandler handler;
+
+        ConnectionHandler get() {
+            boolean intr = false;
+            try {
+                synchronized (this) {
+                    ConnectionHandler handler;
+                    while ((handler = this.handler) == null) try {
+                        wait();
+                    } catch (InterruptedException e) {
+                        intr = true;
+                    }
+                    return handler;
+                }
+            } finally {
+                if (intr) Thread.currentThread().interrupt();
+            }
+        }
+
+        void set(ConnectionHandler handler) {
+            synchronized (this) {
+                this.handler = handler;
+                notifyAll();
+            }
+        }
+    }
+}

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/LocalRequestHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -26,10 +26,11 @@
 import java.util.concurrent.Executor;
 import java.util.concurrent.RejectedExecutionException;
 import org.jboss.remoting3.spi.AbstractHandleableCloseable;
-import org.jboss.remoting3.spi.RemoteRequestContext;
 import org.jboss.remoting3.spi.ReplyHandler;
 import org.jboss.remoting3.spi.RequestHandler;
 import org.jboss.remoting3.spi.SpiUtils;
+import org.jboss.xnio.Cancellable;
+import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.log.Logger;
 
 /**
@@ -53,7 +54,7 @@
         this.replyClass = replyClass;
     }
 
-    public RemoteRequestContext receiveRequest(final Object request, final ReplyHandler replyHandler) {
+    public Cancellable receiveRequest(final Object request, final ReplyHandler replyHandler) {
         final RequestContextImpl<O> context = new RequestContextImpl<O>(replyHandler, clientContext, replyClass);
         try {
             final I castRequest;
@@ -61,7 +62,7 @@
                 castRequest = requestClass.cast(request);
             } catch (ClassCastException e) {
                 SpiUtils.safeHandleException(replyHandler, new RemoteRequestException("Request is the wrong type; expected " + requestClass + " but got " + request.getClass()));
-                return SpiUtils.getBlankRemoteRequestContext();
+                return IoUtils.nullCancellable();
             }
             context.execute(new Runnable() {
                 public void run() {
@@ -76,10 +77,10 @@
             });
         } catch (RejectedExecutionException e) {
             SpiUtils.safeHandleException(replyHandler, new RemoteRequestException("Execution was rejected (server may be too busy)", e));
-            return SpiUtils.getBlankRemoteRequestContext();
+            return IoUtils.nullCancellable();
         }
-        return new RemoteRequestContext() {
-            public RemoteRequestContext cancel() {
+        return new Cancellable() {
+            public Cancellable cancel() {
                 context.cancel();
                 return this;
             }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Registration.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Registration.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Registration.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -22,12 +22,10 @@
 
 package org.jboss.remoting3;
 
-import java.io.Closeable;
-
 /**
  * A simple registration handle.  Registration handles are closeable but the close will not throw an exception.
  */
-public interface Registration extends Closeable {
+public interface Registration extends HandleableCloseable<Registration> {
 
     /**
      * Close the registration.

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemoteClassTable.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemoteClassTable.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemoteClassTable.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,176 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.InterruptedIOException;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
+import org.jboss.marshalling.ClassTable;
+import org.jboss.marshalling.Marshaller;
+import org.jboss.marshalling.Unmarshaller;
+import org.jboss.remoting3.service.classtable.ClassLookupRequest;
+import org.jboss.remoting3.service.classtable.ClassLookupResponse;
+
+final class RemoteClassTable implements ClassTable {
+    private final Client<ClassLookupRequest, ClassLookupResponse> resolver;
+    private final ClientListener<ClassLookupRequest, ClassLookupResponse> clientListener = new RctClientListener();
+    private final RequestListener<ClassLookupRequest, ClassLookupResponse> requestListener = new RctRequestListener();
+
+    private final ConcurrentMap<Integer, FutureClass> remoteClasses = null;
+    private final ConcurrentMap<Integer, Class<?>> localClasses = null;
+    private final ConcurrentMap<Class<?>, IntWriter> localClassWriters = null;
+
+    @SuppressWarnings({ "UnusedDeclaration" })
+    private volatile int seq;
+
+    private static final AtomicIntegerFieldUpdater<RemoteClassTable> seqUpdater = AtomicIntegerFieldUpdater.newUpdater(RemoteClassTable.class, "seq");
+
+    public RemoteClassTable(final Client<ClassLookupRequest, ClassLookupResponse> resolver) {
+        this.resolver = resolver;
+    }
+
+    public ClientListener<ClassLookupRequest, ClassLookupResponse> getClientListener() {
+        return clientListener;
+    }
+
+    public Writer getClassWriter(final Class<?> clazz) throws IOException {
+        IntWriter writer = localClassWriters.get(clazz);
+        if (writer == null) {
+            final int id = seqUpdater.addAndGet(this, 97);
+            writer = new IntWriter(id);
+            IntWriter appearing = localClassWriters.putIfAbsent(clazz, writer);
+            if (appearing != null) {
+                return appearing;
+            }
+            localClasses.put(Integer.valueOf(id), clazz);
+        }
+        return writer;
+    }
+
+    public Class<?> readClass(final Unmarshaller unmarshaller) throws IOException, ClassNotFoundException {
+        final int id = unmarshaller.readInt();
+        final Integer idKey = Integer.valueOf(id);
+        FutureClass futureClass = remoteClasses.get(idKey);
+        if (futureClass != null) {
+            return futureClass.getValue();
+        }
+        futureClass = new FutureClass();
+        FutureClass appearing = remoteClasses.putIfAbsent(idKey, futureClass);
+        if (appearing != null) {
+            return appearing.getValue();
+        }
+        try {
+            final ClassLookupResponse response = resolver.invoke(new ClassLookupRequest(id));
+            futureClass.setValue(response.getResolvedClass());
+            return response.getResolvedClass();
+        } catch (RemoteExecutionException e) {
+            throw new ClassNotFoundException(e.getMessage());
+        }
+    }
+
+    private static final class FutureClass {
+        private Class<?> value;
+        private boolean done;
+
+        public Class<?> getValue() throws IOException, ClassNotFoundException {
+            synchronized (this) {
+                while (! done) try {
+                    wait();
+                } catch (InterruptedException e) {
+                    Thread.currentThread().interrupt();
+                    throw new InterruptedIOException();
+                }
+                final Class<?> result = value;
+                if (result == null) {
+                    throw new ClassNotFoundException();
+                }
+                return result;
+            }
+        }
+
+        public void setValue(final Class<?> value) {
+            synchronized (this) {
+                this.value = value;
+                done = true;
+                notifyAll();
+            }
+        }
+
+        public boolean isDone() {
+            synchronized (this) {
+                return done;
+            }
+        }
+
+        public void setDone(final boolean done) {
+            synchronized (this) {
+                this.done = done;
+                notifyAll();
+            }
+        }
+    }
+
+    private static final class IntWriter implements Writer {
+        private final int value;
+
+        private IntWriter(final int value) {
+            this.value = value;
+        }
+
+        public void writeClass(final Marshaller marshaller, final Class<?> clazz) throws IOException {
+            marshaller.writeInt(value);
+        }
+
+        public int getValue() {
+            return value;
+        }
+    }
+
+    private class RctClientListener implements ClientListener<ClassLookupRequest, ClassLookupResponse> {
+        public RequestListener<ClassLookupRequest, ClassLookupResponse> handleClientOpen(final ClientContext clientContext) {
+            return requestListener;
+        }
+    }
+
+    private class RctRequestListener implements RequestListener<ClassLookupRequest, ClassLookupResponse> {
+        public void handleRequest(final RequestContext<ClassLookupResponse> requestContext, final ClassLookupRequest request) throws RemoteExecutionException {
+            try {
+                final int id = request.getId();
+                final Integer idObj = Integer.valueOf(id);
+                final Class<?> localClass = localClasses.get(idObj);
+                if (localClass != null) {
+                    requestContext.sendReply(new ClassLookupResponse(localClass));
+                } else {
+                    requestContext.sendFailure("No class found with an ID of #" + idObj, null);
+                }
+            } catch (IOException e) {
+                // no action necessary.
+            }
+        }
+
+        public void handleClose() {
+            // ---
+        }
+    }
+}

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Remoting.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -38,11 +38,13 @@
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.lang.reflect.InvocationTargetException;
+import org.jboss.remoting3.security.RemotingPermission;
 import org.jboss.remoting3.spi.RequestHandler;
 import org.jboss.remoting3.spi.RemotingServiceDescriptor;
 import org.jboss.remoting3.spi.ConnectionProviderFactory;
 import org.jboss.remoting3.spi.ProtocolServiceType;
 import org.jboss.xnio.IoUtils;
+import org.jboss.xnio.Option;
 import org.jboss.xnio.OptionMap;
 import org.jboss.xnio.log.Logger;
 import org.jboss.marshalling.ClassTable;
@@ -66,12 +68,14 @@
     private static Endpoint configuredEndpoint;
     private static final Object lock = new Object();
 
-    private static final EndpointPermission CREATE_ENDPOINT_PERM = new EndpointPermission("createEndpoint");
-    private static final EndpointPermission GET_CONFIGURED_ENDPOINT_PERM = new EndpointPermission("getConfiguredEndpoint");
+    private static final RemotingPermission CREATE_ENDPOINT_PERM = new RemotingPermission("createEndpoint");
+    private static final RemotingPermission GET_CONFIGURED_ENDPOINT_PERM = new RemotingPermission("getConfiguredEndpoint");
 
     private static final String PROPERTIES = "remoting.properties";
     private static final String PROPERTY_FILE_PROPNAME = "remoting.property.file";
 
+    static final Option<Boolean> UNCLOSEABLE = Option.simple(Remoting.class, "UNCLOSEABLE", Boolean.class);
+
     private static final ThreadFactory OUR_THREAD_FACTORY = new ThreadFactory() {
         private final ThreadFactory defaultThreadFactory = Executors.defaultThreadFactory();
 
@@ -135,7 +139,7 @@
                     try {
                         final Endpoint endpoint;
                         try {
-                            endpoint = createEndpoint(props.getProperty("endpoint.name", "endpoint"), executor, OptionMap.builder().parseAll(props, "endpoint.option.").getMap());
+                            endpoint = createEndpoint(props.getProperty("endpoint.name", "endpoint"), executor, OptionMap.builder().parseAll(props, "endpoint.option.").set(UNCLOSEABLE, true).getMap());
                         } catch (IOException e) {
                             throw new RuntimeException(e);
                         }
@@ -265,7 +269,7 @@
         if (sm != null) {
             sm.checkPermission(CREATE_ENDPOINT_PERM);
         }
-        final Endpoint endpoint = new EndpointImpl(executor, endpointName);
+        final Endpoint endpoint = new EndpointImpl(executor, endpointName, optionMap);
         return endpoint;
     }
 

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RemotingOptions.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -133,4 +133,14 @@
      * The authentication realm to use if no authentication {@code CallbackHandler} is specified.
      */
     public static final Option<String> AUTH_REALM = Option.simple(RemotingOptions.class, "AUTH_REALM", String.class);
+
+    /**
+     * Specify a fixed ID for a well-known service.
+     */
+    public static final Option<Integer> FIXED_SERVICE_ID = Option.simple(RemotingOptions.class, "FIXED_SERVICE_ID", Integer.class);
+
+    /**
+     * Specify whether a local connection or client should call by reference (the usual default) or value.
+     */
+    public static final Option<Boolean> CALL_BY_VALUE = Option.simple(RemotingOptions.class, "CALL_BY_VALUE", Boolean.class);
 }

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RequestHandlerFactory.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RequestHandlerFactory.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/RequestHandlerFactory.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,60 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.remoting3.spi.RequestHandler;
+
+/**
+ * A factory which creates request handlers corresponding to request listeners for a given client listener.
+ */
+final class RequestHandlerFactory<I, O> {
+    private final Executor executor;
+    private final ClientListener<? super I, ? extends O> clientListener;
+    private final Class<I> requestClass;
+    private final Class<O> replyClass;
+
+    RequestHandlerFactory(final Executor executor, final ClientListener<? super I, ? extends O> clientListener, final Class<I> requestClass, final Class<O> replyClass) {
+        this.executor = executor;
+        this.clientListener = clientListener;
+        this.requestClass = requestClass;
+        this.replyClass = replyClass;
+    }
+
+    static <I, O> RequestHandlerFactory<I, O> create(final Executor executor, final ClientListener<? super I, ? extends O> clientListener, final Class<I> requestClass, final Class<O> replyClass) {
+        return new RequestHandlerFactory<I, O>(executor, clientListener, requestClass, replyClass);
+    }
+
+    RequestHandler createRequestHandler(final Connection connection) {
+        final ClientContextImpl context = new ClientContextImpl(executor, connection);
+        return new LocalRequestHandler<I, O>(executor, clientListener.handleClientOpen(context), context, requestClass, replyClass);
+    }
+
+    Class<I> getRequestClass() {
+        return requestClass;
+    }
+
+    Class<O> getReplyClass() {
+        return replyClass;
+    }
+}

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -1,96 +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 org.jboss.remoting3.spi.RequestHandlerConnector;
-import org.jboss.remoting3.spi.RequestHandler;
-import org.jboss.xnio.OptionMap;
-
-/**
- *
- */
-final class ServiceRegistration {
-    private final boolean remote;
-    private final String serviceType;
-    private final String groupName;
-    private final String endpointName;
-    private final OptionMap optionMap;
-    private final RequestHandlerConnector requestHandlerConnector;
-    private volatile Registration handle;
-
-    ServiceRegistration(final String serviceType, final String groupName, final String endpointName, final OptionMap optionMap, final RequestHandlerConnector requestHandlerConnector) {
-        this.requestHandlerConnector = requestHandlerConnector;
-        remote = true;
-        this.serviceType = serviceType;
-        this.groupName = groupName;
-        this.endpointName = endpointName;
-        this.optionMap = optionMap;
-    }
-
-    ServiceRegistration(final String serviceType, final String groupName, final String endpointName, final RequestHandlerConnector requestHandlerConnector) {
-        this.requestHandlerConnector = requestHandlerConnector;
-        remote = false;
-        optionMap = OptionMap.EMPTY;
-        this.serviceType = serviceType;
-        this.groupName = groupName;
-        this.endpointName = endpointName;
-    }
-
-    public boolean matches(final String serviceType, final String groupName, final String endpointName) {
-        return  (serviceType == null || serviceType.length() == 0 || "*".equals(serviceType) || serviceType.equals(this.serviceType)) &&
-                (groupName == null || groupName.length() == 0 || "*".equals(groupName) || groupName.equals(this.groupName)) &&
-                (endpointName == null || endpointName.length() == 0 || "*".equals(endpointName) || endpointName.equals(this.endpointName));
-    }
-
-    public boolean isRemote() {
-        return remote;
-    }
-
-    public String getServiceType() {
-        return serviceType;
-    }
-
-    public String getGroupName() {
-        return groupName;
-    }
-
-    public String getEndpointName() {
-        return endpointName;
-    }
-
-    public OptionMap getOptionMap() {
-        return optionMap;
-    }
-
-    public RequestHandlerConnector getRequestHandlerConnector() {
-        return requestHandlerConnector;
-    }
-
-    public Registration getHandle() {
-        return handle;
-    }
-
-    void setHandle(final Registration handle) {
-        this.handle = handle;
-    }
-}

Copied: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationInfo.java (from rev 5754, remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistration.java)
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationInfo.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationInfo.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,86 @@
+/*
+ * 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 org.jboss.xnio.OptionMap;
+
+/**
+ *
+ */
+final class ServiceRegistrationInfo {
+
+    private final String serviceType;
+    private final String groupName;
+    private final String endpointName;
+    private final OptionMap optionMap;
+    private final RequestHandlerFactory<?, ?> requestHandlerFactory;
+    private volatile Registration handle;
+    private final int slot;
+
+    ServiceRegistrationInfo(final String serviceType, final String groupName, final String endpointName, final OptionMap optionMap, final RequestHandlerFactory<?, ?> requestHandlerFactory, final int slot) {
+        this.requestHandlerFactory = requestHandlerFactory;
+        this.slot = slot;
+        this.serviceType = serviceType;
+        this.groupName = groupName;
+        this.endpointName = endpointName;
+        this.optionMap = optionMap;
+    }
+
+    public boolean matches(final String serviceType, final String groupName, final String endpointName) {
+        return  (serviceType == null || serviceType.length() == 0 || "*".equals(serviceType) || serviceType.equals(this.serviceType)) &&
+                (groupName == null || groupName.length() == 0 || "*".equals(groupName) || groupName.equals(this.groupName)) &&
+                (endpointName == null || endpointName.length() == 0 || "*".equals(endpointName) || endpointName.equals(this.endpointName));
+    }
+
+    public String getServiceType() {
+        return serviceType;
+    }
+
+    public String getGroupName() {
+        return groupName;
+    }
+
+    public String getEndpointName() {
+        return endpointName;
+    }
+
+    public OptionMap getOptionMap() {
+        return optionMap;
+    }
+
+    public RequestHandlerFactory<?, ?> getRequestHandlerFactory() {
+        return requestHandlerFactory;
+    }
+
+    public Registration getHandle() {
+        return handle;
+    }
+
+    void setHandle(final Registration handle) {
+        this.handle = handle;
+    }
+
+    public int getSlot() {
+        return slot;
+    }
+}

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceRegistrationListener.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -22,7 +22,6 @@
 
 package org.jboss.remoting3;
 
-import org.jboss.remoting3.spi.RequestHandlerConnector;
 import org.jboss.xnio.OptionMap;
 
 /**
@@ -37,7 +36,7 @@
      * Receive notification that a service was registered.
      *
      * @param listenerHandle the handle to this listener
-     * @param info the servce information
+     * @param info the service information
      */
     void serviceRegistered(Registration listenerHandle, ServiceInfo info);
 
@@ -52,7 +51,7 @@
         private ClassLoader serviceClassLoader;
         private Class<?> requestClass;
         private Class<?> replyClass;
-        private RequestHandlerConnector requestHandlerConnector;
+        private int slot;
         private Registration registrationHandle;
         private OptionMap optionMap;
 
@@ -153,39 +152,39 @@
         }
 
         /**
-         * Get the option map.
+         * Get the slot of the service.
          *
-         * @return the option map
+         * @return the slot
          */
-        public OptionMap getOptionMap() {
-            return optionMap;
+        public int getSlot() {
+            return slot;
         }
 
         /**
-         * Set the option map.
+         * Set the slot of the service.
          *
-         * @param optionMap the option map
+         * @param slot the slot
          */
-        public void setOptionMap(final OptionMap optionMap) {
-            this.optionMap = optionMap;
+        public void setSlot(final int slot) {
+            this.slot = slot;
         }
 
         /**
-         * Get the request handler source.
+         * Get the option map.
          *
-         * @return the request handler source
+         * @return the option map
          */
-        public RequestHandlerConnector getRequestHandlerConnector() {
-            return requestHandlerConnector;
+        public OptionMap getOptionMap() {
+            return optionMap;
         }
 
         /**
-         * Set the request handler source.
+         * Set the option map.
          *
-         * @param requestHandlerConnector the request handler source
+         * @param optionMap the option map
          */
-        public void setRequestHandlerConnector(final RequestHandlerConnector requestHandlerConnector) {
-            this.requestHandlerConnector = requestHandlerConnector;
+        public void setOptionMap(final OptionMap optionMap) {
+            this.optionMap = optionMap;
         }
 
         /**

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceURI.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceURI.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/ServiceURI.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -136,7 +136,7 @@
      */
     public static URI create(String serviceType, String groupName, String endpointName) {
         try {
-            StringBuilder builder = new StringBuilder(serviceType.length() + groupName.length() + endpointName.length() + 2);
+            StringBuilder builder = new StringBuilder(32);
             if (serviceType != null && serviceType.length() > 0) {
                 builder.append(serviceType);
             }

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/SimpleCloseable.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/SimpleCloseable.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/SimpleCloseable.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -1,29 +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;
-
-/**
- * A simple close-only handle.
- */
-public interface SimpleCloseable extends HandleableCloseable<SimpleCloseable> {
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/TypedRequest.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/TypedRequest.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/TypedRequest.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -34,9 +34,12 @@
 public interface TypedRequest<I, O> {
 
     /**
-     * Get the reply type class for this request type.
+     * Check the reply type.  If the reply type is incorrect in any way, a {@code java.lang.ClassCastException} is
+     * thrown.
      *
-     * @return the reply type's class
+     * @param reply the raw reply
+     * @return the typesafe reply
+     * @throws ClassCastException if a type conversion error occurs
      */
-    Class<O> getReplyClass();
+    O castReply(Object reply) throws ClassCastException;
 }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Version.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Version.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/Version.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -35,9 +35,18 @@
     /**
      * The version.
      */
-    public static final String VERSION = "3.1.0.CR1";
+    public static final String VERSION = getVersionString();
 
     /**
+     * Get the version string.
+     *
+     * @return the version string
+     */
+    static String getVersionString() {
+        return "TRUNK SNAPSHOT";
+    }
+
+    /**
      * Print the version to {@code System.out}.
      *
      * @param args ignored

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/InetAddressPrincipal.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/InetAddressPrincipal.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/InetAddressPrincipal.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,119 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.security;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.security.Principal;
+
+/**
+ * A principal representing an IP address.
+ */
+public final class InetAddressPrincipal implements Principal, Cloneable {
+    private final InetAddress inetAddress;
+
+    /**
+     * Create a new instance.
+     *
+     * @param inetAddress the address
+     */
+    public InetAddressPrincipal(final InetAddress inetAddress) {
+        if (inetAddress == null) {
+            throw new IllegalArgumentException("inetAddress is null");
+        }
+        try {
+            this.inetAddress = InetAddress.getByAddress(inetAddress.getHostAddress(), inetAddress.getAddress());
+        } catch (UnknownHostException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    /**
+     * Get the name of this principal; it will be the string representation of the IP address.
+     *
+     * @return the name of this principal
+     */
+    public String getName() {
+        return inetAddress.getHostAddress();
+    }
+
+    /**
+     * Get the IP address of this principal.
+     *
+     * @return the address
+     */
+    public InetAddress getInetAddress() {
+        return inetAddress;
+    }
+
+    /**
+     * Determine whether this instance is equal to another.
+     *
+     * @param other the other instance
+     * @return {@code true} if they are equal, {@code false} otherwise
+     */
+    public boolean equals(final Object other) {
+        return other instanceof InetAddressPrincipal && equals((InetAddressPrincipal) other);
+    }
+
+    /**
+     * Determine whether this instance is equal to another.
+     *
+     * @param other the other instance
+     * @return {@code true} if they are equal, {@code false} otherwise
+     */
+    public boolean equals(final InetAddressPrincipal other) {
+        return other != null && inetAddress.equals(other.inetAddress);
+    }
+
+    /**
+     * Get the hash code for this instance.  It will be equal to the hash code of the {@code InetAddress} object herein.
+     *
+     * @return the hash code
+     */
+    public int hashCode() {
+        return inetAddress.hashCode();
+    }
+
+    /**
+     * Get a human-readable representation of this principal.
+     *
+     * @return the string
+     */
+    public String toString() {
+        return "InetAddressPrincipal <" + inetAddress.toString() + ">";
+    }
+
+    /**
+     * Create a clone of this instance.
+     *
+     * @return the clone
+     */
+    public InetAddressPrincipal clone() {
+        try {
+            return (InetAddressPrincipal) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+}

Copied: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/RemotingPermission.java (from rev 5591, remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/EndpointPermission.java)
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/RemotingPermission.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/RemotingPermission.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,61 @@
+/*
+ * 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.security;
+
+import java.security.BasicPermission;
+
+/**
+ * This class is for permissions relating to Remoting endpoints.
+ */
+public class RemotingPermission extends BasicPermission {
+
+    private static final long serialVersionUID = 4984517897378387571L;
+
+    /**
+     * Creates a new {@code EndpointPermission} object with the specified name.
+     * The name is the symbolic name of the {@code EndpointPermission}.
+     *
+     * @param name the name of the {@code EndpointPermission}
+     *
+     * @throws NullPointerException if {@code name} is {@code null}
+     * @throws IllegalArgumentException if {@code name} is empty
+     */
+    public RemotingPermission(String name) throws NullPointerException, IllegalArgumentException {
+        super(name);
+    }
+
+    /**
+     * Creates a new {@code EndpointPermission} object with the specified name.
+     * The name is the symbolic name of the {@code EndpointPermission}, and the
+     * actions string is currently unused.
+     *
+     * @param name the name of the {@code EndpointPermission}
+     * @param actions ignored
+     *
+     * @throws NullPointerException if {@code name} is {@code null}
+     * @throws IllegalArgumentException if {@code name} is empty
+     */
+    public RemotingPermission(String name, String actions) throws NullPointerException, IllegalArgumentException {
+        super(name, actions);
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/SimpleClientCallbackHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/SimpleClientCallbackHandler.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/security/SimpleClientCallbackHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,108 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.security;
+
+import java.io.IOException;
+import org.jboss.xnio.log.Logger;
+
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.TextOutputCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+import javax.security.sasl.RealmCallback;
+import javax.security.sasl.RealmChoiceCallback;
+
+/**
+ * A callback handler which performs client authentication steps.
+ */
+public class SimpleClientCallbackHandler implements CallbackHandler {
+
+    private static final Logger log = Logger.getLogger("org.jboss.remoting.security.client");
+
+    private final String actualUserName;
+    private final String actualUserRealm;
+    private final char[] password;
+
+    /**
+     * An empty password array.
+     */
+    public static final char[] EMPTY_PASSWORD = new char[0];
+
+    /**
+     * Create a new instance.
+     *
+     * @param actualUserName the user name to supply, or {@code null} for none
+     * @param actualUserRealm the user realm to supply, or {@code null} for none
+     * @param password the password to supply, or {@code null} for none
+     */
+    public SimpleClientCallbackHandler(final String actualUserName, final String actualUserRealm, final char[] password) {
+        this.actualUserName = actualUserName;
+        this.actualUserRealm = actualUserRealm;
+        this.password = password;
+    }
+
+    /**
+     * Handle the array of given callbacks.
+     *
+     * @param callbacks the callbacks to handle
+     * @throws UnsupportedCallbackException if a callback is unsupported
+     */
+    public void handle(final Callback[] callbacks) throws UnsupportedCallbackException {
+        MAIN: for (Callback callback : callbacks) {
+            if (callback instanceof NameCallback && actualUserName != null) {
+                final NameCallback nameCallback = (NameCallback) callback;
+                nameCallback.setName(actualUserName);
+            } else if (callback instanceof RealmCallback && actualUserRealm != null) {
+                final RealmCallback realmCallback = (RealmCallback) callback;
+                realmCallback.setText(actualUserRealm);
+            } else if (callback instanceof RealmChoiceCallback && actualUserRealm != null) {
+                final RealmChoiceCallback realmChoiceCallback = (RealmChoiceCallback) callback;
+                final String[] choices = realmChoiceCallback.getChoices();
+                for (int i = 0; i < choices.length; i++) {
+                    if (choices[i] != null && choices[i].equals(actualUserRealm)) {
+                        realmChoiceCallback.setSelectedIndex(i);
+                        continue MAIN;
+                    }
+                }
+                throw new UnsupportedCallbackException(callback, "No realm choices match realm '" + actualUserRealm + "'");
+            } else if (callback instanceof TextOutputCallback) {
+                final TextOutputCallback textOutputCallback = (TextOutputCallback) callback;
+                final String kind;
+                switch (textOutputCallback.getMessageType()) {
+                    case TextOutputCallback.ERROR: kind = "ERROR"; break;
+                    case TextOutputCallback.INFORMATION: kind = "INFORMATION"; break;
+                    case TextOutputCallback.WARNING: kind = "WARNING"; break;
+                    default: kind = "UNKNOWN"; break;
+                }
+                log.debug("Authentication layer produced a %s message: %s", kind, textOutputCallback.getMessage());
+            } else if (callback instanceof PasswordCallback && password != null) {
+                final PasswordCallback passwordCallback = (PasswordCallback) callback;
+                passwordCallback.setPassword(password);
+            } else {
+                throw new UnsupportedCallbackException(callback);
+            }
+        }
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/Services.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/Services.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/Services.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,31 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.service;
+
+public final class Services {
+    public static final int LOCATE_SERVICE = 1;
+    public static final int SERVICE_CLASS_LOOKUP = 2;
+
+    private Services() {
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/ClassLookupRequest.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/ClassLookupRequest.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/ClassLookupRequest.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.service.classtable;
+
+import java.io.Serializable;
+
+public final class ClassLookupRequest implements Serializable {
+
+    private static final long serialVersionUID = -2642558538967065976L;
+
+    private final int id;
+
+    public ClassLookupRequest(final int id) {
+        this.id = id;
+    }
+
+    public int getId() {
+        return id;
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/ClassLookupResponse.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/ClassLookupResponse.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/ClassLookupResponse.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,40 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.service.classtable;
+
+import java.io.Serializable;
+
+public final class ClassLookupResponse implements Serializable {
+
+    private static final long serialVersionUID = -7032893320952114274L;
+
+    private final Class<?> resolvedClass;
+
+    public ClassLookupResponse(final Class<?> resolvedClass) {
+        this.resolvedClass = resolvedClass;
+    }
+
+    public Class<?> getResolvedClass() {
+        return resolvedClass;
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/package-info.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/package-info.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/classtable/package-info.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,27 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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 for the class lookup table service classes.  This service is used to cache classes referenced by requests and
+ * replies on this connection.
+ */
+package org.jboss.remoting3.service.classtable;

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/ServiceReply.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/ServiceReply.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/ServiceReply.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,56 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.service.locator;
+
+import java.io.Serializable;
+
+public final class ServiceReply<I, O> implements Serializable {
+
+    private static final long serialVersionUID = 5722718939504235368L;
+
+    private final int slot;
+    private final Class<I> actualRequestClass;
+    private final Class<O> actualReplyClass;
+
+    public ServiceReply(final int slot, final Class<I> actualRequestClass, final Class<O> actualReplyClass) {
+        this.slot = slot;
+        this.actualRequestClass = actualRequestClass;
+        this.actualReplyClass = actualReplyClass;
+    }
+
+    public static <I, O> ServiceReply<I, O> create(final int slot, final Class<I> actualRequestClass, final Class<O> actualReplyClass) {
+        return new ServiceReply<I,O>(slot, actualRequestClass, actualReplyClass);
+    }
+
+    public int getSlot() {
+        return slot;
+    }
+
+    public Class<I> getActualRequestClass() {
+        return actualRequestClass;
+    }
+
+    public Class<O> getActualReplyClass() {
+        return actualReplyClass;
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/ServiceRequest.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/ServiceRequest.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/ServiceRequest.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,114 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.service.locator;
+
+import java.io.Serializable;
+import org.jboss.remoting3.TypedRequest;
+
+/**
+ * A request to open a {@code Client} with the given service type and optional group name.
+ *
+ * @param <I> the expected request type
+ * @param <O> the expected reply type
+ */
+public final class ServiceRequest<I, O> implements Serializable, TypedRequest<ServiceRequest<I, O>, ServiceReply<I, O>> {
+
+    private static final long serialVersionUID = -1369189420414317503L;
+
+    private final String serviceType;
+    private final String groupName;
+    private final Class<I> expectedRequestClass;
+    private final Class<O> expectedReplyClass;
+
+    /**
+     * Construct a new instance.
+     *
+     * @param serviceType the service type
+     * @param groupName the optional group name ({@code null} means unspecified)
+     * @param expectedRequestClass the expected request class
+     * @param expectedReplyClass the expected reply class
+     */
+    public ServiceRequest(final String serviceType, final String groupName, final Class<I> expectedRequestClass, final Class<O> expectedReplyClass) {
+        if (serviceType == null) {
+            throw new IllegalArgumentException("serviceType is null");
+        }
+        if (expectedRequestClass == null) {
+            throw new IllegalArgumentException("expectedRequestClass is null");
+        }
+        if (expectedReplyClass == null) {
+            throw new IllegalArgumentException("expectedReplyClass is null");
+        }
+        this.serviceType = serviceType;
+        this.groupName = groupName;
+        this.expectedRequestClass = expectedRequestClass;
+        this.expectedReplyClass = expectedReplyClass;
+    }
+
+    /**
+     * Get the service type.
+     *
+     * @return the service type
+     */
+    public String getServiceType() {
+        return serviceType;
+    }
+
+    /**
+     * Get the group name.
+     *
+     * @return the group name, or {@code null} if it wasn't specified
+     */
+    public String getGroupName() {
+        return groupName;
+    }
+
+    /**
+     * Get the expected request class.
+     *
+     * @return the expected request class
+     */
+    public Class<I> getExpectedRequestClass() {
+        return expectedRequestClass;
+    }
+
+    /**
+     * Get the expected reply class.
+     *
+     * @return the expected reply class
+     */
+    public Class<O> getExpectedReplyClass() {
+        return expectedReplyClass;
+    }
+
+    /**
+     * {@inheritDoc}  This implementation verifies that the request and reply classes are compatible with the
+     * given reply object.
+     */
+    @SuppressWarnings({ "unchecked" })
+    public ServiceReply<I, O> castReply(final Object reply) throws ClassCastException {
+        ServiceReply<?, ?> roughReply = (ServiceReply<?, ?>) reply;
+        roughReply.getActualRequestClass().asSubclass(expectedRequestClass);
+        expectedReplyClass.asSubclass(roughReply.getActualReplyClass());
+        return (ServiceReply<I, O>) roughReply;
+    }
+}

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/package-info.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/package-info.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/locator/package-info.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,27 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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 for the service location service classes.  This service is used to find other services by type and group
+ * name.
+ */
+package org.jboss.remoting3.service.locator;
\ No newline at end of file

Added: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/package-info.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/package-info.java	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/service/package-info.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,26 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2010, 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.
+ */
+
+/**
+ * Container package for well-known Remoting services.
+ */
+package org.jboss.remoting3.service;
\ No newline at end of file

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractHandleableCloseable.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -101,7 +101,7 @@
     /**
      * {@inheritDoc}
      */
-    public final void close() throws IOException {
+    public void close() throws IOException {
         final Map<Key, CloseHandler<? super T>> closeHandlers;
         synchronized (closeLock) {
             if (closed) {
@@ -118,8 +118,8 @@
                     runCloseTask(executor, new CloseHandlerTask(handler));
                 }
             }
-            closeAction();
         }
+        closeAction();
     }
 
     /**

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractSimpleCloseable.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractSimpleCloseable.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/AbstractSimpleCloseable.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -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.spi;
-
-import java.util.concurrent.Executor;
-import org.jboss.remoting3.SimpleCloseable;
-
-/**
- * An abstract simple closeable implementation.
- */
-public abstract class AbstractSimpleCloseable extends AbstractHandleableCloseable<SimpleCloseable> implements SimpleCloseable {
-
-    /**
-     * Basic constructor.
-     *
-     * @param executor the executor used to execute the close notification handlers
-     */
-    protected AbstractSimpleCloseable(final Executor executor) {
-        super(executor);
-    }
-}

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandler.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandler.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -34,12 +34,11 @@
     /**
      * Open a request handler.
      *
-     * @param serviceType the service type
-     * @param groupName the group name
+     * @param slot the target slot
      * @param result the result for the connected request handler
      * @return a handle which may be used to cancel the pending operation
      */
-    Cancellable open(String serviceType, String groupName, Result<RequestHandler> result);
+    Cancellable open(int slot, Result<RequestHandler> result);
 
     /**
      * Create a connector which may be used to communicate with the given local RequestHandler.  The connector

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandlerContext.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandlerContext.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionHandlerContext.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -22,6 +22,7 @@
 
 package org.jboss.remoting3.spi;
 
+import java.io.IOException;
 import org.jboss.xnio.OptionMap;
 
 /**
@@ -39,16 +40,16 @@
     ConnectionProviderContext getConnectionProviderContext();
 
     /**
-     * Open a service.
+     * Open a service.  This method should return immediately.
      *
      * @remoting.nonblocking
      *
-     * @param serviceType the service type
-     * @param groupName the service group name
-     * @param optionMap the open options
-     * @param serviceResult the result of the service open
+     * @param slotId the service slot ID
+     * @param optionMap the options to pass to the service
+     * @return the new request handler
+     * @throws IOException if an error occurs
      */
-    void openService(String serviceType, String groupName, OptionMap optionMap, ServiceResult serviceResult);
+    RequestHandler openService(int slotId, OptionMap optionMap) throws IOException;
 
     /**
      * Indicate that the remote side has terminated the connection, so the local side should be closed as well.

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/ConnectionProviderContext.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -22,7 +22,6 @@
 
 package org.jboss.remoting3.spi;
 
-import org.jboss.remoting3.HandleableCloseable;
 import java.util.Map;
 import java.util.concurrent.Executor;
 
@@ -32,7 +31,7 @@
  *
  * @remoting.consume
  */
-public interface ConnectionProviderContext extends HandleableCloseable<ConnectionProviderContext> {
+public interface ConnectionProviderContext {
 
     /**
      * Get the endpoint's executor.

Deleted: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RemoteRequestContext.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RemoteRequestContext.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RemoteRequestContext.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -1,37 +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 org.jboss.xnio.Cancellable;
-
-/**
- * The context of an outstanding remote request.  This instance should be discarded when a reply (of any sort)
- * is received for the request.
- */
-public interface RemoteRequestContext extends Cancellable {
-
-    /**
-     * Signal that the request should be cancelled, if possible.
-     */
-    RemoteRequestContext cancel();
-}

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/RequestHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -23,6 +23,7 @@
 package org.jboss.remoting3.spi;
 
 import org.jboss.remoting3.HandleableCloseable;
+import org.jboss.xnio.Cancellable;
 
 /**
  * A request handler.
@@ -41,7 +42,7 @@
      *
      * @param request the request
      * @param replyHandler a handler for the reply
-     * @return a context which may be used to cancel the request
+     * @return a reference which may be used to cancel the request
      */
-    RemoteRequestContext receiveRequest(Object request, ReplyHandler replyHandler);
+    Cancellable receiveRequest(Object request, ReplyHandler replyHandler);
 }

Modified: remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/SpiUtils.java
===================================================================
--- remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/SpiUtils.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/main/java/org/jboss/remoting3/spi/SpiUtils.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -23,15 +23,9 @@
 package org.jboss.remoting3.spi;
 
 import java.io.IOException;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Modifier;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
 import org.jboss.remoting3.CloseHandler;
 import org.jboss.remoting3.RequestCancelHandler;
 import org.jboss.remoting3.RequestContext;
-import org.jboss.xnio.IoFuture;
 import org.jboss.xnio.log.Logger;
 
 /**
@@ -51,7 +45,7 @@
      */
     public static void safeHandleException(final ReplyHandler replyHandler, final IOException exception) {
         try {
-            replyHandler.handleException(exception);
+            if (replyHandler != null) replyHandler.handleException(exception);
         } catch (Throwable t) {
             heLog.debug(t, "Failed to properly handle exception");
         }
@@ -66,7 +60,7 @@
      */
     public static <O> void safeHandleReply(final ReplyHandler replyHandler, final O reply) {
         try {
-            replyHandler.handleReply(reply);
+            if (replyHandler != null) replyHandler.handleReply(reply);
         } catch (Throwable t) {
             heLog.debug(t, "Failed to properly handle reply");
         }
@@ -79,7 +73,7 @@
      */
     public static void safeHandleCancellation(final ReplyHandler replyHandler) {
         try {
-            replyHandler.handleCancellation();
+            if (replyHandler != null) replyHandler.handleCancellation();
         } catch (Throwable t) {
             heLog.debug(t, "Failed to properly handle cancellation");
         }
@@ -94,7 +88,7 @@
      */
     public static <O> void safeNotifyCancellation(final RequestCancelHandler<O> handler, final RequestContext<O> requestContext) {
         try {
-            handler.notifyCancel(requestContext);
+            if (handler != null && requestContext != null) handler.notifyCancel(requestContext);
         } catch (Throwable t) {
             heLog.error(t, "Request cancel handler threw an exception");
         }
@@ -109,27 +103,10 @@
      */
     public static <T> void safeHandleClose(final CloseHandler<? super T> handler, final T closed) {
         try {
-            handler.handleClose(closed);
+            if (handler != null && closed != null) handler.handleClose(closed);
         } catch (Throwable t) {
             heLog.error(t, "Close handler threw an exception");
         }
     }
-
-    /**
-     * Get a remote request context that simply ignores a cancel request.
-     *
-     * @return a blank remote request context
-     */
-    public static RemoteRequestContext getBlankRemoteRequestContext() {
-        return BLANK_REMOTE_REQUEST_CONTEXT;
-    }
-
-    private static final RemoteRequestContext BLANK_REMOTE_REQUEST_CONTEXT = new BlankRemoteRequestContext();
-
-    private static final class BlankRemoteRequestContext implements RemoteRequestContext {
-        public RemoteRequestContext cancel() {
-            return this;
-        }
-    }
 }
 

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/EndpointTestCase.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -161,8 +161,10 @@
                     return new RequestListener<Object, Object>() {
                         public void handleRequest(final RequestContext<Object> objectRequestContext, final Object request) throws RemoteExecutionException {
                             try {
+                                log.info("Got request %s, sending reply %s", request, replyObj);
                                 objectRequestContext.sendReply(replyObj);
                             } catch (IOException e) {
+                                log.error(e, "reply");
                                 throw new RemoteExecutionException(e);
                             }
                         }

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	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/jboss-remoting/src/test/java/org/jboss/remoting3/spi/CloseableTestCase.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -44,7 +44,7 @@
         try {
             final AtomicBoolean closed = new AtomicBoolean();
             final CountDownLatch latch = new CountDownLatch(1);
-            final AbstractSimpleCloseable closeable = new AbstractSimpleCloseable(executorService) {
+            final AbstractHandleableCloseable<?> closeable = new AbstractHandleableCloseable(executorService) {
                 // empty
             };
             try {

Added: remoting3/trunk/jboss-remoting/src/test/resources/logging.properties
===================================================================
--- remoting3/trunk/jboss-remoting/src/test/resources/logging.properties	                        (rev 0)
+++ remoting3/trunk/jboss-remoting/src/test/resources/logging.properties	2010-02-23 23:49:39 UTC (rev 5755)
@@ -0,0 +1,46 @@
+#
+# JBoss, Home of Professional Open Source
+# Copyright 2010, 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.
+#
+
+# Additional logger names to configure (root logger is always configured)
+#loggers=org.foo.bar, org.foo.baz
+
+# Root logger level
+logger.level=TRACE
+
+# Declare handlers for the root logger
+logger.handlers=CONSOLE
+
+# Declare handlers for additional loggers
+#logger.org.foo.bar.handlers=XXX, YYY
+
+# Console handler configuration
+handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
+handler.CONSOLE.target=SYSTEM_ERR
+handler.CONSOLE.properties=autoFlush
+handler.CONSOLE.level=TRACE
+handler.CONSOLE.autoFlush=true
+handler.CONSOLE.formatter=PATTERN
+
+# The log format pattern for both logs
+formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
+formatter.PATTERN.properties=pattern
+formatter.PATTERN.pattern=%d{HH:mm:ss,SSS} %-5p (%t) [%c] %m%n

Modified: remoting3/trunk/pom.xml
===================================================================
--- remoting3/trunk/pom.xml	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/pom.xml	2010-02-23 23:49:39 UTC (rev 5755)
@@ -29,6 +29,10 @@
     <name>JBoss Remoting Parent</name>
     <description>JBoss Remoting Parent POM</description>
 
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
     <groupId>org.jboss.remoting</groupId>
     <artifactId>jboss-remoting-all</artifactId>
     <packaging>pom</packaging>

Modified: remoting3/trunk/samples/pom.xml
===================================================================
--- remoting3/trunk/samples/pom.xml	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/samples/pom.xml	2010-02-23 23:49:39 UTC (rev 5755)
@@ -29,6 +29,10 @@
     <name>JBoss Remoting Samples</name>
     <description>JBoss Remoting Samples</description>
 
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
     <groupId>org.jboss.remoting</groupId>
     <artifactId>jboss-remoting-samples</artifactId>
     <packaging>jar</packaging>

Modified: remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/client/SocketClientConnectionHandler.java
===================================================================
--- remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/client/SocketClientConnectionHandler.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/client/SocketClientConnectionHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -76,7 +76,7 @@
       } 
    }
 
-   public Cancellable open(String serviceName, String groupName, Result<RequestHandler> result) {
+   public Cancellable open(int slot, Result<RequestHandler> result) {
       try
       {
          final Socket socket = new Socket(remoteHost, remotePort);
@@ -86,8 +86,7 @@
          final Marshaller marshaller = factory.createMarshaller(configuration);
          final Unmarshaller unmarshaller = factory.createUnmarshaller(configuration);
          marshaller.start(Marshalling.createByteOutput(socket.getOutputStream()));
-         marshaller.writeUTF(serviceName);
-         marshaller.writeUTF(groupName);
+         marshaller.writeInt(slot);
          marshaller.flush();
          unmarshaller.start(Marshalling.createByteInput(socket.getInputStream()));
          result.setResult(new SocketClientRequestHandler(getExecutor(), marshaller, unmarshaller));

Modified: remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/client/SocketClientRequestHandler.java
===================================================================
--- remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/client/SocketClientRequestHandler.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/client/SocketClientRequestHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -27,10 +27,10 @@
 import org.jboss.marshalling.Marshaller;
 import org.jboss.marshalling.Unmarshaller;
 import org.jboss.remoting3.spi.AbstractHandleableCloseable;
-import org.jboss.remoting3.spi.RemoteRequestContext;
 import org.jboss.remoting3.spi.ReplyHandler;
 import org.jboss.remoting3.spi.RequestHandler;
 import org.jboss.remoting3.spi.SpiUtils;
+import org.jboss.xnio.Cancellable;
 import org.jboss.xnio.IoUtils;
 import org.jboss.xnio.log.Logger;
 
@@ -53,7 +53,7 @@
       this.unmarshaller = unmarshaller;
    }
 
-   public RemoteRequestContext receiveRequest(Object request, final ReplyHandler replyHandler) {
+   public Cancellable receiveRequest(Object request, final ReplyHandler replyHandler) {
       try {
          marshaller.writeObject(request);
          marshaller.flush();
@@ -78,8 +78,8 @@
          }
       });
 
-      return new RemoteRequestContext() {
-         public RemoteRequestContext cancel() {
+      return new Cancellable () {
+         public Cancellable cancel() {
             log.debug("Closing " + SocketClientRequestHandler.this);
             IoUtils.safeClose(SocketClientRequestHandler.this);
             return this;

Modified: remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/server/SocketServerConnectionHandler.java
===================================================================
--- remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/server/SocketServerConnectionHandler.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/server/SocketServerConnectionHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -110,7 +110,7 @@
    }
 
    @Override
-   public Cancellable open(String serviceName, String groupName, Result<RequestHandler> result) {
+   public Cancellable open(int slot, Result<RequestHandler> result) {
       return null;
    }
 

Modified: remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/server/SocketServerRequestHandler.java
===================================================================
--- remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/server/SocketServerRequestHandler.java	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/samples/src/main/java/org/jboss/remoting3/samples/socket/server/SocketServerRequestHandler.java	2010-02-23 23:49:39 UTC (rev 5755)
@@ -32,13 +32,14 @@
 import org.jboss.remoting3.CloseHandler;
 import org.jboss.remoting3.Endpoint;
 import org.jboss.remoting3.ServiceNotFoundException;
+import org.jboss.remoting3.ServiceOpenException;
 import org.jboss.remoting3.ServiceURI;
 import org.jboss.remoting3.samples.socket.RequestHandlerFuture;
 import org.jboss.remoting3.samples.socket.SocketProtocol;
 import org.jboss.remoting3.spi.ConnectionHandlerContext;
-import org.jboss.remoting3.spi.RemoteRequestContext;
 import org.jboss.remoting3.spi.ReplyHandler;
 import org.jboss.remoting3.spi.RequestHandler;
+import org.jboss.xnio.Cancellable;
 import org.jboss.xnio.OptionMap;
 import org.jboss.xnio.log.Logger;
 
@@ -72,8 +73,7 @@
          marshaller.flush();
          unmarshaller = factory.createUnmarshaller(configuration);
          unmarshaller.start(Marshalling.createByteInput(socket.getInputStream()));
-         final String serviceType = unmarshaller.readUTF();
-         final String groupName = unmarshaller.readUTF();
+         final int slot = unmarshaller.readInt();
          final RequestHandlerFuture requestHandlerFuture = new RequestHandlerFuture();
 
          ConnectionHandlerContext.ServiceResult serviceResult = new ConnectionHandlerContext.ServiceResult() {
@@ -81,11 +81,16 @@
                requestHandlerFuture.setResult(requestHandler);
             }
             public void notFound() {
-               requestHandlerFuture.setException(new ServiceNotFoundException(ServiceURI.create(serviceType, groupName, endpoint.getName()), "No such service located"));
+               requestHandlerFuture.setException(new ServiceOpenException("No such service located"));
             }
          };
-
-         connectionHandlerContext.openService(serviceType, groupName, OptionMap.EMPTY, serviceResult);
+         try
+         {
+            requestHandlerFuture.setResult(connectionHandlerContext.openService(slot, OptionMap.EMPTY));
+         } catch (IOException e)
+         {
+             requestHandlerFuture.setException(e);
+         }
          requestHandler = requestHandlerFuture.get();
          if (requestHandler == null) {
             throw requestHandlerFuture.getException();
@@ -142,7 +147,7 @@
 
 
    @Override
-   public RemoteRequestContext receiveRequest(Object request, ReplyHandler replyHandler) {
+   public Cancellable receiveRequest(Object request, ReplyHandler replyHandler) {
       return null;
    }
 

Modified: remoting3/trunk/taglet/pom.xml
===================================================================
--- remoting3/trunk/taglet/pom.xml	2010-02-21 16:02:16 UTC (rev 5754)
+++ remoting3/trunk/taglet/pom.xml	2010-02-23 23:49:39 UTC (rev 5755)
@@ -26,6 +26,10 @@
 
     <modelVersion>4.0.0</modelVersion>
 
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
     <groupId>org.jboss.remoting</groupId>
     <artifactId>jboss-remoting-taglet</artifactId>
     <name>JBoss Remoting Taglet</name>



More information about the jboss-remoting-commits mailing list