Author: remm Date: Fri Oct 13 15:25:23 2017 New Revision: 1812142 URL: http://svn.apache.org/viewvc?rev=1812142&view=rev Log: Fix the merge mess caused by me cut&pasting the client code back to the container class. Noticed while porting to 8.5. Also fix the i18n property names.
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java Modified: tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties?rev=1812142&r1=1812141&r2=1812142&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/LocalStrings.properties Fri Oct 13 15:25:23 2017 @@ -127,18 +127,18 @@ wsWebSocketContainer.maxBuffer=This impl wsWebSocketContainer.missingAnnotation=Cannot use POJO class [{0}] as it is not annotated with @ClientEndpoint wsWebSocketContainer.sessionCloseFail=Session with ID [{0}] did not close cleanly -wsWebSocketClient.asynchronousSocketChannelFail=Unable to open a connection to the server -wsWebSocketClient.httpRequestFailed=The HTTP request to initiate the WebSocket connection failed -wsWebSocketClient.invalidExtensionParameters=The server responded with extension parameters the client is unable to support -wsWebSocketClient.invalidHeader=Unable to parse HTTP header as no colon is present to delimit header name and header value in [{0}]. The header has been skipped. -wsWebSocketClient.invalidStatus=The HTTP response from the server [{0}] did not permit the HTTP upgrade to WebSocket -wsWebSocketClient.invalidSubProtocol=The WebSocket server returned multiple values for the Sec-WebSocket-Protocol header -wsWebSocketClient.pathNoHost=No host was specified in URI -wsWebSocketClient.pathWrongScheme=The scheme [{0}] is not supported. The supported schemes are ws and wss -wsWebSocketClient.proxyConnectFail=Failed to connect to the configured Proxy [{0}]. The HTTP response code was [{1}] -wsWebSocketClient.sslEngineFail=Unable to create SSLEngine to support SSL/TLS connections -wsWebSocketClient.missingLocationHeader=Failed to handle HTTP response code [{0}]. Missing Location header in response -wsWebSocketClient.redirectThreshold=Cyclic Location header [{0}] detected / reached max number of redirects [{1}] of max [{2}] -wsWebSocketClient.unsupportedAuthScheme=Failed to handle HTTP response code [{0}]. Unsupported Authentication scheme [{1}] returned in response -wsWebSocketClient.failedAuthentication=Failed to handle HTTP response code [{0}]. Authentication header was not accepted by server. -wsWebSocketClient.missingWWWAuthenticateHeader=Failed to handle HTTP response code [{0}]. Missing WWW-Authenticate header in response \ No newline at end of file +wsWebSocketContainer.asynchronousSocketChannelFail=Unable to open a connection to the server +wsWebSocketContainer.httpRequestFailed=The HTTP request to initiate the WebSocket connection failed +wsWebSocketContainer.invalidExtensionParameters=The server responded with extension parameters the client is unable to support +wsWebSocketContainer.invalidHeader=Unable to parse HTTP header as no colon is present to delimit header name and header value in [{0}]. The header has been skipped. +wsWebSocketContainer.invalidStatus=The HTTP response from the server [{0}] did not permit the HTTP upgrade to WebSocket +wsWebSocketContainer.invalidSubProtocol=The WebSocket server returned multiple values for the Sec-WebSocket-Protocol header +wsWebSocketContainer.pathNoHost=No host was specified in URI +wsWebSocketContainer.pathWrongScheme=The scheme [{0}] is not supported. The supported schemes are ws and wss +wsWebSocketContainer.proxyConnectFail=Failed to connect to the configured Proxy [{0}]. The HTTP response code was [{1}] +wsWebSocketContainer.sslEngineFail=Unable to create SSLEngine to support SSL/TLS connections +wsWebSocketContainer.missingLocationHeader=Failed to handle HTTP response code [{0}]. Missing Location header in response +wsWebSocketContainer.redirectThreshold=Cyclic Location header [{0}] detected / reached max number of redirects [{1}] of max [{2}] +wsWebSocketContainer.unsupportedAuthScheme=Failed to handle HTTP response code [{0}]. Unsupported Authentication scheme [{1}] returned in response +wsWebSocketContainer.failedAuthentication=Failed to handle HTTP response code [{0}]. Authentication header was not accepted by server. +wsWebSocketContainer.missingWWWAuthenticateHeader=Failed to handle HTTP response code [{0}]. Missing WWW-Authenticate header in response \ No newline at end of file Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java?rev=1812142&r1=1812141&r2=1812142&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/WsWebSocketContainer.java Fri Oct 13 15:25:23 2017 @@ -76,7 +76,6 @@ import org.apache.tomcat.websocket.pojo. public class WsWebSocketContainer implements WebSocketContainer, BackgroundProcess { private static final StringManager sm = StringManager.getManager(WsWebSocketContainer.class); - private static final Random RANDOM = new Random(); private static final byte[] CRLF = new byte[] { 13, 10 }; @@ -195,172 +194,6 @@ public class WsWebSocketContainer implem return connectToServerRecursive(endpoint, clientEndpointConfiguration, path, new HashSet<>()); } - protected void registerSession(Endpoint endpoint, WsSession wsSession) { - - if (!wsSession.isOpen()) { - // The session was closed during onOpen. No need to register it. - return; - } - synchronized (endPointSessionMapLock) { - if (endpointSessionMap.size() == 0) { - BackgroundProcessManager.getInstance().register(this); - } - Set<WsSession> wsSessions = endpointSessionMap.get(endpoint); - if (wsSessions == null) { - wsSessions = new HashSet<>(); - endpointSessionMap.put(endpoint, wsSessions); - } - wsSessions.add(wsSession); - } - sessions.put(wsSession, wsSession); - } - - - protected void unregisterSession(Endpoint endpoint, WsSession wsSession) { - - synchronized (endPointSessionMapLock) { - Set<WsSession> wsSessions = endpointSessionMap.get(endpoint); - if (wsSessions != null) { - wsSessions.remove(wsSession); - if (wsSessions.size() == 0) { - endpointSessionMap.remove(endpoint); - } - } - if (endpointSessionMap.size() == 0) { - BackgroundProcessManager.getInstance().unregister(this); - } - } - sessions.remove(wsSession); - } - - - Set<Session> getOpenSessions(Endpoint endpoint) { - Set<Session> result = new HashSet<>(); - synchronized (endPointSessionMapLock) { - Set<WsSession> sessions = endpointSessionMap.get(endpoint); - if (sessions != null) { - result.addAll(sessions); - } - } - return result; - } - - @Override - public long getDefaultMaxSessionIdleTimeout() { - return defaultMaxSessionIdleTimeout; - } - - - @Override - public void setDefaultMaxSessionIdleTimeout(long timeout) { - this.defaultMaxSessionIdleTimeout = timeout; - } - - - @Override - public int getDefaultMaxBinaryMessageBufferSize() { - return maxBinaryMessageBufferSize; - } - - - @Override - public void setDefaultMaxBinaryMessageBufferSize(int max) { - maxBinaryMessageBufferSize = max; - } - - - @Override - public int getDefaultMaxTextMessageBufferSize() { - return maxTextMessageBufferSize; - } - - - @Override - public void setDefaultMaxTextMessageBufferSize(int max) { - maxTextMessageBufferSize = max; - } - - - /** - * {@inheritDoc} - * - * Currently, this implementation does not support any extensions. - */ - @Override - public Set<Extension> getInstalledExtensions() { - return Collections.emptySet(); - } - - - /** - * {@inheritDoc} - * - * The default value for this implementation is -1. - */ - @Override - public long getDefaultAsyncSendTimeout() { - return defaultAsyncTimeout; - } - - - /** - * {@inheritDoc} - * - * The default value for this implementation is -1. - */ - @Override - public void setAsyncSendTimeout(long timeout) { - this.defaultAsyncTimeout = timeout; - } - - - /** - * Cleans up the resources still in use by WebSocket sessions created from - * this container. This includes closing sessions and cancelling - * {@link Future}s associated with blocking read/writes. - */ - public void destroy() { - CloseReason cr = new CloseReason( - CloseCodes.GOING_AWAY, sm.getString("wsWebSocketContainer.shutdown")); - - for (WsSession session : sessions.keySet()) { - try { - session.close(cr); - } catch (IOException ioe) { - log.debug(sm.getString( - "wsWebSocketContainer.sessionCloseFail", session.getId()), ioe); - } - } - - // Only unregister with AsyncChannelGroupUtil if this instance - // registered with it - if (asynchronousChannelGroup != null) { - synchronized (asynchronousChannelGroupLock) { - if (asynchronousChannelGroup != null) { - AsyncChannelGroupUtil.unregister(); - asynchronousChannelGroup = null; - } - } - } - } - - - protected AsynchronousChannelGroup getAsynchronousChannelGroup() { - // Use AsyncChannelGroupUtil to share a common group amongst all - // WebSocket clients - AsynchronousChannelGroup result = asynchronousChannelGroup; - if (result == null) { - synchronized (asynchronousChannelGroupLock) { - if (asynchronousChannelGroup == null) { - asynchronousChannelGroup = AsyncChannelGroupUtil.register(); - } - result = asynchronousChannelGroup; - } - } - return result; - } - - private Session connectToServerRecursive(Endpoint endpoint, ClientEndpointConfig clientEndpointConfiguration, URI path, Set<URI> redirectSet) @@ -379,14 +212,14 @@ public class WsWebSocketContainer implem secure = true; } else { throw new DeploymentException(sm.getString( - "wsWebSocketClient.pathWrongScheme", scheme)); + "wsWebSocketContainer.pathWrongScheme", scheme)); } // Validate host String host = path.getHost(); if (host == null) { throw new DeploymentException( - sm.getString("wsWebSocketClient.pathNoHost")); + sm.getString("wsWebSocketContainer.pathNoHost")); } int port = path.getPort(); @@ -445,7 +278,7 @@ public class WsWebSocketContainer implem socketChannel = AsynchronousSocketChannel.open(getAsynchronousChannelGroup()); } catch (IOException ioe) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.asynchronousSocketChannelFail"), ioe); + "wsWebSocketContainer.asynchronousSocketChannelFail"), ioe); } Map<String,Object> userProperties = clientEndpointConfiguration.getUserProperties(); @@ -478,7 +311,7 @@ public class WsWebSocketContainer implem HttpResponse httpResponse = processResponse(response, channel, timeout); if (httpResponse.getStatus() != 200) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.proxyConnectFail", selectedProxy, + "wsWebSocketContainer.proxyConnectFail", selectedProxy, Integer.toString(httpResponse.getStatus()))); } } catch (TimeoutException | InterruptedException | ExecutionException | @@ -487,7 +320,7 @@ public class WsWebSocketContainer implem channel.close(); } throw new DeploymentException( - sm.getString("wsWebSocketClient.httpRequestFailed"), e); + sm.getString("wsWebSocketContainer.httpRequestFailed"), e); } } @@ -530,7 +363,7 @@ public class WsWebSocketContainer implem if (locationHeader == null || locationHeader.isEmpty() || locationHeader.get(0) == null || locationHeader.get(0).isEmpty()) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.missingLocationHeader", + "wsWebSocketContainer.missingLocationHeader", Integer.toString(httpResponse.status))); } @@ -551,7 +384,7 @@ public class WsWebSocketContainer implem if (!redirectSet.add(redirectLocation) || redirectSet.size() > maxRedirects) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.redirectThreshold", redirectLocation, + "wsWebSocketContainer.redirectThreshold", redirectLocation, Integer.toString(redirectSet.size()), Integer.toString(maxRedirects))); } @@ -564,7 +397,7 @@ public class WsWebSocketContainer implem if (userProperties.get(Constants.AUTHORIZATION_HEADER_NAME) != null) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.failedAuthentication", + "wsWebSocketContainer.failedAuthentication", Integer.valueOf(httpResponse.status))); } @@ -574,7 +407,7 @@ public class WsWebSocketContainer implem if (wwwAuthenticateHeaders == null || wwwAuthenticateHeaders.isEmpty() || wwwAuthenticateHeaders.get(0) == null || wwwAuthenticateHeaders.get(0).isEmpty()) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.missingWWWAuthenticateHeader", + "wsWebSocketContainer.missingWWWAuthenticateHeader", Integer.toString(httpResponse.status))); } @@ -586,7 +419,7 @@ public class WsWebSocketContainer implem if (auth == null) { throw new DeploymentException( - sm.getString("wsWebSocketClient.unsupportedAuthScheme", + sm.getString("wsWebSocketContainer.unsupportedAuthScheme", Integer.valueOf(httpResponse.status), authScheme)); } @@ -598,7 +431,7 @@ public class WsWebSocketContainer implem } else { - throw new DeploymentException(sm.getString("wsWebSocketClient.invalidStatus", + throw new DeploymentException(sm.getString("wsWebSocketContainer.invalidStatus", Integer.toString(httpResponse.status))); } } @@ -614,7 +447,7 @@ public class WsWebSocketContainer implem subProtocol = protocolHeaders.get(0); } else { throw new DeploymentException( - sm.getString("wsWebSocketClient.invalidSubProtocol")); + sm.getString("wsWebSocketContainer.invalidSubProtocol")); } // Extensions @@ -636,7 +469,7 @@ public class WsWebSocketContainer implem Transformation t = factory.create(extension.getName(), wrapper, false); if (t == null) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.invalidExtensionParameters")); + "wsWebSocketContainer.invalidExtensionParameters")); } if (transformation == null) { transformation = t; @@ -649,7 +482,7 @@ public class WsWebSocketContainer implem } catch (ExecutionException | InterruptedException | SSLException | EOFException | TimeoutException | URISyntaxException | AuthenticationException e) { throw new DeploymentException( - sm.getString("wsWebSocketClient.httpRequestFailed"), e); + sm.getString("wsWebSocketContainer.httpRequestFailed"), e); } finally { if (!success) { channel.close(); @@ -744,6 +577,56 @@ public class WsWebSocketContainer implem return ByteBuffer.wrap(bytes); } + protected void registerSession(Endpoint endpoint, WsSession wsSession) { + + if (!wsSession.isOpen()) { + // The session was closed during onOpen. No need to register it. + return; + } + synchronized (endPointSessionMapLock) { + if (endpointSessionMap.size() == 0) { + BackgroundProcessManager.getInstance().register(this); + } + Set<WsSession> wsSessions = endpointSessionMap.get(endpoint); + if (wsSessions == null) { + wsSessions = new HashSet<>(); + endpointSessionMap.put(endpoint, wsSessions); + } + wsSessions.add(wsSession); + } + sessions.put(wsSession, wsSession); + } + + + protected void unregisterSession(Endpoint endpoint, WsSession wsSession) { + + synchronized (endPointSessionMapLock) { + Set<WsSession> wsSessions = endpointSessionMap.get(endpoint); + if (wsSessions != null) { + wsSessions.remove(wsSession); + if (wsSessions.size() == 0) { + endpointSessionMap.remove(endpoint); + } + } + if (endpointSessionMap.size() == 0) { + BackgroundProcessManager.getInstance().unregister(this); + } + } + sessions.remove(wsSession); + } + + + Set<Session> getOpenSessions(Endpoint endpoint) { + HashSet<Session> result = new HashSet<>(); + synchronized (endPointSessionMapLock) { + Set<WsSession> sessions = endpointSessionMap.get(endpoint); + if (sessions != null) { + result.addAll(sessions); + } + } + return result; + } + private static Map<String, List<String>> createRequestHeaders(String host, int port, ClientEndpointConfig clientEndpointConfiguration) { @@ -933,13 +816,13 @@ public class WsWebSocketContainer implem // CONNECT for proxy may return a 1.0 response if (parts.length < 2 || !("HTTP/1.0".equals(parts[0]) || "HTTP/1.1".equals(parts[0]))) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.invalidStatus", line)); + "wsWebSocketContainer.invalidStatus", line)); } try { return Integer.parseInt(parts[1]); } catch (NumberFormatException nfe) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.invalidStatus", line)); + "wsWebSocketContainer.invalidStatus", line)); } } @@ -949,7 +832,7 @@ public class WsWebSocketContainer implem int index = line.indexOf(':'); if (index == -1) { - log.warn(sm.getString("wsWebSocketClient.invalidHeader", line)); + log.warn(sm.getString("wsWebSocketContainer.invalidHeader", line)); return; } // Header names are case insensitive so always use lower case @@ -1034,28 +917,127 @@ public class WsWebSocketContainer implem return engine; } catch (Exception e) { throw new DeploymentException(sm.getString( - "wsWebSocketClient.sslEngineFail"), e); + "wsWebSocketContainer.sslEngineFail"), e); } } - private static class HttpResponse { - private final int status; - private final HandshakeResponse handshakeResponse; - public HttpResponse(int status, HandshakeResponse handshakeResponse) { - this.status = status; - this.handshakeResponse = handshakeResponse; + @Override + public long getDefaultMaxSessionIdleTimeout() { + return defaultMaxSessionIdleTimeout; + } + + + @Override + public void setDefaultMaxSessionIdleTimeout(long timeout) { + this.defaultMaxSessionIdleTimeout = timeout; + } + + + @Override + public int getDefaultMaxBinaryMessageBufferSize() { + return maxBinaryMessageBufferSize; + } + + + @Override + public void setDefaultMaxBinaryMessageBufferSize(int max) { + maxBinaryMessageBufferSize = max; + } + + + @Override + public int getDefaultMaxTextMessageBufferSize() { + return maxTextMessageBufferSize; + } + + + @Override + public void setDefaultMaxTextMessageBufferSize(int max) { + maxTextMessageBufferSize = max; + } + + + /** + * {@inheritDoc} + * + * Currently, this implementation does not support any extensions. + */ + @Override + public Set<Extension> getInstalledExtensions() { + return Collections.emptySet(); + } + + + /** + * {@inheritDoc} + * + * The default value for this implementation is -1. + */ + @Override + public long getDefaultAsyncSendTimeout() { + return defaultAsyncTimeout; + } + + + /** + * {@inheritDoc} + * + * The default value for this implementation is -1. + */ + @Override + public void setAsyncSendTimeout(long timeout) { + this.defaultAsyncTimeout = timeout; + } + + + /** + * Cleans up the resources still in use by WebSocket sessions created from + * this container. This includes closing sessions and cancelling + * {@link Future}s associated with blocking read/writes. + */ + public void destroy() { + CloseReason cr = new CloseReason( + CloseCodes.GOING_AWAY, sm.getString("wsWebSocketContainer.shutdown")); + + for (WsSession session : sessions.keySet()) { + try { + session.close(cr); + } catch (IOException ioe) { + log.debug(sm.getString( + "wsWebSocketContainer.sessionCloseFail", session.getId()), ioe); + } } - public int getStatus() { - return status; + // Only unregister with AsyncChannelGroupUtil if this instance + // registered with it + if (asynchronousChannelGroup != null) { + synchronized (asynchronousChannelGroupLock) { + if (asynchronousChannelGroup != null) { + AsyncChannelGroupUtil.unregister(); + asynchronousChannelGroup = null; + } + } } + } - public HandshakeResponse getHandshakeResponse() { - return handshakeResponse; + + private AsynchronousChannelGroup getAsynchronousChannelGroup() { + // Use AsyncChannelGroupUtil to share a common group amongst all + // WebSocket clients + AsynchronousChannelGroup result = asynchronousChannelGroup; + if (result == null) { + synchronized (asynchronousChannelGroupLock) { + if (asynchronousChannelGroup == null) { + asynchronousChannelGroup = AsyncChannelGroupUtil.register(); + } + result = asynchronousChannelGroup; + } } + return result; } + // ----------------------------------------------- BackgroundProcess methods @Override @@ -1090,4 +1072,24 @@ public class WsWebSocketContainer implem return processPeriod; } + + private static class HttpResponse { + private final int status; + private final HandshakeResponse handshakeResponse; + + public HttpResponse(int status, HandshakeResponse handshakeResponse) { + this.status = status; + this.handshakeResponse = handshakeResponse; + } + + + public int getStatus() { + return status; + } + + + public HandshakeResponse getHandshakeResponse() { + return handshakeResponse; + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org