All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.atmosphere.container.JSR356Endpoint Maven / Gradle / Ivy
/*
* Copyright 2015 Async-IO.org
*
* Licensed 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.atmosphere.container;
import org.atmosphere.container.version.JSR356WebSocket;
import org.atmosphere.cpr.ApplicationConfig;
import org.atmosphere.cpr.AtmosphereFramework;
import org.atmosphere.cpr.AtmosphereRequest;
import org.atmosphere.cpr.AtmosphereResponse;
import org.atmosphere.util.IOUtils;
import org.atmosphere.websocket.WebSocket;
import org.atmosphere.websocket.WebSocketEventListener;
import org.atmosphere.websocket.WebSocketProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.servlet.http.HttpSession;
import javax.websocket.CloseReason;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.Session;
import javax.websocket.server.HandshakeRequest;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import static org.atmosphere.cpr.ApplicationConfig.ALLOW_QUERYSTRING_AS_REQUEST;
public class JSR356Endpoint extends Endpoint {
private static final Logger logger = LoggerFactory.getLogger(JSR356Endpoint.class);
private final static String JAVAX_WEBSOCKET_ENDPOINT_LOCAL_ADDRESS = "javax.websocket.endpoint.localAddress";
private final static String JAVAX_WEBSOCKET_ENDPOINT_REMOTE_ADDRESS = "javax.websocket.endpoint.remoteAddress";
private final WebSocketProcessor webSocketProcessor;
private final Integer maxBinaryBufferSize;
private final Integer maxTextBufferSize;
private AtmosphereRequest request;
private final AtmosphereFramework framework;
private WebSocket webSocket;
private final int webSocketWriteTimeout;
private HandshakeRequest handshakeRequest;
public JSR356Endpoint(AtmosphereFramework framework, WebSocketProcessor webSocketProcessor) {
this.framework = framework;
this.webSocketProcessor = webSocketProcessor;
if (framework.isUseNativeImplementation()) {
throw new IllegalStateException("You cannot use WebSocket native implementation with JSR356. Please set " + ApplicationConfig.PROPERTY_NATIVE_COMETSUPPORT + " to false");
}
String s = framework.getAtmosphereConfig().getInitParameter(ApplicationConfig.WEBSOCKET_IDLETIME);
if (s != null) {
webSocketWriteTimeout = Integer.valueOf(s);
} else {
webSocketWriteTimeout = -1;
}
s = framework.getAtmosphereConfig().getInitParameter(ApplicationConfig.WEBSOCKET_MAXBINARYSIZE);
if (s != null) {
maxBinaryBufferSize = Integer.valueOf(s);
} else {
maxBinaryBufferSize = -1;
}
s = framework.getAtmosphereConfig().getInitParameter(ApplicationConfig.WEBSOCKET_MAXTEXTSIZE);
if (s != null) {
maxTextBufferSize = Integer.valueOf(s);
} else {
maxTextBufferSize = -1;
}
}
public JSR356Endpoint handshakeRequest(HandshakeRequest handshakeRequest) {
this.handshakeRequest = handshakeRequest;
return this;
}
@Override
public void onOpen(Session session, final EndpointConfig endpointConfig) {
if (framework.isDestroyed()) return;
if (!webSocketProcessor.handshake(request)) {
try {
session.close(new CloseReason(CloseReason.CloseCodes.CANNOT_ACCEPT, "Handshake not accepted."));
} catch (IOException e) {
logger.trace("", e);
}
return;
}
if (!session.isOpen()) {
logger.trace("Session Closed {}", session);
return;
}
if (maxBinaryBufferSize != -1) session.setMaxBinaryMessageBufferSize(maxBinaryBufferSize);
if (webSocketWriteTimeout != -1) session.setMaxIdleTimeout(webSocketWriteTimeout);
if (maxTextBufferSize != -1) session.setMaxTextMessageBufferSize(maxTextBufferSize);
webSocket = new JSR356WebSocket(session, framework.getAtmosphereConfig());
Map headers = new HashMap();
// TODO: We don't support multi map header, which cause => https://github.com/Atmosphere/atmosphere/issues/1945
for (Map.Entry> e : handshakeRequest.getHeaders().entrySet()) {
headers.put(e.getKey(), e.getValue().size() > 0 ? e.getValue().get(0) : "");
}
// Force WebSocket. Hack for https://github.com/Atmosphere/atmosphere/issues/1944
headers.put("Connection", "Upgrade");
String servletPath = framework.getAtmosphereConfig().getInitParameter(ApplicationConfig.JSR356_MAPPING_PATH);
if (servletPath == null) {
servletPath = IOUtils.guestServletPath(framework.getAtmosphereConfig());
}
URI uri = session.getRequestURI();
String[] paths = uri.getPath() != null ? uri.getPath().split("/") : new String[]{};
int pathInfoStartIndex = 3;
String contextPath = framework.getAtmosphereConfig().getServletContext().getContextPath();
if ("".equals(contextPath) || "".equals(servletPath)) {
pathInfoStartIndex = 2;
}
// /contextPath/servletPath/pathInfo or /servletPath/pathInfo
StringBuffer b = new StringBuffer("/");
for (int i = 0; i < paths.length; i++) {
if (i >= pathInfoStartIndex) {
b.append(paths[i]).append("/");
}
}
if (b.length() > 1) {
b.deleteCharAt(b.length() - 1);
}
String pathInfo = b.toString();
if (pathInfo.equals("/")) {
pathInfo = null;
}
try {
String requestURL = uri.toASCIIString();
if (requestURL.contains("?")) {
requestURL = requestURL.substring(0, requestURL.indexOf("?"));
}
// https://issues.apache.org/bugzilla/show_bug.cgi?id=56573
// https://java.net/jira/browse/WEBSOCKET_SPEC-228
if ((!requestURL.startsWith("http://")) || (!requestURL.startsWith("https://"))) {
if (requestURL.startsWith("/")) {
List l = handshakeRequest.getHeaders().get("origin");
if (l == null) {
// https://issues.jboss.org/browse/UNDERTOW-252
l = handshakeRequest.getHeaders().get("Origin");
}
String origin;
if (l != null && l.size() > 0) {
origin = l.get(0);
} else {
// Broken WebSocket Spec
logger.trace("Unable to retrieve the `origin` header for websocket {}", session);
origin = new StringBuilder("http").append(session.isSecure() ? "s" : "").append("://0.0.0.0:80").toString();
}
requestURL = new StringBuilder(origin).append(requestURL).toString();
} else if (requestURL.startsWith("ws://")) {
requestURL = requestURL.replace("ws://", "http://");
} else if (requestURL.startsWith("wss://")) {
requestURL = requestURL.replace("wss://", "https://");
}
}
request = new AtmosphereRequest.Builder()
.requestURI(uri.getPath())
.requestURL(requestURL)
.headers(headers)
.session((HttpSession) handshakeRequest.getHttpSession())
.servletPath(servletPath)
.contextPath(framework.getServletContext().getContextPath())
.pathInfo(pathInfo)
.userPrincipal(session.getUserPrincipal())
.remoteInetSocketAddress(new Callable() {
@Override
public InetSocketAddress call() throws Exception {
return (InetSocketAddress) endpointConfig.getUserProperties().get(JAVAX_WEBSOCKET_ENDPOINT_REMOTE_ADDRESS);
}
})
.localInetSocketAddress(new Callable() {
@Override
public InetSocketAddress call() throws Exception {
return (InetSocketAddress) endpointConfig.getUserProperties().get(JAVAX_WEBSOCKET_ENDPOINT_LOCAL_ADDRESS);
}
})
.build()
.queryString(session.getQueryString());
// TODO: Fix this crazy code.
framework.addInitParameter(ALLOW_QUERYSTRING_AS_REQUEST, "false");
webSocketProcessor.open(webSocket, request, AtmosphereResponse.newInstance(framework.getAtmosphereConfig(), request, webSocket));
framework.addInitParameter(ALLOW_QUERYSTRING_AS_REQUEST, "true");
if (session.isOpen()) {
session.addMessageHandler(new MessageHandler.Whole() {
@Override
public void onMessage(String s) {
webSocketProcessor.invokeWebSocketProtocol(webSocket, s);
}
});
session.addMessageHandler(new MessageHandler.Whole() {
@Override
public void onMessage(ByteBuffer bb) {
byte[] b = bb.hasArray() ? bb.array() : new byte[bb.limit()];
bb.get(b);
webSocketProcessor.invokeWebSocketProtocol(webSocket, b, 0, b.length);
}
});
} else {
logger.trace("Session closed during onOpen {}", session);
onClose(session, new CloseReason(CloseReason.CloseCodes.GOING_AWAY, "Session closed already"));
}
} catch (Throwable e) {
if (session.isOpen()){
logger.error("", e);
} else {
logger.trace("Session closed during onOpen", e);
}
try {
session.close(new CloseReason(CloseReason.CloseCodes.UNEXPECTED_CONDITION, e.getMessage()));
} catch (IOException e1) {
logger.trace("", e);
}
return;
}
}
@Override
public void onClose(javax.websocket.Session session, javax.websocket.CloseReason closeCode) {
logger.trace("{} closed {}", session, closeCode);
if (request != null) {
request.destroy();
webSocketProcessor.close(webSocket, closeCode.getCloseCode().getCode());
}
}
@Override
public void onError(javax.websocket.Session session, java.lang.Throwable t) {
try {
logger.error("", t);
webSocketProcessor.notifyListener(webSocket,
new WebSocketEventListener.WebSocketEvent(t, WebSocketEventListener.WebSocketEvent.TYPE.EXCEPTION, webSocket));
} catch (Exception ex) {
// Ignore completely
// https://github.com/Atmosphere/atmosphere/issues/1758
}
}
}