You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/01/20 18:54:04 UTC
svn commit: r1435904 - in /tomcat/trunk: java/javax/websocket/
java/org/apache/tomcat/websocket/ java/org/apache/tomcat/websocket/server/
res/META-INF/tomcat-websocket.jar/services/ res/checkstyle/
test/org/apache/tomcat/websocket/ test/org/apache/tomc...
Author: markt
Date: Sun Jan 20 17:54:03 2013
New Revision: 1435904
URL: http://svn.apache.org/viewvc?rev=1435904&view=rev
Log:
Move server side specific code to separate package. Further refactoring is likely to be required as client side code is developed.
Added:
tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointBase.java
- copied, changed from r1434921, tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java
tomcat/trunk/java/org/apache/tomcat/websocket/server/
tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java (with props)
tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties (with props)
tomcat/trunk/java/org/apache/tomcat/websocket/server/ServerContainerImpl.java
- copied, changed from r1434927, tomcat/trunk/java/org/apache/tomcat/websocket/ServerContainerImpl.java
tomcat/trunk/java/org/apache/tomcat/websocket/server/WsProtocolHandler.java
- copied, changed from r1434921, tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java
tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointServer.java (with props)
tomcat/trunk/java/org/apache/tomcat/websocket/server/WsSci.java
- copied, changed from r1434921, tomcat/trunk/java/org/apache/tomcat/websocket/WsSci.java
tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServlet.java
- copied, changed from r1434921, tomcat/trunk/java/org/apache/tomcat/websocket/WsServlet.java
tomcat/trunk/java/org/apache/tomcat/websocket/server/package-info.java (with props)
tomcat/trunk/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java (with props)
tomcat/trunk/test/org/apache/tomcat/websocket/server/
tomcat/trunk/test/org/apache/tomcat/websocket/server/TestServerContainerImpl.java
- copied, changed from r1434921, tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java
Removed:
tomcat/trunk/java/org/apache/tomcat/websocket/ServerContainerImpl.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsSci.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsServlet.java
tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java
Modified:
tomcat/trunk/java/javax/websocket/WebSocketContainer.java
tomcat/trunk/java/org/apache/tomcat/websocket/Constants.java
tomcat/trunk/java/org/apache/tomcat/websocket/Util.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java
tomcat/trunk/res/META-INF/tomcat-websocket.jar/services/javax.servlet.ServletContainerInitializer
tomcat/trunk/res/checkstyle/org-import-control.xml
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/WsConfigListener.java
Modified: tomcat/trunk/java/javax/websocket/WebSocketContainer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/websocket/WebSocketContainer.java?rev=1435904&r1=1435903&r2=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/javax/websocket/WebSocketContainer.java (original)
+++ tomcat/trunk/java/javax/websocket/WebSocketContainer.java Sun Jan 20 17:54:03 2013
@@ -28,6 +28,21 @@ public interface WebSocketContainer {
Session connectToServer(Class<?> annotatedEndpointClass, URI path)
throws DeploymentException;
+ /**
+ * Creates a new connection to the WebSocket.
+ *
+ * @param endpoint
+ * An instance of this class will be created to handle responses
+ * from the server
+ * @param clientEndpointConfiguration
+ * Used to configure the new connection
+ * @param path
+ * The full URL of the WebSocket endpoint to connect to
+ *
+ * @return The WebSocket session for the connection
+ *
+ * @throws DeploymentException If the connection can not be established
+ */
Session connectToServer(Class<? extends Endpoint> endpoint,
ClientEndpointConfiguration clientEndpointConfiguration, URI path)
throws DeploymentException;
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/Constants.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/Constants.java?rev=1435904&r1=1435903&r2=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/Constants.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/Constants.java Sun Jan 20 17:54:03 2013
@@ -23,7 +23,6 @@ public class Constants {
protected static final String PACKAGE_NAME =
Constants.class.getPackage().getName();
- protected static final String SERVLET_NAME = WsServlet.class.getName();
// OP Codes
public static final byte OPCODE_CONTINUATION = 0x00;
public static final byte OPCODE_TEXT = 0x01;
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/Util.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/Util.java?rev=1435904&r1=1435903&r2=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/Util.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/Util.java Sun Jan 20 17:54:03 2013
@@ -30,32 +30,6 @@ class Util {
}
- /**
- * Converts a path defined for a WebSocket endpoint into a path that can be
- * used as a servlet mapping.
- *
- * @param wsPath The WebSocket endpoint path to convert
- * @return The servlet mapping
- */
- static String getServletPath(String wsPath) {
- int templateStart = wsPath.indexOf('{');
- if (templateStart == -1) {
- if (wsPath.charAt(wsPath.length() - 1) == '/') {
- return wsPath + '*';
- } else {
- return wsPath + "/*";
- }
- } else {
- String temp = wsPath.substring(0, templateStart);
- if (temp.charAt(temp.length() - 1) == '/') {
- return temp + '*';
- } else {
- return temp.substring(0, temp.lastIndexOf('/') + 1) + '*';
- }
- }
- }
-
-
static CloseCode getCloseCode(int code) {
if (code > 2999 && code < 5000) {
return CloseCodes.NORMAL_CLOSURE;
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java?rev=1435904&r1=1435903&r2=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java Sun Jan 20 17:54:03 2013
@@ -83,8 +83,13 @@ public class WsFrame {
this.sis = sis;
this.wsSession = wsSession;
+ // TODO This needs to work for client and server side code
+ /*
int readBufferSize =
ServerContainerImpl.getServerContainer().getReadBufferSize();
+ */
+ // Temp hack until the above is resolved
+ int readBufferSize = 8192;
inputBuffer = new byte[readBufferSize];
messageBufferBinary = ByteBuffer.allocate(readBufferSize);
Copied: tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointBase.java (from r1434921, tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java)
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointBase.java?p2=tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointBase.java&p1=tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java&r1=1434921&r2=1435904&rev=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpointBase.java Sun Jan 20 17:54:03 2013
@@ -24,35 +24,21 @@ import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
-import java.util.concurrent.BrokenBarrierException;
-import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.Future;
-import javax.servlet.ServletOutputStream;
import javax.websocket.EncodeException;
import javax.websocket.RemoteEndpoint;
import javax.websocket.SendHandler;
import javax.websocket.SendResult;
-public class WsRemoteEndpoint implements RemoteEndpoint {
+public abstract class WsRemoteEndpointBase implements RemoteEndpoint {
- private final Object messageWriteLock = new Object();
-
- private final ServletOutputStream sos;
- private final WsSession wsSession;
// Max length for outgoing WebSocket frame header is 10 bytes
private final ByteBuffer header = ByteBuffer.allocate(10);
private final ByteBuffer textToByte = ByteBuffer.allocate(8192);
private final CharsetEncoder encoder = Charset.forName("UTF8").newEncoder();
private volatile Boolean isText = null;
- private volatile CyclicBarrier writeBarrier = new CyclicBarrier(2);
-
-
- public WsRemoteEndpoint(WsSession wsSession, ServletOutputStream sos) {
- this.wsSession = wsSession;
- this.sos = sos;
- }
@Override
@@ -200,14 +186,7 @@ public class WsRemoteEndpoint implements
}
- public void onWritePossible() {
- try {
- writeBarrier.await();
- } catch (InterruptedException | BrokenBarrierException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
+ public abstract void onWritePossible();
protected void sendMessage(byte opCode, ByteBuffer message,
@@ -250,50 +229,13 @@ public class WsRemoteEndpoint implements
}
header.flip();
- // Could sync on sos but don't as other (user or container) code may
- // sync on this creating the potential for deadlocks.
- synchronized (messageWriteLock) {
- doBlockingWrite(header);
- doBlockingWrite(message);
- try {
- sos.flush();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
-
- if (Constants.OPCODE_CLOSE == opCode) {
- try {
- sos.close();
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- if (opCode == Constants.OPCODE_CLOSE) {
- // Connection is closing - ensure no threads are stuck waiting on
- // the write barrier
- writeBarrier.reset();
- }
- }
-
- private void doBlockingWrite(ByteBuffer data) {
- if (!sos.canWrite()) {
- try {
- writeBarrier.await();
- } catch (InterruptedException | BrokenBarrierException e) {
- wsSession.getLocalEndpoint().onError(wsSession, e);
- }
- }
- try {
- sos.write(data.array(), data.arrayOffset(), data.limit());
- } catch (IOException e) {
- wsSession.getLocalEndpoint().onError(wsSession, e);
- }
+ writeMessage(opCode, header, message);
}
+ protected abstract void writeMessage(int opCode, ByteBuffer header,
+ ByteBuffer message);
+
@Override
public void setBatchingAllowed(boolean batchingAllowed) {
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java?rev=1435904&r1=1435903&r2=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java Sun Jan 20 17:54:03 2013
@@ -43,12 +43,12 @@ public class WsSession implements Sessio
private static final Charset UTF8 = Charset.forName("UTF8");
private final Endpoint localEndpoint;
- private WsRemoteEndpoint wsRemoteEndpoint;
+ private WsRemoteEndpointBase wsRemoteEndpoint;
private MessageHandler textMessageHandler = null;
private MessageHandler binaryMessageHandler = null;
private MessageHandler.Basic<PongMessage> pongMessageHandler = null;
- protected WsSession(Endpoint localEndpoint) {
+ public WsSession(Endpoint localEndpoint) {
this.localEndpoint = localEndpoint;
}
@@ -250,7 +250,7 @@ public class WsSession implements Sessio
}
- protected void setRemote(WsRemoteEndpoint wsRemoteEndpoint) {
+ public void setRemote(WsRemoteEndpointBase wsRemoteEndpoint) {
this.wsRemoteEndpoint = wsRemoteEndpoint;
}
@@ -269,12 +269,12 @@ public class WsSession implements Sessio
return pongMessageHandler;
}
- protected void onClose(CloseReason closeReason) {
+ public void onClose(CloseReason closeReason) {
localEndpoint.onClose(this, closeReason);
}
- protected Endpoint getLocalEndpoint() {
+ public Endpoint getLocalEndpoint() {
return localEndpoint;
}
Added: tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java?rev=1435904&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java Sun Jan 20 17:54:03 2013
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.websocket.server;
+
+/**
+ * Internal implementation constants.
+ */
+public class Constants {
+
+ protected static final String PACKAGE_NAME =
+ Constants.class.getPackage().getName();
+ protected static final String SERVLET_NAME = WsServlet.class.getName();
+
+ private Constants() {
+ // Hide default constructor
+ }
+}
Propchange: tomcat/trunk/java/org/apache/tomcat/websocket/server/Constants.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties?rev=1435904&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties (added)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties Sun Jan 20 17:54:03 2013
@@ -0,0 +1,37 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+sci.newInstance.fail=Failed to create an Endpoint instance of type [{0}]
+serverContainer.endpointDeploy=Endpoint class [{0}] deploying to path [{1}] in ServletContext [{2}]
+serverContainer.missingEndpoint=An Endpoint instance has been request for path [{0}] but no matching Endpoint class was found
+serverContainer.pojoDeploy=POJO class [{0}] deploying to path [{1}] in ServletContext [{2}]
+serverContainer.servletContextMismatch=Attempted to register a POJO annotated for WebSocket at path [{0}] in the ServletContext with context path [{1}] when the WebSocket ServerContainer is allocated to the ServletContext with context path [{2}]
+serverContainer.servletContextMissing=No ServletContext was specified
+uriTemplate.noMatch=The input template [{0}] generated the pattern [{1}] which did not match the supplied pathInfo [{2}]
+# Note the wsFrame.* messages are used as close reasons in WebSocket control
+# frames and therefore must be 123 bytes (not characters) or less in length.
+# Messages are encoded using UTF-8 where a single character may be encoded in
+# as many as 4 bytes.
+wsFrame.byteToLongFail=Too many bytes ([{0}]) were provided to be converted into a long
+wsFrame.controlFragmented=A fragmented control frame was received but control frames may not be fragmented
+wsFrame.controlPayloadTooBig=A control frame was sent with a payload of size [{0}] which is larger than the maximum permitted of 125 bytes
+wsFrame.controlNoFin=A control frame was sent that did not have the fin bit set. Control frames are not permitted to use continuation frames.
+wsFrame.invalidOpCode= A WebSocket frame was sent with an unrecognised opCode of [{0}]
+wsFrame.invalidUtf8=A WebSocket text frame was received that could not be decoded to UTF-8 because it contained invalid byte sequences
+wsFrame.invalidUtf8Close=A WebSocket close frame was received with a close reason that contained invalid UTF-8 byte sequences
+wsFrame.noContinuation=A new message was started when a continuation frame was expected
+wsFrame.notMasked=The client frame was not masked but all client frames must be masked
+wsFrame.oneByteCloseCode=The client sent a close frame with a single byte payload which is not valid
+wsFrame.textMessageTooBig=The decoded text message was too big for the output buffer and the endpoint does not support partial messages
+wsFrame.wrongRsv=The client frame set the reserved bits to [{0}] which was not supported by this endpoint
\ No newline at end of file
Propchange: tomcat/trunk/java/org/apache/tomcat/websocket/server/LocalStrings.properties
------------------------------------------------------------------------------
svn:eol-style = native
Copied: tomcat/trunk/java/org/apache/tomcat/websocket/server/ServerContainerImpl.java (from r1434927, tomcat/trunk/java/org/apache/tomcat/websocket/ServerContainerImpl.java)
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/ServerContainerImpl.java?p2=tomcat/trunk/java/org/apache/tomcat/websocket/server/ServerContainerImpl.java&p1=tomcat/trunk/java/org/apache/tomcat/websocket/ServerContainerImpl.java&r1=1434927&r2=1435904&rev=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/ServerContainerImpl.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/ServerContainerImpl.java Sun Jan 20 17:54:03 2013
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tomcat.websocket;
+package org.apache.tomcat.websocket.server;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
@@ -31,6 +31,7 @@ import javax.websocket.server.ServerEndp
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.res.StringManager;
+import org.apache.tomcat.websocket.WsWebSocketContainer;
import org.apache.tomcat.websocket.pojo.PojoEndpointConfiguration;
import org.apache.tomcat.websocket.pojo.PojoMethodMapping;
@@ -111,7 +112,7 @@ public class ServerContainerImpl extends
throw new DeploymentException(sm.getString("sci.newInstance.fail",
endpointClass.getName()), e);
}
- String servletPath = Util.getServletPath(path);
+ String servletPath = getServletPath(path);
if (log.isDebugEnabled()) {
log.debug(sm.getString("serverContainer.endpointDeploy",
endpointClass.getName(), path,
@@ -150,7 +151,7 @@ public class ServerContainerImpl extends
log.debug(sm.getString("serverContainer.pojoDeploy",
pojo.getName(), wsPath, servletContext.getContextPath()));
}
- String servletPath = Util.getServletPath(wsPath);
+ String servletPath = getServletPath(wsPath);
// Remove the trailing /* before adding it to the map
pojoMap.put(servletPath.substring(0, servletPath.length() - 2), pojo);
pojoMethodMap.put(pojo,
@@ -201,4 +202,30 @@ public class ServerContainerImpl extends
public void setReadBufferSize(int readBufferSize) {
this.readBufferSize = readBufferSize;
}
+
+
+ /**
+ * Converts a path defined for a WebSocket endpoint into a path that can be
+ * used as a servlet mapping.
+ *
+ * @param wsPath The WebSocket endpoint path to convert
+ * @return The servlet mapping
+ */
+ static String getServletPath(String wsPath) {
+ int templateStart = wsPath.indexOf('{');
+ if (templateStart == -1) {
+ if (wsPath.charAt(wsPath.length() - 1) == '/') {
+ return wsPath + '*';
+ } else {
+ return wsPath + "/*";
+ }
+ } else {
+ String temp = wsPath.substring(0, templateStart);
+ if (temp.charAt(temp.length() - 1) == '/') {
+ return temp + '*';
+ } else {
+ return temp.substring(0, temp.lastIndexOf('/') + 1) + '*';
+ }
+ }
+ }
}
Copied: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsProtocolHandler.java (from r1434921, tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java)
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsProtocolHandler.java?p2=tomcat/trunk/java/org/apache/tomcat/websocket/server/WsProtocolHandler.java&p1=tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java&r1=1434921&r2=1435904&rev=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsProtocolHandler.java Sun Jan 20 17:54:03 2013
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tomcat.websocket;
+package org.apache.tomcat.websocket.server;
import java.io.EOFException;
import java.io.IOException;
@@ -30,6 +30,10 @@ import javax.websocket.CloseReason.Close
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfiguration;
+import org.apache.tomcat.websocket.WsFrame;
+import org.apache.tomcat.websocket.WsIOException;
+import org.apache.tomcat.websocket.WsSession;
+
/**
* Servlet 3.1 HTTP upgrade handler for WebSocket connections.
*/
@@ -69,10 +73,11 @@ public class WsProtocolHandler implement
try {
WsFrame wsFrame = new WsFrame(sis, wsSession);
sis.setReadListener(new WsReadListener(this, wsFrame, wsSession));
- WsRemoteEndpoint wsRemoteEndpoint =
- new WsRemoteEndpoint(wsSession, sos);
- wsSession.setRemote(wsRemoteEndpoint);
- sos.setWriteListener(new WsWriteListener(this, wsRemoteEndpoint));
+ WsRemoteEndpointServer wsRemoteEndpointServer =
+ new WsRemoteEndpointServer(wsSession, sos);
+ wsSession.setRemote(wsRemoteEndpointServer);
+ sos.setWriteListener(
+ new WsWriteListener(this, wsRemoteEndpointServer));
ep.onOpen(wsSession, endpointConfig);
} finally {
t.setContextClassLoader(cl);
@@ -150,18 +155,18 @@ public class WsProtocolHandler implement
private static class WsWriteListener implements WriteListener {
private final WsProtocolHandler wsProtocolHandler;
- private final WsRemoteEndpoint wsRemoteEndpoint;
+ private final WsRemoteEndpointServer wsRemoteEndpointServer;
private WsWriteListener(WsProtocolHandler wsProtocolHandler,
- WsRemoteEndpoint wsRemoteEndpoint) {
+ WsRemoteEndpointServer wsRemoteEndpointServer) {
this.wsProtocolHandler = wsProtocolHandler;
- this.wsRemoteEndpoint = wsRemoteEndpoint;
+ this.wsRemoteEndpointServer = wsRemoteEndpointServer;
}
@Override
public void onWritePossible() {
- wsRemoteEndpoint.onWritePossible();
+ wsRemoteEndpointServer.onWritePossible();
}
Added: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointServer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointServer.java?rev=1435904&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointServer.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointServer.java Sun Jan 20 17:54:03 2013
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.websocket.server;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+import javax.servlet.ServletOutputStream;
+
+import org.apache.tomcat.websocket.Constants;
+import org.apache.tomcat.websocket.WsRemoteEndpointBase;
+import org.apache.tomcat.websocket.WsSession;
+
+/**
+ * This is the server side {@link RemoteEndpoint} implementation - i.e. what the
+ * server uses to send data to the client. Communication is over a
+ * {@link ServletOutputStream}.
+ */
+public class WsRemoteEndpointServer extends WsRemoteEndpointBase {
+
+ private final WsSession wsSession;
+ private final ServletOutputStream sos;
+ private final Object messageWriteLock = new Object();
+
+ private volatile CyclicBarrier writeBarrier = new CyclicBarrier(2);
+
+
+ public WsRemoteEndpointServer(WsSession wsSession,
+ ServletOutputStream sos) {
+ this.wsSession = wsSession;
+ this.sos = sos;
+ }
+
+
+ @Override
+ public void onWritePossible() {
+ try {
+ writeBarrier.await();
+ } catch (InterruptedException | BrokenBarrierException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+
+ @Override
+ protected void writeMessage(int opCode, ByteBuffer header,
+ ByteBuffer message) {
+ // Could sync on sos but don't as other (user or container) code may
+ // sync on this creating the potential for deadlocks.
+ synchronized (messageWriteLock) {
+ doBlockingWrite(header);
+ doBlockingWrite(message);
+ try {
+ sos.flush();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ if (Constants.OPCODE_CLOSE == opCode) {
+ try {
+ sos.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+ if (opCode == Constants.OPCODE_CLOSE) {
+ // Connection is closing - ensure no threads are stuck waiting on
+ // the write barrier
+ writeBarrier.reset();
+ }
+ }
+
+
+ private void doBlockingWrite(ByteBuffer data) {
+ if (!sos.canWrite()) {
+ try {
+ writeBarrier.await();
+ } catch (InterruptedException | BrokenBarrierException e) {
+ wsSession.getLocalEndpoint().onError(wsSession, e);
+ }
+ }
+ try {
+ sos.write(data.array(), data.arrayOffset(), data.limit());
+ } catch (IOException e) {
+ wsSession.getLocalEndpoint().onError(wsSession, e);
+ }
+ }
+}
Propchange: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsRemoteEndpointServer.java
------------------------------------------------------------------------------
svn:eol-style = native
Copied: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsSci.java (from r1434921, tomcat/trunk/java/org/apache/tomcat/websocket/WsSci.java)
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsSci.java?p2=tomcat/trunk/java/org/apache/tomcat/websocket/server/WsSci.java&p1=tomcat/trunk/java/org/apache/tomcat/websocket/WsSci.java&r1=1434921&r2=1435904&rev=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsSci.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsSci.java Sun Jan 20 17:54:03 2013
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tomcat.websocket;
+package org.apache.tomcat.websocket.server;
import java.util.Set;
@@ -24,6 +24,7 @@ import javax.servlet.ServletException;
import javax.servlet.annotation.HandlesTypes;
import javax.websocket.server.WebSocketEndpoint;
+
/**
* Registers an interest in any class that is annotated with
* {@link WebSocketEndpoint} so that Endpoint can be published via the WebSocket
Copied: tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServlet.java (from r1434921, tomcat/trunk/java/org/apache/tomcat/websocket/WsServlet.java)
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServlet.java?p2=tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServlet.java&p1=tomcat/trunk/java/org/apache/tomcat/websocket/WsServlet.java&r1=1434921&r2=1435904&rev=1435904&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsServlet.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/WsServlet.java Sun Jan 20 17:54:03 2013
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tomcat.websocket;
+package org.apache.tomcat.websocket.server;
import java.io.IOException;
import java.nio.charset.Charset;
@@ -38,6 +38,7 @@ import javax.websocket.Extension;
import javax.websocket.server.ServerEndpointConfiguration;
import javax.xml.bind.DatatypeConverter;
+
/**
* Handles the initial HTTP connection for WebSocket connections.
*/
Added: tomcat/trunk/java/org/apache/tomcat/websocket/server/package-info.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/server/package-info.java?rev=1435904&view=auto
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/server/package-info.java (added)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/server/package-info.java Sun Jan 20 17:54:03 2013
@@ -0,0 +1,21 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * Server-side specific implementation classes. These are in a separate package
+ * to make packaging a pure client JAR simpler.
+ */
+package org.apache.tomcat.websocket.server;
\ No newline at end of file
Propchange: tomcat/trunk/java/org/apache/tomcat/websocket/server/package-info.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: tomcat/trunk/res/META-INF/tomcat-websocket.jar/services/javax.servlet.ServletContainerInitializer
URL: http://svn.apache.org/viewvc/tomcat/trunk/res/META-INF/tomcat-websocket.jar/services/javax.servlet.ServletContainerInitializer?rev=1435904&r1=1435903&r2=1435904&view=diff
==============================================================================
--- tomcat/trunk/res/META-INF/tomcat-websocket.jar/services/javax.servlet.ServletContainerInitializer (original)
+++ tomcat/trunk/res/META-INF/tomcat-websocket.jar/services/javax.servlet.ServletContainerInitializer Sun Jan 20 17:54:03 2013
@@ -1 +1 @@
-org.apache.tomcat.websocket.WsSci
+org.apache.tomcat.websocket.server.WsSci
Modified: tomcat/trunk/res/checkstyle/org-import-control.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/res/checkstyle/org-import-control.xml?rev=1435904&r1=1435903&r2=1435904&view=diff
==============================================================================
--- tomcat/trunk/res/checkstyle/org-import-control.xml (original)
+++ tomcat/trunk/res/checkstyle/org-import-control.xml Sun Jan 20 17:54:03 2013
@@ -138,12 +138,16 @@
</subpackage>
</subpackage>
<subpackage name="websocket">
- <allow pkg="javax.servlet"/>
<allow pkg="javax.websocket"/>
<allow pkg="org.apache.juli"/>
<allow pkg="org.apache.tomcat.util"/>
<!-- Ideally want to remove this -->
<allow pkg="org.apache.tomcat.websocket.pojo"/>
+ <disallow pkg="javax.servlet"/>
+ <subpackage name="server">
+ <allow pkg="javax.servlet"/>
+ <allow pkg="org.apache.tomcat.websocket"/>
+ </subpackage>
</subpackage>
</subpackage>
</import-control>
\ No newline at end of file
Added: tomcat/trunk/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java?rev=1435904&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java (added)
+++ tomcat/trunk/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java Sun Jan 20 17:54:03 2013
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.websocket;
+
+import java.io.File;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.websocket.ContainerProvider;
+import javax.websocket.DefaultClientConfiguration;
+import javax.websocket.Endpoint;
+import javax.websocket.EndpointConfiguration;
+import javax.websocket.MessageHandler;
+import javax.websocket.Session;
+import javax.websocket.WebSocketContainer;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.startup.Tomcat;
+import org.apache.catalina.startup.TomcatBaseTest;
+
+public class TestWsWebSocketContainer extends TomcatBaseTest {
+
+ private static final String MESSAGE_STRING_1 = "qwerty";
+
+ @Test
+ public void testConnectToServerEndpoint() throws Exception {
+ // Examples app includes WebSocket Echo endpoint
+ Tomcat tomcat = getTomcatInstance();
+ File appDir = new File(getBuildDirectory(), "webapps/examples");
+ tomcat.addWebapp(null, "/examples", appDir.getAbsolutePath());
+
+ tomcat.start();
+
+ WebSocketContainer wsContainer = ContainerProvider.getClientContainer();
+ Session wsSession = wsContainer.connectToServer(TesterEndpoint.class,
+ new DefaultClientConfiguration(), new URI("http://localhost:" +
+ getPort() + "/examples/echoAnnotation"));
+ TesterMessageHandlerString handler = new TesterMessageHandlerString(1);
+ wsSession.addMessageHandler(handler);
+ wsSession.getRemote().sendString(MESSAGE_STRING_1);
+
+ boolean latchResult = handler.getLatch().await(10, TimeUnit.SECONDS);
+
+ Assert.assertTrue(latchResult);
+
+ List<String> messages = handler.getMessages();
+ Assert.assertEquals(1, messages.size());
+ Assert.assertEquals(MESSAGE_STRING_1, messages.get(0));
+ }
+
+ private static class TesterMessageHandlerString
+ implements MessageHandler.Basic<String> {
+
+ private final CountDownLatch latch;
+
+ private List<String> messages = new ArrayList<>();
+
+ public TesterMessageHandlerString(int latchCount) {
+ if (latchCount > 0) {
+ latch = new CountDownLatch(latchCount);
+ } else {
+ latch = null;
+ }
+ }
+
+ public List<String> getMessages() {
+ return messages;
+ }
+
+ public CountDownLatch getLatch() {
+ return latch;
+ }
+
+ @Override
+ public void onMessage(String message) {
+ if (latch != null) {
+ latch.countDown();
+ }
+ messages.add(message);
+ }
+ }
+
+ private static class TesterEndpoint extends Endpoint {
+
+ @Override
+ public void onOpen(Session session, EndpointConfiguration config) {
+ // TODO Auto-generated method stub
+ }
+ }
+}
Propchange: tomcat/trunk/test/org/apache/tomcat/websocket/TestWsWebSocketContainer.java
------------------------------------------------------------------------------
svn:eol-style = native
Copied: tomcat/trunk/test/org/apache/tomcat/websocket/server/TestServerContainerImpl.java (from r1434921, tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java)
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/websocket/server/TestServerContainerImpl.java?p2=tomcat/trunk/test/org/apache/tomcat/websocket/server/TestServerContainerImpl.java&p1=tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java&r1=1434921&r2=1435904&rev=1435904&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/websocket/server/TestServerContainerImpl.java Sun Jan 20 17:54:03 2013
@@ -14,30 +14,30 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.tomcat.websocket;
+package org.apache.tomcat.websocket.server;
import org.junit.Assert;
import org.junit.Test;
-public class TestUtil {
+public class TestServerContainerImpl {
@Test
public void testGetServletMappingPath() throws Exception {
Assert.assertEquals("/foo/*",
- Util.getServletPath("/foo"));
+ ServerContainerImpl.getServletPath("/foo"));
Assert.assertEquals("/foo/*",
- Util.getServletPath("/foo/"));
+ ServerContainerImpl.getServletPath("/foo/"));
Assert.assertEquals("/foo/bar/*",
- Util.getServletPath("/foo/bar"));
+ ServerContainerImpl.getServletPath("/foo/bar"));
Assert.assertEquals("/foo/bar/*",
- Util.getServletPath("/foo/bar/"));
+ ServerContainerImpl.getServletPath("/foo/bar/"));
Assert.assertEquals("/foo/*",
- Util.getServletPath("/foo/{bar}"));
+ ServerContainerImpl.getServletPath("/foo/{bar}"));
Assert.assertEquals("/foo/*",
- Util.getServletPath("/foo/{bar}/"));
+ ServerContainerImpl.getServletPath("/foo/{bar}/"));
Assert.assertEquals("/foo/*",
- Util.getServletPath("/foo/x{bar}"));
+ ServerContainerImpl.getServletPath("/foo/x{bar}"));
Assert.assertEquals("/foo/*",
- Util.getServletPath("/foo/x{bar}/"));
+ ServerContainerImpl.getServletPath("/foo/x{bar}/"));
}
}
Modified: tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/WsConfigListener.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/WsConfigListener.java?rev=1435904&r1=1435903&r2=1435904&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/WsConfigListener.java (original)
+++ tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/WsConfigListener.java Sun Jan 20 17:54:03 2013
@@ -23,7 +23,7 @@ import javax.servlet.annotation.WebListe
import javax.websocket.DeploymentException;
import javax.websocket.server.DefaultServerConfiguration;
-import org.apache.tomcat.websocket.ServerContainerImpl;
+import org.apache.tomcat.websocket.server.ServerContainerImpl;
@WebListener
public class WsConfigListener implements ServletContextListener {
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org