[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