[jboss-remoting-commits] JBoss Remoting SVN: r3987 - in remoting3/trunk: http/src/main/java/org/jboss/cx/remoting/http/cookie and 4 other directories.

jboss-remoting-commits at lists.jboss.org jboss-remoting-commits at lists.jboss.org
Mon Apr 14 12:37:33 EDT 2008


Author: david.lloyd at jboss.com
Date: 2008-04-14 12:37:33 -0400 (Mon, 14 Apr 2008)
New Revision: 3987

Added:
   remoting3/trunk/http-urlconnection/src/main/java/org/jboss/cx/remoting/http/urlconnection/HttpUrlChannel.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/OutputAction.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSession.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/Cookie.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieClientSession.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieDomain.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieMatcher.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieParser.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieValidator.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieMatcher.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieParser.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieValidator.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/HttpChannel.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/OutboundHttpChannelProvider.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpChannelContext.java
Removed:
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/id/HttpSubChannelIdentifier.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/id/IdentifierProvider.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/HttpTransporter.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/ReadyNotifier.java
Modified:
   remoting3/trunk/http-se6/src/main/java/org/jboss/cx/remoting/http/se6/ServerInstance.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/Http.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/HttpProtocolSupport.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/AbstractIncomingHttpMessage.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/IncomingHttpMessage.java
   remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpSessionContext.java
Log:
Start on http stuff

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/Http.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/Http.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/Http.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -4,14 +4,11 @@
  *
  */
 public final class Http {
-    public static final String HEADER_SESSION_ID = "JBoss-Remoting-Session-ID";
-    public static final String HEADER_ACK = "JBoss-Remoting-Ack";
-    public static final String HEADER_SEQ = "JBoss-Remoting-Seq";
-
     private Http() {}
 
     enum MessageType {
         SESSION_OPEN,
+        SESSION_JOIN,
         SESSION_CLOSE,
 
         STREAM_OPEN,

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/HttpProtocolSupport.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/HttpProtocolSupport.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/HttpProtocolSupport.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -2,72 +2,131 @@
 
 import java.io.IOException;
 import java.net.URI;
+import java.security.SecureRandom;
+import java.util.Random;
 import java.util.concurrent.ConcurrentMap;
-import java.util.Random;
 import org.jboss.cx.remoting.Endpoint;
 import org.jboss.cx.remoting.RemotingException;
-import org.jboss.cx.remoting.util.CollectionUtil;
-import org.jboss.cx.remoting.util.AttributeMap;
-import org.jboss.cx.remoting.http.spi.RemotingHttpServerContext;
-import org.jboss.cx.remoting.http.spi.RemotingHttpSessionContext;
-import org.jboss.cx.remoting.http.spi.HttpTransporter;
-import org.jboss.cx.remoting.http.spi.IncomingHttpMessage;
+import org.jboss.cx.remoting.spi.Registration;
 import org.jboss.cx.remoting.spi.protocol.ProtocolContext;
 import org.jboss.cx.remoting.spi.protocol.ProtocolHandler;
 import org.jboss.cx.remoting.spi.protocol.ProtocolHandlerFactory;
+import org.jboss.cx.remoting.util.AttributeMap;
+import org.jboss.cx.remoting.util.CollectionUtil;
 
 /**
  *
  */
 public final class HttpProtocolSupport {
-    private final ProtocolHandlerFactory protocolHandlerFactory = new HttpProtocolHandlerFactory();
-    private HttpTransporter httpTransporter;
 
-    private final Endpoint endpoint;
-    // todo - need secure random?
-    private final Random random = new Random();
+    public HttpProtocolSupport() {/* empty */}
 
-    private final ConcurrentMap<String, RemotingHttpSessionContext> sessions = CollectionUtil.concurrentMap();
+    // Accessors: dependency
 
-    public HttpProtocolSupport(final Endpoint endpoint) throws RemotingException {
+    private Endpoint endpoint;
+    private Random random;
+
+    public Endpoint getEndpoint() {
+        return endpoint;
+    }
+
+    public void setEndpoint(final Endpoint endpoint) {
         this.endpoint = endpoint;
-        endpoint.registerProtocol("http", protocolHandlerFactory);
     }
 
-    public void setHttpTransporter(final HttpTransporter httpTransporter) {
-        this.httpTransporter = httpTransporter;
+    public Random getRandom() {
+        return random;
     }
 
-    public RemotingHttpServerContext addServer() {
-        return new RemotingHttpServerContext() {
-            public RemotingHttpSessionContext locateSession(IncomingHttpMessage message) {
-                final String sessionId = message.getFirstHeaderValue(Http.HEADER_SESSION_ID);
-                return sessionId == null ? null : sessions.get(sessionId);
+    public void setRandom(final Random random) {
+        this.random = random;
+    }
+
+    // Accessors: configuration
+    // (none)
+
+    // Lifecycle
+
+    private Registration registration;
+
+    public void create() throws RemotingException {
+        registration = endpoint.registerProtocol("http", new ProtocolHandlerFactory() {
+            public boolean isLocal(final URI uri) {
+                return false;
             }
-        };
+
+            public ProtocolHandler createHandler(final ProtocolContext context, final URI remoteUri, final AttributeMap attributeMap) throws IOException {
+                final RemotingHttpSession session = new RemotingHttpSession();
+                final String sessionId;
+                for (;;) {
+                    final String generatedId = generateSessionId();
+                    if (sessionMap.putIfAbsent(generatedId, session) == null) {
+                        sessionId = generatedId;
+                        break;
+                    }
+                }
+                session.intialize(HttpProtocolSupport.this, sessionId, context);
+                return session.getProtocolHandler();
+            }
+
+            public void close() {
+            }
+        });
+        if (random == null) {
+            random = new SecureRandom();
+        }
     }
 
-    public String generateSessionId() {
-        return Long.toString(random.nextLong());
+    public void start() {
+        registration.start();
     }
 
-    public boolean registerSession(String idStr, RemotingHttpSessionContext context) {
-        return sessions.putIfAbsent(idStr, context) == null;
+    public void stop() {
+        registration.stop();
     }
 
-    public final class HttpProtocolHandlerFactory implements ProtocolHandlerFactory {
-        public boolean isLocal(URI uri) {
-            return false;
+    public void destroy() {
+        try {
+            registration.unregister();
+        } finally {
+            endpoint = null;
+            random = null;
+            registration = null;
         }
+    }
 
-        public ProtocolHandler createHandler(ProtocolContext context, URI remoteUri, final AttributeMap attributeMap) throws IOException {
-            if (httpTransporter == null) {
-                throw new IOException("No ability to initiate an HTTP connection (no transporter available)");
-            }
-            return new RemotingHttpSessionImpl(HttpProtocolSupport.this, context).getProtocolHandler();
+    // Session management
+
+    // todo - weak value concurrent hash map
+    private final ConcurrentMap<String, RemotingHttpSession> sessionMap = CollectionUtil.concurrentMap();
+
+    private String generateSessionId() {
+        final byte[] bytes = new byte[32];
+        StringBuilder builder = new StringBuilder(bytes.length * 2);
+        random.nextBytes(bytes);
+        for (byte b : bytes) {
+            builder.append(Character.digit(b >>> 4 & 15, 16));
+            builder.append(Character.digit(b & 15, 16));
         }
+        return builder.toString();
+    }
 
-        public void close() {
+    // todo - additional marshaller negotiation
+    public void establishInboundSession() throws RemotingException {
+        final RemotingHttpSession session = new RemotingHttpSession();
+        final String sessionId;
+        for (;;) {
+            final String generatedId = generateSessionId();
+            if (sessionMap.putIfAbsent(generatedId, session) == null) {
+                sessionId = generatedId;
+                break;
+            }
         }
+        final ProtocolContext protocolContext = endpoint.openIncomingSession(session.getProtocolHandler());
+        session.intialize(this, sessionId, protocolContext);
     }
+
+    RemotingHttpSession lookupSession(String sessionId) {
+        return sessionMap.get(sessionId);
+    }
 }

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/OutputAction.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/OutputAction.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/OutputAction.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,11 @@
+package org.jboss.cx.remoting.http;
+
+import org.jboss.cx.remoting.spi.ByteMessageOutput;
+import java.io.IOException;
+
+/**
+ *
+ */
+public interface OutputAction {
+    void run(ByteMessageOutput target) throws IOException;
+}

Copied: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSession.java (from rev 3919, remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java)
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSession.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSession.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,293 @@
+package org.jboss.cx.remoting.http;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import org.jboss.cx.remoting.RemoteExecutionException;
+import org.jboss.cx.remoting.http.spi.AbstractOutgoingHttpMessage;
+import org.jboss.cx.remoting.http.spi.IncomingHttpMessage;
+import org.jboss.cx.remoting.http.spi.RemotingHttpSessionContext;
+import org.jboss.cx.remoting.spi.ByteMessageOutput;
+import org.jboss.cx.remoting.spi.ObjectMessageOutput;
+import org.jboss.cx.remoting.spi.protocol.ContextIdentifier;
+import org.jboss.cx.remoting.spi.protocol.ProtocolContext;
+import org.jboss.cx.remoting.spi.protocol.ProtocolHandler;
+import org.jboss.cx.remoting.spi.protocol.RequestIdentifier;
+import org.jboss.cx.remoting.spi.protocol.ServiceIdentifier;
+import org.jboss.cx.remoting.spi.protocol.StreamIdentifier;
+import org.jboss.cx.remoting.util.AtomicStateMachine;
+import static org.jboss.cx.remoting.util.AtomicStateMachine.start;
+import org.jboss.cx.remoting.util.CollectionUtil;
+
+/**
+ *
+ */
+public final class RemotingHttpSession {
+//    private final RemotingHttpSessionContext context = new SessionContext();
+    private ProtocolContext protocolContext;
+    private ProtocolHandler protocolHandler = new ProtocolHandlerImpl();
+    private final BlockingQueue<IncomingHttpMessage> incomingQueue = CollectionUtil.synchronizedQueue(new LinkedList<IncomingHttpMessage>());
+    private final BlockingQueue<OutputAction> outgoingQueue = CollectionUtil.synchronizedQueue(new LinkedList<OutputAction>());
+
+    private String sessionId;
+
+    public void setSessionId(final String sessionId) {
+        this.sessionId = sessionId;
+    }
+
+    public void intialize(final HttpProtocolSupport httpProtocolSupport, final String sessionId, final ProtocolContext protocolContext) {
+        
+    }
+
+    private enum State implements org.jboss.cx.remoting.util.State<State> {
+        INITIAL,
+        UP,
+        DOWN,
+        ;
+
+        public boolean isReachable(final State dest) {
+            return compareTo(dest) < 0;
+        }
+    }
+
+    private final AtomicStateMachine<State> state = start(State.INITIAL);
+
+    private static final int PROTOCOL_VERSION = 0;
+
+    public RemotingHttpSession() {
+    }
+
+    public String getSessionId() {
+        return sessionId;
+    }
+
+    public RemotingHttpSessionContext getContext() {
+//        return context;
+        return null;
+    }
+
+    public ProtocolHandler getProtocolHandler() {
+        return protocolHandler;
+    }
+
+//    private final class SessionContext implements RemotingHttpSessionContext {
+//        private final Set<ReadyNotifier> readyNotifiers = CollectionUtil.synchronizedSet(new HashSet<ReadyNotifier>());
+//
+//        public void queueMessage(IncomingHttpMessage message) {
+//            incomingQueue.add(message);
+//            synchronized(readyNotifiers) {
+//                for (ReadyNotifier notifier : readyNotifiers) {
+//                    notifier.notifyReady(this);
+//                }
+//            }
+//        }
+//
+//        public void addReadyNotifier(ReadyNotifier notifier) {
+//            readyNotifiers.add(notifier);
+//        }
+//
+//        public OutgoingHttpMessage getNextMessageImmediate() {
+//            final List<OutputAction> actions = CollectionUtil.arrayList();
+//            outgoingQueue.drainTo(actions);
+//            if (actions.isEmpty()) {
+//                return null;
+//            }
+//            return new OutgoingActionHttpMessage(actions);
+//        }
+//
+//        public OutgoingHttpMessage getNextMessage(long timeoutMillis) throws InterruptedException {
+//            synchronized(outgoingQueue) {
+//                final OutputAction first = outgoingQueue.poll(timeoutMillis, TimeUnit.MILLISECONDS);
+//                if (first != null) {
+//                    final List<OutputAction> actions = CollectionUtil.arrayList();
+//                    actions.add(first);
+//                    outgoingQueue.drainTo(actions);
+//                    return new OutgoingActionHttpMessage(actions);
+//                } else {
+//                    return null;
+//                }
+//            }
+//        }
+//    }
+
+    private final class ProtocolHandlerImpl implements ProtocolHandler {
+
+        public void sendReply(final ContextIdentifier remoteContextIdentifier, final RequestIdentifier requestIdentifier, final Object reply) throws IOException {
+        }
+
+        public void sendException(final ContextIdentifier remoteContextIdentifier, final RequestIdentifier requestIdentifier, final RemoteExecutionException exception) throws IOException {
+        }
+
+        public void sendCancelAcknowledge(final ContextIdentifier remoteContextIdentifier, final RequestIdentifier requestIdentifier) throws IOException {
+        }
+
+        public void sendServiceClosing(final ServiceIdentifier remoteServiceIdentifier) throws IOException {
+        }
+
+        public void sendContextClosing(final ContextIdentifier remoteContextIdentifier, final boolean done) throws IOException {
+        }
+
+        public ContextIdentifier getLocalRootContextIdentifier() {
+            return null;
+        }
+
+        public ContextIdentifier getRemoteRootContextIdentifier() {
+            return null;
+        }
+
+        public ContextIdentifier openContext(final ServiceIdentifier serviceIdentifier) throws IOException {
+            return null;
+        }
+
+        public void sendContextClose(final ContextIdentifier contextIdentifier, final boolean immediate, final boolean cancel, final boolean interrupt) throws IOException {
+        }
+
+        public RequestIdentifier openRequest(final ContextIdentifier contextIdentifier) throws IOException {
+            return null;
+        }
+
+        public void sendServiceClose(final ServiceIdentifier serviceIdentifier) throws IOException {
+        }
+
+        public void sendRequest(final ContextIdentifier contextIdentifier, final RequestIdentifier requestIdentifier, final Object request, final Executor streamExecutor) throws IOException {
+        }
+
+        public void sendCancelRequest(final ContextIdentifier contextIdentifier, final RequestIdentifier requestIdentifier, final boolean mayInterrupt) throws IOException {
+        }
+
+        public ContextIdentifier openContext() throws IOException {
+            return null;
+        }
+
+        public ServiceIdentifier openService() throws IOException {
+            return null;
+        }
+
+        public StreamIdentifier openStream() throws IOException {
+            return null;
+        }
+
+        public void closeStream(final StreamIdentifier streamIdentifier) throws IOException {
+        }
+
+        public ObjectMessageOutput sendStreamData(final StreamIdentifier streamIdentifier, final long sequence, final Executor streamExecutor) throws IOException {
+            return null;
+        }
+
+        public void closeSession() throws IOException {
+        }
+
+        public String getRemoteEndpointName() {
+            return null;
+        }
+    }
+
+    public class BufferedByteMessageOutput implements ByteMessageOutput, OutputAction {
+        private final int bufsize;
+        private final List<byte[]> bufferList = new ArrayList<byte[]>();
+        private int sizeOfLast;
+
+        public BufferedByteMessageOutput(final int bufsize) {
+            this.bufsize = bufsize;
+        }
+
+        public void write(int b) throws IOException {
+            final byte[] last = bufferList.get(bufferList.size());
+            if (sizeOfLast == last.length) {
+                final byte[] bytes = new byte[bufsize];
+                bufferList.add(bytes);
+                bytes[0] = (byte) b;
+                sizeOfLast = 1;
+            } else {
+                last[sizeOfLast++] = (byte) b;
+            }
+        }
+
+        public void write(byte[] b) throws IOException {
+            write(b, 0, b.length);
+        }
+
+        public void write(byte[] b, int offs, int len) throws IOException {
+            byte[] bytes = bufferList.get(bufferList.size());
+            while (len > 0) {
+                final int copySize = bytes.length - sizeOfLast;
+                if (len <= copySize) {
+                    System.arraycopy(b, offs, bytes, sizeOfLast, len);
+                    sizeOfLast += len;
+                    return;
+                } else {
+                    System.arraycopy(b, offs, bytes, sizeOfLast, copySize);
+                    bytes = new byte[bufsize];
+                    bufferList.add(bytes);
+                    sizeOfLast = 0;
+                    len -= copySize;
+                    offs += copySize;
+                }
+            }
+        }
+
+        public void commit() throws IOException {
+            outgoingQueue.add(this);
+        }
+
+        public int getBytesWritten() throws IOException {
+            Iterator<byte[]> it = bufferList.iterator();
+            if (! it.hasNext()) {
+                return 0;
+            }
+            int t = 0;
+            for (;;) {
+                byte[] b = it.next();
+                if (it.hasNext()) {
+                    t += b.length;
+                } else {
+                    return t + sizeOfLast;
+                }
+            }
+        }
+
+        public void close() throws IOException {
+            bufferList.clear();
+        }
+
+        public void flush() throws IOException {
+        }
+
+        public void run(ByteMessageOutput output) throws IOException {
+            final Iterator<byte[]> iterator = bufferList.iterator();
+            if (! iterator.hasNext()) {
+                return;
+            }
+            for (;;) {
+                byte[] bytes = iterator.next();
+                if (iterator.hasNext()) {
+                    output.write(bytes);
+                } else {
+                    output.write(bytes, 0, sizeOfLast);
+                    return;
+                }
+            }
+        }
+    }
+
+    private final class OutgoingActionHttpMessage extends AbstractOutgoingHttpMessage {
+        private final List<OutputAction> actions;
+
+        public OutgoingActionHttpMessage(final List<OutputAction> actions) {
+            this.actions = actions;
+        }
+
+        public void writeMessageData(ByteMessageOutput byteOutput) throws IOException {
+            final ObjectMessageOutput msgOut = protocolContext.getMessageOutput(byteOutput);
+            msgOut.writeInt(PROTOCOL_VERSION);
+            msgOut.commit();
+            for (OutputAction action : actions) {
+                action.run(byteOutput);
+            }
+        }
+    }
+}

Deleted: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/RemotingHttpSessionImpl.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -1,439 +0,0 @@
-package org.jboss.cx.remoting.http;
-
-import org.jboss.cx.remoting.http.spi.RemotingHttpSessionContext;
-import org.jboss.cx.remoting.http.spi.IncomingHttpMessage;
-import org.jboss.cx.remoting.http.spi.ReadyNotifier;
-import org.jboss.cx.remoting.http.spi.OutgoingHttpMessage;
-import org.jboss.cx.remoting.http.spi.AbstractOutgoingHttpMessage;
-import org.jboss.cx.remoting.util.CollectionUtil;
-import org.jboss.cx.remoting.spi.ObjectMessageOutput;
-import org.jboss.cx.remoting.spi.ByteMessageOutput;
-import org.jboss.cx.remoting.spi.protocol.ProtocolContext;
-import org.jboss.cx.remoting.spi.protocol.ProtocolHandler;
-import org.jboss.cx.remoting.spi.protocol.ServiceIdentifier;
-import org.jboss.cx.remoting.spi.protocol.ContextIdentifier;
-import org.jboss.cx.remoting.spi.protocol.RequestIdentifier;
-import org.jboss.cx.remoting.spi.protocol.StreamIdentifier;
-import org.jboss.cx.remoting.RemoteExecutionException;
-
-import java.util.LinkedList;
-import java.util.Set;
-import java.util.HashSet;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.concurrent.Executor;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicLong;
-import java.io.IOException;
-import java.io.ObjectInput;
-import java.io.ObjectOutput;
-
-/**
- *
- */
-public final class RemotingHttpSessionImpl {
-    private final RemotingHttpSessionContext context = new SessionContext();
-    private final ProtocolContext protocolContext;
-    private final ProtocolHandler protocolHandler = new ProtocolHandlerImpl();
-    private final BlockingQueue<IncomingHttpMessage> incomingQueue = CollectionUtil.synchronizedQueue(new LinkedList<IncomingHttpMessage>());
-    private final BlockingQueue<OutputAction> outgoingQueue = CollectionUtil.synchronizedQueue(new LinkedList<OutputAction>());
-    private final String sessionId;
-    private final AtomicLong outputSequence = new AtomicLong(0L);
-    private final AtomicLong inputSequence = new AtomicLong(0L);
-
-    private static final int PROTOCOL_VERSION = 0;
-
-    public RemotingHttpSessionImpl(final HttpProtocolSupport protocolSupport, final ProtocolContext protocolContext) {
-        this.protocolContext = protocolContext;
-        String sessionId;
-        do {
-            sessionId = protocolSupport.generateSessionId();
-        } while (! protocolSupport.registerSession(sessionId, context));
-        this.sessionId = sessionId;
-    }
-
-    public String getSessionId() {
-        return sessionId;
-    }
-
-    public RemotingHttpSessionContext getContext() {
-        return context;
-    }
-
-    public ProtocolHandler getProtocolHandler() {
-        return protocolHandler;
-    }
-
-    private final class SessionContext implements RemotingHttpSessionContext {
-        private final Set<ReadyNotifier> readyNotifiers = CollectionUtil.synchronizedSet(new HashSet<ReadyNotifier>());
-
-        public void queueMessage(IncomingHttpMessage message) {
-            incomingQueue.add(message);
-            synchronized(readyNotifiers) {
-                for (ReadyNotifier notifier : readyNotifiers) {
-                    notifier.notifyReady(this);
-                }
-            }
-        }
-
-        public void addReadyNotifier(ReadyNotifier notifier) {
-            readyNotifiers.add(notifier);
-        }
-
-        public OutgoingHttpMessage getNextMessageImmediate() {
-            final List<OutputAction> actions = CollectionUtil.arrayList();
-            outgoingQueue.drainTo(actions);
-            if (actions.isEmpty()) {
-                return null;
-            }
-            return new OutgoingActionHttpMessage(actions);
-        }
-
-        public OutgoingHttpMessage getNextMessage(long timeoutMillis) throws InterruptedException {
-            synchronized(outgoingQueue) {
-                final OutputAction first = outgoingQueue.poll(timeoutMillis, TimeUnit.MILLISECONDS);
-                if (first != null) {
-                    final List<OutputAction> actions = CollectionUtil.arrayList();
-                    actions.add(first);
-                    outgoingQueue.drainTo(actions);
-                    return new OutgoingActionHttpMessage(actions);
-                } else {
-                    return null;
-                }
-            }
-        }
-    }
-
-    private void write(ObjectOutput output, MsgType type) throws IOException {
-        output.writeInt(type.ordinal());
-    }
-
-    private void write(ObjectOutput output, ServiceIdentifier serviceIdentifier) throws IOException {
-        output.writeUTF(serviceIdentifier.toString());
-    }
-
-    private void write(ObjectOutput output, ContextIdentifier contextIdentifier) throws IOException {
-        output.writeUTF(contextIdentifier.toString());
-    }
-
-    private void write(ObjectOutput output, RequestIdentifier requestIdentifier) throws IOException {
-        output.writeUTF(requestIdentifier.toString());
-    }
-
-    private void write(ObjectOutput output, StreamIdentifier streamIdentifier) throws IOException {
-        output.writeUTF(streamIdentifier.toString());
-    }
-
-    private final class ProtocolHandlerImpl implements ProtocolHandler {
-
-        public void sendServiceActivate(final ServiceIdentifier remoteServiceIdentifier) throws IOException {
-            outgoingQueue.add(new OutputAction() {
-                public void run(ByteMessageOutput target) throws IOException {
-                    final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(target);
-                    write(msgOutput, MsgType.SERVICE_ACTIVATE);
-                    write(msgOutput, remoteServiceIdentifier);
-                    msgOutput.commit();
-                }
-            });
-        }
-
-        public void sendReply(final ContextIdentifier remoteContextIdentifier, final RequestIdentifier requestIdentifier, final Object reply) throws IOException {
-            // we have to buffer because reply might be mutable!
-            final BufferedByteMessageOutput output = new BufferedByteMessageOutput(256);
-            final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(output);
-            write(msgOutput, MsgType.REPLY);
-            write(msgOutput, remoteContextIdentifier);
-            write(msgOutput, requestIdentifier);
-            msgOutput.writeObject(reply);
-            msgOutput.commit();
-        }
-
-        public void sendException(final ContextIdentifier remoteContextIdentifier, final RequestIdentifier requestIdentifier, final RemoteExecutionException exception) throws IOException {
-            // we have to buffer because exception might contain mutable elements
-            final BufferedByteMessageOutput output = new BufferedByteMessageOutput(256);
-            final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(output);
-            write(msgOutput, MsgType.EXCEPTION);
-            write(msgOutput, remoteContextIdentifier);
-            write(msgOutput, requestIdentifier);
-            msgOutput.writeObject(exception);
-            msgOutput.commit();
-        }
-
-        public void sendCancelAcknowledge(final ContextIdentifier remoteContextIdentifier, final RequestIdentifier requestIdentifier) throws IOException {
-            outgoingQueue.add(new OutputAction() {
-                public void run(ByteMessageOutput target) throws IOException {
-                    final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(target);
-                    write(msgOutput, MsgType.CANCEL_ACK);
-                    write(msgOutput, remoteContextIdentifier);
-                    write(msgOutput, requestIdentifier);
-                    msgOutput.commit();
-                }
-            });
-        }
-
-        public void sendServiceClosing(final ServiceIdentifier remoteServiceIdentifier) throws IOException {
-            outgoingQueue.add(new OutputAction() {
-                public void run(ByteMessageOutput target) throws IOException {
-                    final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(target);
-                    write(msgOutput, MsgType.SERVICE_TERMINATE);
-                    write(msgOutput, remoteServiceIdentifier);
-                    msgOutput.commit();
-                }
-            });
-        }
-
-        public void sendContextClosing(final ContextIdentifier remoteContextIdentifier, final boolean done) throws IOException {
-        }
-
-        public ContextIdentifier getLocalRootContextIdentifier() {
-            return null;
-        }
-
-        public ContextIdentifier getRemoteRootContextIdentifier() {
-            return null;
-        }
-
-        public ContextIdentifier openContext(final ServiceIdentifier serviceIdentifier) throws IOException {
-            final ContextIdentifier contextIdentifier = null;
-            outgoingQueue.add(new OutputAction() {
-                public void run(ByteMessageOutput target) throws IOException {
-                    final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(target);
-                    write(msgOutput, MsgType.CONTEXT_OPENED);
-                    write(msgOutput, serviceIdentifier);
-                    write(msgOutput, contextIdentifier);
-                    msgOutput.commit();
-                }
-            });
-            return contextIdentifier;
-        }
-
-        public void sendContextClose(final ContextIdentifier contextIdentifier, final boolean immediate, final boolean cancel, final boolean interrupt) throws IOException {
-            outgoingQueue.add(new OutputAction() {
-                public void run(ByteMessageOutput target) throws IOException {
-                    final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(target);
-                    write(msgOutput, MsgType.CLOSE_CONTEXT);
-                    write(msgOutput, contextIdentifier);
-                    msgOutput.commit();
-                }
-            });
-        }
-
-        public RequestIdentifier openRequest(ContextIdentifier contextIdentifier) throws IOException {
-            return null;
-        }
-
-        public ServiceIdentifier openService() throws IOException {
-            return null;
-        }
-
-        public void sendServiceClose(final ServiceIdentifier serviceIdentifier) throws IOException {
-            outgoingQueue.add(new OutputAction() {
-                public void run(ByteMessageOutput target) throws IOException {
-                    final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(target);
-                    write(msgOutput, MsgType.CLOSE_SERVICE);
-                    write(msgOutput, serviceIdentifier);
-                    msgOutput.commit();
-                }
-            });
-        }
-
-        public void sendRequest(final ContextIdentifier contextIdentifier, final RequestIdentifier requestIdentifier, final Object request, final Executor streamExecutor) throws IOException {
-            // we have to buffer because request might be mutable!
-            final BufferedByteMessageOutput output = new BufferedByteMessageOutput(256);
-            final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(output, streamExecutor);
-            write(msgOutput, MsgType.REQUEST);
-            write(msgOutput, contextIdentifier);
-            write(msgOutput, requestIdentifier);
-            msgOutput.writeObject(request);
-            msgOutput.commit();
-        }
-
-        public void sendCancelRequest(final ContextIdentifier contextIdentifier, final RequestIdentifier requestIdentifier, final boolean mayInterrupt) throws IOException {
-            outgoingQueue.add(new OutputAction() {
-                public void run(ByteMessageOutput target) throws IOException {
-                    final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(target);
-                    write(msgOutput, MsgType.CANCEL_REQUEST);
-                    write(msgOutput, contextIdentifier);
-                    write(msgOutput, requestIdentifier);
-                    msgOutput.writeBoolean(mayInterrupt);
-                    msgOutput.commit();
-                }
-            });
-        }
-
-        public ContextIdentifier openContext() throws IOException {
-            return null;
-        }
-
-        public StreamIdentifier openStream() throws IOException {
-            return null;
-        }
-
-        public void closeStream(final StreamIdentifier streamIdentifier) throws IOException {
-            outgoingQueue.add(new OutputAction() {
-                public void run(ByteMessageOutput target) throws IOException {
-                    final ObjectMessageOutput msgOutput = protocolContext.getMessageOutput(target);
-                    write(msgOutput, MsgType.CLOSE_STREAM);
-                    write(msgOutput, streamIdentifier);
-                    msgOutput.commit();
-                }
-            });
-        }
-
-        public StreamIdentifier readStreamIdentifier(ObjectInput input) throws IOException {
-            return null;
-        }
-
-        public void writeStreamIdentifier(ObjectOutput output, StreamIdentifier identifier) throws IOException {
-            write(output, identifier);
-        }
-
-        public ObjectMessageOutput sendStreamData(StreamIdentifier streamIdentifier, Executor streamExecutor) throws IOException {
-            return protocolContext.getMessageOutput(new BufferedByteMessageOutput(256), streamExecutor);
-        }
-
-        public void closeSession() throws IOException {
-        }
-
-        public String getRemoteEndpointName() {
-            return null;
-        }
-    }
-
-    public class BufferedByteMessageOutput implements ByteMessageOutput, OutputAction {
-        private final int bufsize;
-        private final List<byte[]> bufferList = new ArrayList<byte[]>();
-        private int sizeOfLast;
-
-        public BufferedByteMessageOutput(final int bufsize) {
-            this.bufsize = bufsize;
-        }
-
-        public void write(int b) throws IOException {
-            final byte[] last = bufferList.get(bufferList.size());
-            if (sizeOfLast == last.length) {
-                final byte[] bytes = new byte[bufsize];
-                bufferList.add(bytes);
-                bytes[0] = (byte) b;
-                sizeOfLast = 1;
-            } else {
-                last[sizeOfLast++] = (byte) b;
-            }
-        }
-
-        public void write(byte[] b) throws IOException {
-            write(b, 0, b.length);
-        }
-
-        public void write(byte[] b, int offs, int len) throws IOException {
-            byte[] bytes = bufferList.get(bufferList.size());
-            while (len > 0) {
-                final int copySize = bytes.length - sizeOfLast;
-                if (len <= copySize) {
-                    System.arraycopy(b, offs, bytes, sizeOfLast, len);
-                    sizeOfLast += len;
-                    return;
-                } else {
-                    System.arraycopy(b, offs, bytes, sizeOfLast, copySize);
-                    bytes = new byte[bufsize];
-                    bufferList.add(bytes);
-                    sizeOfLast = 0;
-                    len -= copySize;
-                    offs += copySize;
-                }
-            }
-        }
-
-        public void commit() throws IOException {
-            outgoingQueue.add(this);
-        }
-
-        public int getBytesWritten() throws IOException {
-            Iterator<byte[]> it = bufferList.iterator();
-            if (! it.hasNext()) {
-                return 0;
-            }
-            int t = 0;
-            for (;;) {
-                byte[] b = it.next();
-                if (it.hasNext()) {
-                    t += b.length;
-                } else {
-                    return t + sizeOfLast;
-                }
-            }
-        }
-
-        public void close() throws IOException {
-            bufferList.clear();
-        }
-
-        public void flush() throws IOException {
-        }
-
-        public void run(ByteMessageOutput output) throws IOException {
-            final Iterator<byte[]> iterator = bufferList.iterator();
-            if (! iterator.hasNext()) {
-                return;
-            }
-            for (;;) {
-                byte[] bytes = iterator.next();
-                if (iterator.hasNext()) {
-                    output.write(bytes);
-                } else {
-                    output.write(bytes, 0, sizeOfLast);
-                    return;
-                }
-            }
-        }
-    }
-
-    private void addSessionHeader(final OutgoingHttpMessage msg) {
-        msg.addHeader(Http.HEADER_SESSION_ID, sessionId);
-    }
-
-    private interface OutputAction {
-        void run(ByteMessageOutput target) throws IOException;
-    }
-
-    private final class OutgoingActionHttpMessage extends AbstractOutgoingHttpMessage {
-        private final List<OutputAction> actions;
-        private final long sequenceValue;
-
-        public OutgoingActionHttpMessage(final List<OutputAction> actions) {
-            this.actions = actions;
-            sequenceValue = outputSequence.getAndIncrement();
-            addSessionHeader(this);
-            addHeader(Http.HEADER_SEQ, Long.toString(sequenceValue, 16));
-        }
-
-        public void writeMessageData(ByteMessageOutput byteOutput) throws IOException {
-            final ObjectMessageOutput msgOut = protocolContext.getMessageOutput(byteOutput);
-            msgOut.writeInt(PROTOCOL_VERSION);
-            write(msgOut, MsgType.DATA_START);
-            msgOut.writeLong(sequenceValue);
-            msgOut.commit();
-            for (OutputAction action : actions) {
-                action.run(byteOutput);
-            }
-            write(msgOut, MsgType.DATA_END);
-        }
-    }
-
-    // DO NOT re-order
-    private enum MsgType {
-        DATA_START,
-        DATA_END,
-
-        SERVICE_ACTIVATE,
-        REPLY,
-        EXCEPTION,
-        CANCEL_ACK,
-        SERVICE_TERMINATE,
-        CONTEXT_OPENED,
-        CLOSE_CONTEXT,
-        SERVICE_REQUEST, CLOSE_SERVICE, REQUEST, CANCEL_REQUEST, CLOSE_STREAM,
-    }
-}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/Cookie.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/Cookie.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/Cookie.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,123 @@
+package org.jboss.cx.remoting.http.cookie;
+
+import java.io.Serializable;
+
+/**
+ * C is for: a simple HTTP cookie class, for HTTP transports that have no cookie handling.  It's good enough for me.
+ */
+public final class Cookie implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private final String value;
+    private final String name;
+    private final String path;
+    private final CookieDomain domain;
+    private final long expires;
+    private final boolean secure;
+    private final Key key;
+
+    public Cookie(final String name, final String value, final String path, final CookieDomain domain, final long expires, final boolean secure) {
+        this.expires = expires;
+        if (name == null) {
+            throw new NullPointerException("name is null");
+        }
+        if (value == null) {
+            throw new NullPointerException("value is null");
+        }
+        if (path == null) {
+            throw new NullPointerException("path is null");
+        }
+        if (domain == null) {
+            throw new NullPointerException("domain is null");
+        }
+        this.name = name;
+        this.value = value;
+        this.path = path;
+        this.domain = domain;
+        this.secure = secure;
+        key = new Key(name, path);
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public CookieDomain getDomain() {
+        return domain;
+    }
+
+    public long getExpires() {
+        return expires;
+    }
+
+    public boolean isSecure() {
+        return secure;
+    }
+
+    public boolean equals(Cookie other) {
+        return this == other || name.equals(other.name) && value.equals(other.value) && path.equals(other.path) && domain.equals(other.domain) && secure == other.secure;
+    }
+
+    public boolean equals(Object other) {
+        return other instanceof Cookie && equals((Cookie) other);
+    }
+
+    public int hashCode() {
+        return 31 * (31 * (31 * (31 * name.hashCode() + value.hashCode()) + path.hashCode()) + domain.hashCode()) + (secure ? 1 : 0);
+    }
+
+    public boolean isExpired() {
+        return expires != 0L && System.currentTimeMillis() > expires;
+    }
+
+    public Key getKey() {
+        return key;
+    }
+
+    public static final class Key implements Serializable {
+        private static final long serialVersionUID = 1L;
+
+        private final String name;
+        private final String path;
+
+        public Key(final String name, final String path) {
+            if (name == null) {
+                throw new NullPointerException("name is null");
+            }
+            if (path == null) {
+                throw new NullPointerException("path is null");
+            }
+            this.name = name;
+            this.path = path;
+        }
+
+        public int hashCode() {
+            return 31 * path.hashCode() + name.hashCode();
+        }
+
+        private String getName() {
+            return name;
+        }
+
+        private String getPath() {
+            return path;
+        }
+
+        public boolean equals(final Key other) {
+            return this == other || name.equals(other.getName()) && path.equals(other.getPath());
+        }
+
+        public boolean equals(final Object other) {
+            return super.equals(other);
+        }
+    }
+}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieClientSession.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieClientSession.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieClientSession.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,80 @@
+package org.jboss.cx.remoting.http.cookie;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import org.jboss.cx.remoting.log.Logger;
+import static org.jboss.cx.remoting.util.CollectionUtil.synchronizedHashMap;
+
+/**
+ *
+ */
+public final class CookieClientSession {
+    private static final Logger log = Logger.getLogger(CookieClientSession.class);
+
+    private final CookieMatcher cookieMatcher;
+    private final CookieValidator cookieValidator;
+    private final CookieParser cookieParser;
+
+    private final Map<Cookie.Key, Cookie> cookieMap = synchronizedHashMap();
+
+    public CookieClientSession(final CookieMatcher cookieMatcher, final CookieValidator cookieValidator, final CookieParser cookieParser) {
+        this.cookieMatcher = cookieMatcher;
+        this.cookieValidator = cookieValidator;
+        this.cookieParser = cookieParser;
+    }
+
+    public CookieClientSession() {
+        cookieMatcher = new SimpleCookieMatcher();
+        cookieValidator = new SimpleCookieValidator();
+        cookieParser = new SimpleCookieParser();
+    }
+
+    /**
+     * Get a cookie header for this session, given a request domain and path.  Follows all the silly rules, like being
+     * sorted by path length.
+     *
+     * @param domain the request domain
+     * @param path the request path (sans file, with trailing slash)
+     * @param secureRequest {@code true} if the request will use the {@code https} protocol
+     * @return the cookie header value
+     */
+    public String getCookieHeader(String domain, String path, boolean secureRequest) {
+        final CookieDomain cookieDomain = new CookieDomain(domain);
+        final SortedMap<Cookie.Key, Cookie> sortedValidatedCookies = new TreeMap<Cookie.Key, Cookie>();
+        for (final Cookie cookie : cookieMap.values()) {
+            if (cookieMatcher.matches(cookie, cookieDomain, path, secureRequest)) {
+                sortedValidatedCookies.put(cookie.getKey(), cookie);
+            }
+        }
+        final StringBuilder builder = new StringBuilder();
+        final Iterator<Cookie> it = sortedValidatedCookies.values().iterator();
+        while (it.hasNext()) {
+            Cookie cookie = it.next();
+            builder.append(cookie.getName()).append('=').append(cookie.getValue());
+            if (it.hasNext()) builder.append("; ");
+        }
+        return builder.length() == 0 ? null : builder.toString();
+    }
+
+    /**
+     * Handle a Set-Cookie type of header from the server.
+     *
+     * @param headerValue the text of the header
+     * @param domain the request domain
+     * @param path the request path
+     */
+    public void handleSetCookieHeader(String headerValue, String domain, String path) {
+        final CookieDomain requestDomain = new CookieDomain(domain);
+        final Cookie[] cookies = cookieParser.parseSetCookie(headerValue, requestDomain, path);
+        for (Cookie cookie : cookies) {
+            if (! cookieValidator.isValid(cookie, requestDomain)) {
+                log.trace("Ignoring invalid cookie %s", cookie);
+            } else {
+                log.trace("Adding cookie '%s' from domain '%s'", cookie, requestDomain);
+                cookieMap.put(cookie.getKey(), cookie);
+            }
+        }
+    }
+}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieDomain.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieDomain.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieDomain.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,87 @@
+package org.jboss.cx.remoting.http.cookie;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import org.jboss.cx.remoting.util.CollectionUtil;
+import static org.jboss.cx.remoting.util.CollectionUtil.split;
+import static org.jboss.cx.remoting.util.CollectionUtil.toArrayReversed;
+
+/**
+ *
+ */
+public final class CookieDomain implements Serializable {
+
+    public static final CookieDomain LOCAL = new CookieDomain(".local");
+
+    private static final long serialVersionUID = 1L;
+
+    private final String[] parts;
+    private final boolean hostDomainName;
+
+    private CookieDomain(String[] parts, boolean hostDomainName) {
+        this.parts = parts;
+        this.hostDomainName = hostDomainName;
+    }
+
+    public CookieDomain(String domain) {
+        if (domain == null) {
+            throw new NullPointerException("domain is null");
+        }
+        if (domain.length() == 0) {
+            throw new IllegalArgumentException("domain is empty");
+        }
+        hostDomainName = domain.charAt(0) == '.';
+        final String baseDomain = hostDomainName ? domain.substring(1).toLowerCase() : domain.toLowerCase();
+        parts = toArrayReversed(split(".", baseDomain).iterator(), String.class);
+    }
+
+    public boolean equals(final CookieDomain other) {
+        return other != null && hostDomainName == other.hostDomainName && Arrays.equals(parts, other.parts);
+    }
+
+    public boolean equals(final Object other) {
+        return other instanceof CookieDomain && equals((CookieDomain)other);
+    }
+
+    public int hashCode() {
+        return Arrays.hashCode(parts) + (hostDomainName ? 1 : 0);
+    }
+
+    public String toString() {
+        final StringBuilder builder = new StringBuilder(40);
+        builder.append("Domain: ");
+        for (String x : parts) {
+            builder.append(x);
+            builder.append('/');
+        }
+        builder.setLength(builder.length() - 1);
+        return builder.toString();
+    }
+
+    public boolean matches(final CookieDomain other) {
+        // todo this doesn't quite match rfc 2965
+        return other.hostDomainName ? CollectionUtil.arrayStartsWith(parts, other.parts) : Arrays.equals(other.parts, parts); 
+    }
+
+    public int getPartCount() {
+        return parts.length;
+    }
+
+    public String getPart(int index) {
+        return parts[index];
+    }
+
+    public boolean hasParent() {
+        return parts.length > 1;
+    }
+
+    public boolean isHostDomainName() {
+        return hostDomainName;
+    }
+
+    public CookieDomain getParent() {
+        final String[] parentParts = new String[parts.length - 1];
+        System.arraycopy(parts, 0, parentParts, 0, parentParts.length);
+        return new CookieDomain(parentParts, false);
+    }
+}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieMatcher.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieMatcher.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieMatcher.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,18 @@
+package org.jboss.cx.remoting.http.cookie;
+
+/**
+ * Cookie matcher.  Used to determine if a cookie should be sent to a server.
+ */
+public interface CookieMatcher {
+
+    /**
+     * Determine whether a cookie matches a server.
+     *
+     * @param cookie the cookie
+     * @param requestDomain the domain that the request is being sent to
+     * @param path the path that the request is being sent to
+     * @param secure whether the request is on a secure channel
+     * @return {@code true} if the cookie should be sent
+     */
+    boolean matches(Cookie cookie, CookieDomain requestDomain, String path, boolean secure);
+}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieParser.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieParser.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieParser.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,8 @@
+package org.jboss.cx.remoting.http.cookie;
+
+/**
+ *
+ */
+public interface CookieParser {
+    Cookie[] parseSetCookie(String setCookie, CookieDomain defaultDomain, String defaultPath);
+}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieValidator.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieValidator.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/CookieValidator.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,16 @@
+package org.jboss.cx.remoting.http.cookie;
+
+/**
+ * Cookie validator.  Used to validate cookies sent to the client from the server.
+ */
+public interface CookieValidator {
+
+    /**
+     * Determine whether a cookie from a server is valid.
+     *
+     * @param cookie the cookie from the server
+     * @param fromDomain the actual domain that the request was sent to
+     * @return {@code true} if the cookie is valid
+     */
+    boolean isValid(Cookie cookie, CookieDomain fromDomain);
+}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieMatcher.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieMatcher.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieMatcher.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,17 @@
+package org.jboss.cx.remoting.http.cookie;
+
+/**
+ * Simple cookie matcher.  See http://wp.netscape.com/newsref/std/cookie_spec.html
+ */
+public final class SimpleCookieMatcher implements CookieMatcher {
+
+    public boolean matches(final Cookie cookie, final CookieDomain requestDomain, final String path, final boolean secure) {
+        final boolean cookieSecure = cookie.isSecure();
+        if (cookieSecure && ! secure) {
+            return false;
+        }
+        final CookieDomain cookieDomain = cookie.getDomain();
+        final String cookiePath = cookie.getPath();
+        return requestDomain.matches(cookieDomain) && path.startsWith(cookiePath) && !cookie.isExpired();
+    }
+}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieParser.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieParser.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieParser.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,83 @@
+package org.jboss.cx.remoting.http.cookie;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import org.jboss.cx.remoting.log.Logger;
+import org.jboss.cx.remoting.util.CollectionUtil;
+
+/**
+ *
+ */
+public final class SimpleCookieParser implements CookieParser {
+
+    private static final String DATE_FORMAT = "EEE, dd-MMM-yyyy HH:mm:ss";
+
+    private static final Logger log = Logger.getLogger(SimpleCookieParser.class);
+
+    private static final class Pair {
+
+        private final String name;
+        private final String value;
+
+        private Pair(final String name, final String value) {
+            this.name = name;
+            this.value = value;
+        }
+    }
+
+    public Cookie[] parseSetCookie(final String setCookie, final CookieDomain defaultDomain, final String defaultPath) {
+        if (setCookie == null) {
+            throw new NullPointerException("setCookie is null");
+        }
+        if (defaultDomain == null) {
+            throw new NullPointerException("defaultDomain is null");
+        }
+        if (defaultPath == null) {
+            throw new NullPointerException("defaultPath is null");
+        }
+        boolean secure = false;
+        long expires = 0L;
+        CookieDomain domain = defaultDomain;
+        String path = defaultPath;
+        List<Pair> pairs = CollectionUtil.arrayList();
+        for (final String s : CollectionUtil.split(";", setCookie)) {
+            final String assignment = s.trim();
+            final int equalsPos = assignment.indexOf('=');
+            if (equalsPos == -1) {
+                if (assignment.toLowerCase().equals("secure")) {
+                    secure = true;
+                    continue;
+                }
+            } else {
+                String name = assignment.substring(0, equalsPos).trim();
+                String lowerName = name.toLowerCase();
+                String value = assignment.substring(equalsPos + 1).trim();
+                if (lowerName.equals("expires")) {
+                    final int gmti = value.lastIndexOf(" GMT");
+                    if (gmti != -1) {
+                        value = value.substring(0, gmti);
+                    }
+                    final SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
+                    try {
+                        expires = dateFormat.parse(value).getTime();
+                    } catch (ParseException e) {
+                        log.trace("Invalid cookie expiration date '%s'", value);
+                    }
+                } else if (lowerName.equals("domain")) {
+                    domain = new CookieDomain(value);
+                } else if (lowerName.equals("path")) {
+                    path = value;
+                } else {
+                    pairs.add(new Pair(name, value));
+                }
+            }
+        }
+        Cookie[] cookies = new Cookie[pairs.size()];
+        int i = 0;
+        for (Pair pair : pairs) {
+            cookies[i++] = new Cookie(pair.name, pair.value, path, domain, expires, secure);
+        }
+        return cookies;
+    }
+}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieValidator.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieValidator.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/cookie/SimpleCookieValidator.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,52 @@
+package org.jboss.cx.remoting.http.cookie;
+
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Simple cookie validator.  Validates a cookie coming down from a server.  See
+ * http://wp.netscape.com/newsref/std/cookie_spec.html and http://www.ietf.org/rfc/rfc2965.txt
+ * for more info.
+ */
+public final class SimpleCookieValidator implements CookieValidator {
+    private static final Set<String> TLD_SET;
+
+    static {
+        final HashSet<String> tldSet = new HashSet<String>();
+        tldSet.add("com");
+        tldSet.add("edu");
+        tldSet.add("net");
+        tldSet.add("org");
+        tldSet.add("gov");
+        tldSet.add("mil");
+        tldSet.add("int");
+        TLD_SET = Collections.unmodifiableSet(tldSet);
+    }
+
+    public boolean isValid(final Cookie cookie, final CookieDomain requestDomain) {
+        final CookieDomain cookieDomain = cookie.getDomain();
+        for (int i = 0; i < cookieDomain.getPartCount(); i++) {
+            if (cookieDomain.getPart(i).length() == 0) {
+                return false;
+            }
+        }
+        final int numParts = cookieDomain.getPartCount() + (cookieDomain.isHostDomainName() ? 1 : 0);
+        final String tld = numParts == 0 ? null : cookieDomain.getPart(0);
+        final int minSegments = TLD_SET.contains(tld) ? 3 : 4;
+        if (numParts < minSegments) {
+            // not valid: domain name is too short
+            return false;
+        }
+        final String path = cookie.getPath();
+        if (path.length() == 0 || path.charAt(0) != '/') {
+            // not valid: bad or missing path
+            return false;
+        }
+        if (! requestDomain.matches(cookieDomain)) {
+            // wrong domain
+            return false;
+        }
+        return true;
+    }
+}

Deleted: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/id/HttpSubChannelIdentifier.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/id/HttpSubChannelIdentifier.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/id/HttpSubChannelIdentifier.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -1,24 +0,0 @@
-package org.jboss.cx.remoting.http.id;
-
-/**
- *
- */
-public abstract class HttpSubChannelIdentifier {
-    private final long id;
-
-    protected HttpSubChannelIdentifier(long id) {
-        this.id = id;
-    }
-
-    public int hashCode() {
-        return (int) id;
-    }
-
-    public boolean equals(Object obj) {
-        return obj instanceof HttpSubChannelIdentifier && ((HttpSubChannelIdentifier)obj).id == id;
-    }
-
-    public String toString() {
-        return Long.toHexString(id);
-    }
-}

Deleted: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/id/IdentifierProvider.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/id/IdentifierProvider.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/id/IdentifierProvider.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -1,19 +0,0 @@
-package org.jboss.cx.remoting.http.id;
-
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicLong;
-
-/**
- *
- */
-public final class IdentifierProvider {
-    private final Random rng;
-
-    public IdentifierProvider(final Random rng) {
-        this.rng = rng;
-    }
-
-    public AtomicLong newSequence() {
-        return new AtomicLong(rng.nextLong());
-    }
-}

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/AbstractIncomingHttpMessage.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/AbstractIncomingHttpMessage.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/AbstractIncomingHttpMessage.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -1,34 +1,10 @@
 package org.jboss.cx.remoting.http.spi;
 
-import java.net.InetAddress;
-
 /**
  *
  */
 public abstract class AbstractIncomingHttpMessage extends AbstractHttpMessage implements IncomingHttpMessage {
-    private final InetAddress remoteAddress, localAddress;
-    private final int localPort, remotePort;
 
-    protected AbstractIncomingHttpMessage(final InetAddress localAddress, final int localPort, final InetAddress remoteAddress, final int remotePort) {
-        this.remoteAddress = remoteAddress;
-        this.localAddress = localAddress;
-        this.localPort = localPort;
-        this.remotePort = remotePort;
+    protected AbstractIncomingHttpMessage() {
     }
-
-    public InetAddress getRemoteAddress() {
-        return remoteAddress;
-    }
-
-    public int getRemotePort() {
-        return remotePort;
-    }
-
-    public InetAddress getLocalAddress() {
-        return localAddress;
-    }
-
-    public int getLocalPort() {
-        return localPort;
-    }
 }

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/HttpChannel.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/HttpChannel.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/HttpChannel.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,12 @@
+package org.jboss.cx.remoting.http.spi;
+
+/**
+ *
+ */
+public interface HttpChannel {
+    void setChannelContext(RemotingHttpChannelContext channelContext);
+
+    void sendMessage(OutgoingHttpMessage message);
+
+    void close();
+}

Deleted: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/HttpTransporter.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/HttpTransporter.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/HttpTransporter.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -1,10 +0,0 @@
-package org.jboss.cx.remoting.http.spi;
-
-import java.net.URI;
-
-/**
- *
- */
-public interface HttpTransporter {
-    void esablish(URI remoteUri, RemotingHttpSessionContext newSessionContext);
-}

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/IncomingHttpMessage.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/IncomingHttpMessage.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/IncomingHttpMessage.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -1,7 +1,6 @@
 package org.jboss.cx.remoting.http.spi;
 
 import java.io.IOException;
-import java.net.InetAddress;
 import org.jboss.cx.remoting.spi.ByteMessageInput;
 
 /**
@@ -9,12 +8,4 @@
  */
 public interface IncomingHttpMessage extends HttpMessage {
     ByteMessageInput getMessageData() throws IOException;
-
-    InetAddress getRemoteAddress();
-
-    int getRemotePort();
-
-    InetAddress getLocalAddress();
-
-    int getLocalPort();
 }

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/OutboundHttpChannelProvider.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/OutboundHttpChannelProvider.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/OutboundHttpChannelProvider.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,8 @@
+package org.jboss.cx.remoting.http.spi;
+
+/**
+ *
+ */
+public interface OutboundHttpChannelProvider {
+
+}

Deleted: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/ReadyNotifier.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/ReadyNotifier.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/ReadyNotifier.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -1,8 +0,0 @@
-package org.jboss.cx.remoting.http.spi;
-
-/**
- *
- */
-public interface ReadyNotifier {
-    void notifyReady(RemotingHttpSessionContext context);
-}

Added: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpChannelContext.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpChannelContext.java	                        (rev 0)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpChannelContext.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,11 @@
+package org.jboss.cx.remoting.http.spi;
+
+/**
+ *
+ */
+public interface RemotingHttpChannelContext {
+
+    void receiveMessage(IncomingHttpMessage incomingHttpMessage);
+
+    void sendComplete(OutgoingHttpMessage outgoingHttpMessage);
+}

Modified: remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpSessionContext.java
===================================================================
--- remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpSessionContext.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http/src/main/java/org/jboss/cx/remoting/http/spi/RemotingHttpSessionContext.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -1,23 +1,12 @@
 package org.jboss.cx.remoting.http.spi;
 
-import javax.security.auth.callback.CallbackHandler;
-
 /**
  *
  */
 public interface RemotingHttpSessionContext {
-    void queueMessage(IncomingHttpMessage message);
+    void processInboundMessage(IncomingHttpMessage incomingHttpMessage);
 
-    /**
-     * Add a notifier to be called if there is data ready but there are no waiters for {@code getNextRequest}/{@code getNextReply}.
-     * The notifier can use the {@code getNext*Immediate} methods to check for the next message.
-     *
-     * @param notifier the notifier
-     */
-    void addReadyNotifier(ReadyNotifier notifier);
+    OutgoingHttpMessage getOutgoingHttpMessage();
 
-    OutgoingHttpMessage getNextMessageImmediate();
-
-    OutgoingHttpMessage getNextMessage(long timeoutMillis) throws InterruptedException;
-
+    OutgoingHttpMessage waitForOutgoingHttpMessage(long millis);
 }

Modified: remoting3/trunk/http-se6/src/main/java/org/jboss/cx/remoting/http/se6/ServerInstance.java
===================================================================
--- remoting3/trunk/http-se6/src/main/java/org/jboss/cx/remoting/http/se6/ServerInstance.java	2008-04-14 16:37:01 UTC (rev 3986)
+++ remoting3/trunk/http-se6/src/main/java/org/jboss/cx/remoting/http/se6/ServerInstance.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -66,7 +66,7 @@
             final InetAddress remoteAddress = inetSocketAddress.getAddress();
             final int remotePort = inetSocketAddress.getPort();
             RemotingHttpSessionContext httpSessionContext = null; // todo locate
-            httpSessionContext.queueMessage(new AbstractIncomingHttpMessage(localAddress, localPort, remoteAddress, remotePort) {
+            httpSessionContext.queueMessage(new AbstractIncomingHttpMessage() {
                 public ByteMessageInput getMessageData() {
                     final InputStream inputStream = httpExchange.getRequestBody();
                     return new ByteMessageInput() {

Added: remoting3/trunk/http-urlconnection/src/main/java/org/jboss/cx/remoting/http/urlconnection/HttpUrlChannel.java
===================================================================
--- remoting3/trunk/http-urlconnection/src/main/java/org/jboss/cx/remoting/http/urlconnection/HttpUrlChannel.java	                        (rev 0)
+++ remoting3/trunk/http-urlconnection/src/main/java/org/jboss/cx/remoting/http/urlconnection/HttpUrlChannel.java	2008-04-14 16:37:33 UTC (rev 3987)
@@ -0,0 +1,142 @@
+package org.jboss.cx.remoting.http.urlconnection;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.List;
+import java.util.Iterator;
+import java.util.concurrent.ConcurrentMap;
+import org.jboss.cx.remoting.http.spi.AbstractIncomingHttpMessage;
+import org.jboss.cx.remoting.http.spi.OutgoingHttpMessage;
+import org.jboss.cx.remoting.http.spi.RemotingHttpSessionContext;
+import org.jboss.cx.remoting.log.Logger;
+import org.jboss.cx.remoting.spi.ByteMessageInput;
+import org.jboss.cx.remoting.spi.ByteMessageOutput;
+import org.jboss.cx.remoting.util.CollectionUtil;
+
+/**
+ *
+ */
+public final class HttpUrlChannel {
+
+    private static final Logger log = Logger.getLogger(HttpUrlChannel.class);
+
+    private final ConcurrentMap<String, String> cookies = CollectionUtil.synchronizedMap(new LinkedHashMap<String, String>());
+
+    private RemotingHttpSessionContext sessionContext;
+
+    public RemotingHttpSessionContext getSessionContext() {
+        return sessionContext;
+    }
+
+    public void setSessionContext(final RemotingHttpSessionContext sessionContext) {
+        this.sessionContext = sessionContext;
+    }
+
+    public void doIt() {
+        final URL connectUrl = null;
+        new Runnable() {
+            public void run() {
+                for (;;) {
+                    final OutgoingHttpMessage message = sessionContext.getOutgoingHttpMessage();
+                    HttpURLConnection httpConnection = null;
+                    try {
+                        httpConnection = (HttpURLConnection) connectUrl.openConnection();
+                        httpConnection.setDoInput(true);
+                        httpConnection.setDoOutput(true);
+                        httpConnection.setDefaultUseCaches(false);
+                        httpConnection.setUseCaches(false);
+                        httpConnection.setInstanceFollowRedirects(false);
+//                        httpURLConnection.setConnectTimeout();
+//                        httpURLConnection.setReadTimeout();
+                        httpConnection.setRequestMethod("POST"); // All remoting requests are POST
+                        for (Map.Entry<String, String> entry : cookies.entrySet()) {
+                            httpConnection.setRequestProperty();
+                            entry.getKey()
+                        }
+                        httpConnection.connect();
+                        final OutputStream outputStream = httpConnection.getOutputStream();
+                        message.writeMessageData(new ByteMessageOutput() {
+
+                            public void write(final int b) throws IOException {
+                                outputStream.write(b);
+                            }
+
+                            public void write(final byte[] b) throws IOException {
+                                outputStream.write(b);
+                            }
+
+                            public void write(final byte[] b, final int offs, final int len) throws IOException {
+                                outputStream.write(b, offs, len);
+                            }
+
+                            public void commit() throws IOException {
+                            }
+
+                            public int getBytesWritten() throws IOException {
+                                throw new UnsupportedOperationException("getBytesWritten()");
+                            }
+
+                            public void close() throws IOException {
+                                outputStream.close();
+                            }
+
+                            public void flush() throws IOException {
+                                outputStream.flush();
+                            }
+                        });
+                        // now read the reply
+                        final List<String> setCookies = httpConnection.getHeaderFields().get("Set-Cookie");
+                        final InputStream inputStream = httpConnection.getInputStream();
+                        sessionContext.processInboundMessage(new AbstractIncomingHttpMessage() {
+                            public ByteMessageInput getMessageData() throws IOException {
+                                return new ByteMessageInput() {
+
+                                    public int read() throws IOException {
+                                        return inputStream.read();
+                                    }
+
+                                    public int read(final byte[] data) throws IOException {
+                                        return inputStream.read(data);
+                                    }
+
+                                    public int read(final byte[] data, final int offs, final int len) throws IOException {
+                                        return inputStream.read(data, offs, len);
+                                    }
+
+                                    public int remaining() {
+                                        throw new UnsupportedOperationException("remaining()");
+                                    }
+
+                                    public void close() throws IOException {
+                                        inputStream.close();
+                                    }
+                                };
+                            }
+                        });
+                    } catch (IOException e) {
+                        // probably a HTTP error occurred, so let's consume it
+                        try {
+                            if (httpConnection != null) {
+                                final int responseCode = httpConnection.getResponseCode();
+                                log.trace("Got error response code %d from remote URL '%s'", Integer.valueOf(responseCode), connectUrl);
+                                final InputStream errorStream = httpConnection.getErrorStream();
+                                // consume & discard the error stream
+                                while (errorStream.read() > -1);
+                                errorStream.close();
+                            }
+                        } catch (IOException e2) {
+                            log.trace("Error consuming the error stream from remote URL '%s'", connectUrl);
+                        }
+                        // todo - need a backoff timer to prevent a storm of HTTP errors.  Or perhaps the session should be torn down.
+                    }
+                }
+            }
+        };
+
+    }
+}




More information about the jboss-remoting-commits mailing list