You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2013/08/05 10:06:42 UTC
[2/2] git commit: WICKET-5301 Create a module for Native WebSocket
based on JSR 356
WICKET-5301 Create a module for Native WebSocket based on JSR 356
Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/36ad94dd
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/36ad94dd
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/36ad94dd
Branch: refs/heads/javax.websocket
Commit: 36ad94ddf50121dd1f288232b3e6ce8453d919a5
Parents: d6ff34e
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Mon Aug 5 10:05:47 2013 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Mon Aug 5 10:05:47 2013 +0200
----------------------------------------------------------------------
.../wicket-native-websocket/pom.xml | 1 +
.../ws/api/AbstractWebSocketProcessor.java | 1 -
.../protocol/ws/api/WebSocketBehavior.java | 4 +
.../ws/api/res/js/wicket-websocket-jquery.js | 23 +-
.../api/res/js/wicket-websocket-setup.js.tmpl | 2 +-
.../wicket-native-websocket-javax/pom.xml | 67 +++
.../ws/javax/JavaxUpgradeHttpRequest.java | 558 +++++++++++++++++++
.../ws/javax/JavaxWebSocketConnection.java | 119 ++++
.../protocol/ws/javax/JavaxWebSocketFilter.java | 280 ++++++++++
.../ws/javax/JavaxWebSocketProcessor.java | 83 +++
.../protocol/ws/javax/WicketEndpoint.java | 67 +++
.../src/test/java/log4j.properties | 16 +
.../util/licence/ApacheLicenceHeaderTest.java | 34 ++
13 files changed, 1240 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/pom.xml b/wicket-experimental/wicket-native-websocket/pom.xml
index e9e87cb..a2f8c05 100644
--- a/wicket-experimental/wicket-native-websocket/pom.xml
+++ b/wicket-experimental/wicket-native-websocket/pom.xml
@@ -33,5 +33,6 @@
<module>wicket-native-websocket-jetty</module>
<module>wicket-native-websocket-jetty9</module>
<module>wicket-native-websocket-tomcat</module>
+ <module>wicket-native-websocket-javax</module>
</modules>
</project>
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
index 16eeb5b..3ac7625 100644
--- a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
@@ -92,7 +92,6 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
public AbstractWebSocketProcessor(final HttpServletRequest request, final WebApplication application)
{
this.sessionId = request.getSession(true).getId();
- Session.get().bind();
String pageId = request.getParameter("pageId");
Checks.notEmpty(pageId, "Request parameter 'pageId' is required!");
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java
index ec2bbd5..f7f1e5d 100644
--- a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java
@@ -114,6 +114,10 @@ public abstract class WebSocketBehavior extends Behavior
Url baseUrl = component.getRequestCycle().getUrlRenderer().getBaseUrl();
CharSequence ajaxBaseUrl = Strings.escapeMarkup(baseUrl.toString());
variables.put("baseUrl", ajaxBaseUrl);
+
+ String contextPath = component.getRequest().getContextPath();
+ variables.put("contextPath", contextPath);
+
String webSocketSetupScript = webSocketSetupTemplate.asString(variables);
response.render(OnDomReadyHeaderItem.forScript(webSocketSetupScript));
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js
index d1d9495..7423c47 100644
--- a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-jquery.js
@@ -38,18 +38,15 @@
var self = this,
url,
- hashIdx,
- delim;
-
- url = document.location.toString()
- .replace('http://', 'ws://')
- .replace('https://', 'wss://');
- hashIdx = url.indexOf('#');
- if (hashIdx > -1) {
- url = url.substring(0, hashIdx);
- }
- delim = url.indexOf('?') > -1 ? '&' : '?';
- url += delim + 'pageId=' + Wicket.WebSocket.pageId;
+ protocol;
+
+ protocol = document.location.protocol
+ .replace('https:', 'wss:')
+ .replace('http:', 'ws:');
+
+ url = protocol + '//' + document.location.host + Wicket.WebSocket.contextPath + '/wicket/websocket';
+
+ url += '?pageId=' + Wicket.WebSocket.pageId;
url += '&wicket-ajax-baseurl=' + Wicket.WebSocket.baseUrl;
self.ws = new WebSocket(url);
@@ -135,4 +132,4 @@
}
};
-})();
\ No newline at end of file
+})();
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl
index 3d8950a..6d2f8a3 100644
--- a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/res/js/wicket-websocket-setup.js.tmpl
@@ -2,7 +2,7 @@
'use strict';
if (!Wicket.WebSocket.pageId) {
- jQuery.extend(Wicket.WebSocket, { pageId: ${pageId}, baseUrl: '${baseUrl}' });
+ jQuery.extend(Wicket.WebSocket, { pageId: ${pageId}, baseUrl: '${baseUrl}', contextPath: '${contextPath}' });
Wicket.WebSocket.createDefaultConnection();
}
})();
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/pom.xml b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/pom.xml
new file mode 100644
index 0000000..1d05f36
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket-native-websocket</artifactId>
+ <version>0.9-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>wicket-native-websocket-javax</artifactId>
+ <packaging>jar</packaging>
+ <version>0.9-SNAPSHOT</version>
+ <name>Wicket Native WebSocket Javax</name>
+ <description>Provides the common code needed for the different integrations with web container's WebSocket implementations</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.wicket</groupId>
+ <artifactId>wicket-native-websocket-core</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.websocket</groupId>
+ <artifactId>javax.websocket-api</artifactId>
+ <version>1.0</version>
+ <scope>provided</scope>
+ </dependency>
+
+ </dependencies>
+
+ <repositories>
+ <repository>
+ <id>tc8</id>
+ <url>https://repository.apache.org/content/repositories/orgapachetomcat-048/</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+</project>
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxUpgradeHttpRequest.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxUpgradeHttpRequest.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxUpgradeHttpRequest.java
new file mode 100644
index 0000000..2fea729
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxUpgradeHttpRequest.java
@@ -0,0 +1,558 @@
+/*
+ * 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.wicket.protocol.ws.javax;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.servlet.AsyncContext;
+import javax.servlet.DispatcherType;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
+import javax.websocket.Session;
+
+import org.apache.wicket.util.string.StringValue;
+
+/**
+ * An artificial HttpServletRequest with data collected from the
+ * available WebSocket Session and from the HandshakeRequest
+ */
+public class JavaxUpgradeHttpRequest implements HttpServletRequest
+{
+ private final HttpSession httpSession;
+ private final String queryString;
+ private final Principal userPrincipal;
+ private final String requestUri;
+ private final Map<String, String[]> parametersMap;
+ private final Map<String, List<String>> headers;
+ private final String contextPath = ""; // artificial
+
+ public JavaxUpgradeHttpRequest(final Session session)
+ {
+ Map<String, Object> userProperties = session.getUserProperties();
+ this.httpSession = (HttpSession) userProperties.get("session");
+ this.headers = (Map<String, List<String>>) userProperties.get("headers");
+ this.queryString = (String) userProperties.get("queryString");
+ this.userPrincipal = (Principal) userProperties.get("userPrincipal");
+ this.requestUri = userProperties.get("requestURI").toString();
+
+ this.parametersMap = new HashMap<>();
+
+ Map<String, List<String>> parameters = (Map<String, List<String>>) userProperties.get("parameterMap");
+ for (Map.Entry<String, List<String>> entry : parameters.entrySet())
+ {
+ String name = entry.getKey();
+ List<String> value = entry.getValue();
+ parametersMap.put(name, value.toArray(new String[value.size()]));
+ }
+ }
+
+ @Override
+ public String getAuthType()
+ {
+ return null;
+ }
+
+ @Override
+ public Cookie[] getCookies()
+ {
+ return new Cookie[0];
+ }
+
+ @Override
+ public long getDateHeader(String name)
+ {
+ String headerValue = getHeader(name);
+ return StringValue.valueOf(headerValue).toLong();
+ }
+
+ @Override
+ public String getHeader(String name)
+ {
+ String value = null;
+ if (headers != null)
+ {
+ List<String> headerValues = headers.get(name);
+ if (headerValues.isEmpty() == false)
+ {
+ value = headerValues.get(0);
+ }
+ }
+ return value;
+ }
+
+ @Override
+ public Enumeration<String> getHeaders(String name)
+ {
+ Enumeration<String> values = null;
+ if (headers != null)
+ {
+ List<String> headerValues = headers.get(name);
+ if (headerValues.isEmpty() == false)
+ {
+ final Iterator<String> iterator = headerValues.iterator();
+ values = new Enumeration<String>()
+ {
+ @Override
+ public boolean hasMoreElements()
+ {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public String nextElement()
+ {
+ return iterator.next();
+ }
+ };
+ }
+ }
+ return values;
+ }
+
+ @Override
+ public Enumeration<String> getHeaderNames()
+ {
+ Enumeration<String> names = null;
+ if (headers != null)
+ {
+ Set<String> headerNames = headers.keySet();
+ if (headerNames.isEmpty() == false)
+ {
+ final Iterator<String> iterator = headerNames.iterator();
+ names = new Enumeration<String>()
+ {
+ @Override
+ public boolean hasMoreElements()
+ {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public String nextElement()
+ {
+ return iterator.next();
+ }
+ };
+ }
+ }
+ return names;
+ }
+
+ @Override
+ public int getIntHeader(String name)
+ {
+ String headerValue = getHeader(name);
+ return StringValue.valueOf(headerValue).toInt();
+ }
+
+ @Override
+ public String getMethod()
+ {
+ return null;
+ }
+
+ @Override
+ public String getPathInfo()
+ {
+ return null;
+ }
+
+ @Override
+ public String getPathTranslated()
+ {
+ return null;
+ }
+
+ @Override
+ public String getContextPath()
+ {
+ return contextPath;
+ }
+
+ @Override
+ public String getQueryString()
+ {
+ return queryString;
+ }
+
+ @Override
+ public String getRemoteUser()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isUserInRole(String role)
+ {
+ return false;
+ }
+
+ @Override
+ public Principal getUserPrincipal()
+ {
+ return userPrincipal;
+ }
+
+ @Override
+ public String getRequestedSessionId()
+ {
+ return null;
+ }
+
+ @Override
+ public String getRequestURI()
+ {
+ return requestUri;
+ }
+
+ @Override
+ public StringBuffer getRequestURL()
+ {
+ return null;
+ }
+
+ @Override
+ public String getServletPath()
+ {
+ return null;
+ }
+
+ @Override
+ public HttpSession getSession(boolean create)
+ {
+ return httpSession;
+ }
+
+ @Override
+ public HttpSession getSession()
+ {
+ return httpSession;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdValid()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromCookie()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromURL()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isRequestedSessionIdFromUrl()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
+ {
+ return false;
+ }
+
+ @Override
+ public void login(String username, String password) throws ServletException
+ {
+ }
+
+ @Override
+ public void logout() throws ServletException
+ {
+ }
+
+ @Override
+ public Collection<Part> getParts() throws IOException, ServletException
+ {
+ return null;
+ }
+
+ @Override
+ public Part getPart(String name) throws IOException, ServletException
+ {
+ return null;
+ }
+
+ @Override
+ public Object getAttribute(String name)
+ {
+ return null;
+ }
+
+ @Override
+ public Enumeration<String> getAttributeNames()
+ {
+ return new Enumeration<String>()
+ {
+ @Override
+ public boolean hasMoreElements()
+ {
+ return false;
+ }
+
+ @Override
+ public String nextElement()
+ {
+ return null;
+ }
+ };
+ }
+
+ @Override
+ public String getCharacterEncoding()
+ {
+ return null;
+ }
+
+ @Override
+ public void setCharacterEncoding(String env) throws UnsupportedEncodingException
+ {
+ }
+
+ @Override
+ public int getContentLength()
+ {
+ return 0;
+ }
+
+ @Override
+ public String getContentType()
+ {
+ return null;
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException
+ {
+ return null;
+ }
+
+ @Override
+ public String getParameter(String name)
+ {
+ String[] values = parametersMap.get(name);
+ return values != null ? values[0] : null;
+ }
+
+ @Override
+ public Enumeration<String> getParameterNames()
+ {
+ final Iterator<String> iterator = parametersMap.keySet().iterator();
+ return new Enumeration<String>()
+ {
+ @Override
+ public boolean hasMoreElements()
+ {
+ return iterator.hasNext();
+ }
+
+ @Override
+ public String nextElement()
+ {
+ return iterator.next();
+ }
+ };
+ }
+
+ @Override
+ public String[] getParameterValues(String name)
+ {
+ return parametersMap.get(name);
+ }
+
+ @Override
+ public Map<String, String[]> getParameterMap()
+ {
+ return parametersMap;
+ }
+
+ @Override
+ public String getProtocol()
+ {
+ return null;
+ }
+
+ @Override
+ public String getScheme()
+ {
+ return null;
+ }
+
+ @Override
+ public String getServerName()
+ {
+ return null;
+ }
+
+ @Override
+ public int getServerPort()
+ {
+ return 0;
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException
+ {
+ return null;
+ }
+
+ @Override
+ public String getRemoteAddr()
+ {
+ return null;
+ }
+
+ @Override
+ public String getRemoteHost()
+ {
+ return null;
+ }
+
+ @Override
+ public void setAttribute(String name, Object o)
+ {
+ }
+
+ @Override
+ public void removeAttribute(String name)
+ {
+ }
+
+ @Override
+ public Locale getLocale()
+ {
+ return null;
+ }
+
+ @Override
+ public Enumeration<Locale> getLocales()
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isSecure()
+ {
+ return false;
+ }
+
+ @Override
+ public RequestDispatcher getRequestDispatcher(String path)
+ {
+ return null;
+ }
+
+ @Override
+ public String getRealPath(String path)
+ {
+ return null;
+ }
+
+ @Override
+ public int getRemotePort()
+ {
+ return 0;
+ }
+
+ @Override
+ public String getLocalName()
+ {
+ return null;
+ }
+
+ @Override
+ public String getLocalAddr()
+ {
+ return null;
+ }
+
+ @Override
+ public int getLocalPort()
+ {
+ return 0;
+ }
+
+ @Override
+ public ServletContext getServletContext()
+ {
+ return null;
+ }
+
+ @Override
+ public AsyncContext startAsync() throws IllegalStateException
+ {
+ return null;
+ }
+
+ @Override
+ public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) throws IllegalStateException
+ {
+ return null;
+ }
+
+ @Override
+ public boolean isAsyncStarted()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isAsyncSupported()
+ {
+ return false;
+ }
+
+ @Override
+ public AsyncContext getAsyncContext()
+ {
+ return null;
+ }
+
+ @Override
+ public DispatcherType getDispatcherType()
+ {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java
new file mode 100644
index 0000000..553682a
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketConnection.java
@@ -0,0 +1,119 @@
+/*
+ * 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.wicket.protocol.ws.javax;
+
+import java.io.IOException;
+import java.nio.ByteBuffer;
+
+import javax.websocket.CloseReason;
+import javax.websocket.Session;
+
+import org.apache.wicket.protocol.ws.api.AbstractWebSocketConnection;
+import org.apache.wicket.protocol.ws.api.AbstractWebSocketProcessor;
+import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
+import org.apache.wicket.util.lang.Args;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A wrapper around Jetty9's native WebSocketConnection.
+ *
+ * @since 6.2
+ */
+public class JavaxWebSocketConnection extends AbstractWebSocketConnection
+{
+ private static final Logger LOG = LoggerFactory.getLogger(JavaxWebSocketConnection.class);
+
+ private final Session session;
+
+ /**
+ * Constructor.
+ *
+ * @param session
+ * the jetty websocket connection
+ */
+ public JavaxWebSocketConnection(Session session, AbstractWebSocketProcessor webSocketProcessor)
+ {
+ super(webSocketProcessor);
+ this.session = Args.notNull(session, "connection");
+ }
+
+ @Override
+ public boolean isOpen()
+ {
+ return session.isOpen();
+ }
+
+ @Override
+ public void close(int code, String reason)
+ {
+ if (isOpen())
+ {
+ try
+ {
+ session.close(new CloseReason(new CloseCode(code), reason));
+ } catch (IOException iox)
+ {
+ LOG.error("An error occurred while closing WebSocket session", iox);
+ }
+ }
+ }
+
+ @Override
+ public IWebSocketConnection sendMessage(String message) throws IOException
+ {
+ checkClosed();
+
+ session.getBasicRemote().sendText(message);
+ return this;
+ }
+
+ @Override
+ public IWebSocketConnection sendMessage(byte[] message, int offset, int length)
+ throws IOException
+ {
+ checkClosed();
+
+ ByteBuffer buf = ByteBuffer.wrap(message, offset, length);
+ session.getBasicRemote().sendBinary(buf);
+ return this;
+ }
+
+ private void checkClosed()
+ {
+ if (!isOpen())
+ {
+ throw new IllegalStateException("The connection is closed.");
+ }
+ }
+
+ private static class CloseCode implements CloseReason.CloseCode
+ {
+ private final int code;
+
+ private CloseCode(int code)
+ {
+ this.code = code;
+ }
+
+ @Override
+ public int getCode()
+ {
+ return code;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketFilter.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketFilter.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketFilter.java
new file mode 100644
index 0000000..55b202b
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketFilter.java
@@ -0,0 +1,280 @@
+/*
+ * 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.wicket.protocol.ws.javax;
+
+import java.net.URI;
+import java.security.Principal;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.websocket.Decoder;
+import javax.websocket.DeploymentException;
+import javax.websocket.Encoder;
+import javax.websocket.Extension;
+import javax.websocket.HandshakeResponse;
+import javax.websocket.server.HandshakeRequest;
+import javax.websocket.server.ServerContainer;
+import javax.websocket.server.ServerEndpointConfig;
+
+import org.apache.wicket.protocol.http.WicketFilter;
+import org.apache.wicket.protocol.ws.AbstractUpgradeFilter;
+import org.apache.wicket.util.string.Strings;
+
+/**
+ * An upgrade filter that setups javax.websocket
+ */
+public class JavaxWebSocketFilter extends AbstractUpgradeFilter
+{
+ /**
+ * A fake mount path used for WebSocket endpoint.
+ * WicketFilter should not process this path.
+ * @see WicketFilter#ignorePaths
+ */
+ private static final String WICKET_WEB_SOCKET_PATH = "/wicket/websocket";
+
+ /**
+ * A key used to store the application object in WebSocket's Endpoint user properties
+ */
+ static final String APPLICATION_KEY = "wicket.application";
+
+ @Override
+ public void init(final boolean isServlet, final FilterConfig filterConfig) throws ServletException
+ {
+ super.init(isServlet, new JavaxWebSocketFilterConfig(filterConfig));
+
+ ServletContext servletContext = filterConfig.getServletContext();
+ ServerContainer sc = (ServerContainer) servletContext.getAttribute(ServerContainer.class.getName());
+
+ try
+ {
+ ServerEndpointConfig config = new WicketServerEndpointConfig(ServerEndpointConfig.Builder.create(WicketEndpoint.class, WICKET_WEB_SOCKET_PATH).build());
+ config.getUserProperties().put(APPLICATION_KEY, getApplication());
+ sc.addEndpoint(config);
+ }
+ catch (DeploymentException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ /**
+ * A wrapper of the passed FilterConfig in #init() that adds #WICKET_WEB_SOCKET_PATH to
+ * the list of ignored paths
+ */
+ private static class JavaxWebSocketFilterConfig implements FilterConfig
+ {
+ private final FilterConfig delegate;
+
+ private JavaxWebSocketFilterConfig(FilterConfig delegate)
+ {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public String getFilterName()
+ {
+ return delegate.getFilterName();
+ }
+
+ @Override
+ public ServletContext getServletContext()
+ {
+ return delegate.getServletContext();
+ }
+
+ @Override
+ public String getInitParameter(String s)
+ {
+ String result = delegate.getInitParameter(s);
+
+ if (WicketFilter.IGNORE_PATHS_PARAM.equalsIgnoreCase(s))
+ {
+ if (Strings.isEmpty(result))
+ {
+ result = WICKET_WEB_SOCKET_PATH;
+ }
+ else
+ {
+ result = result + ',' + WICKET_WEB_SOCKET_PATH;
+ }
+ }
+
+ return result;
+ }
+
+ @Override
+ public Enumeration<String> getInitParameterNames()
+ {
+ return delegate.getInitParameterNames();
+ }
+ }
+
+ /**
+ * A ServerEndpointConfig that uses custom Configurator to collect
+ * all available information from the passed HandshakeRequest
+ */
+ private static class WicketServerEndpointConfig implements ServerEndpointConfig
+ {
+ private final ServerEndpointConfig delegate;
+ private Configurator configurator;
+
+ private WicketServerEndpointConfig(ServerEndpointConfig delegate)
+ {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public Class<?> getEndpointClass()
+ {
+ return delegate.getEndpointClass();
+ }
+
+ @Override
+ public String getPath()
+ {
+ return delegate.getPath();
+ }
+
+ @Override
+ public List<String> getSubprotocols()
+ {
+ return delegate.getSubprotocols();
+ }
+
+ @Override
+ public List<Extension> getExtensions()
+ {
+ return delegate.getExtensions();
+ }
+
+ @Override
+ public Configurator getConfigurator()
+ {
+ if (configurator == null)
+ {
+ configurator = new JavaxWebSocketConfigurator(delegate.getConfigurator());
+ }
+ return configurator;
+ }
+
+ @Override
+ public List<Class<? extends Encoder>> getEncoders()
+ {
+ return delegate.getEncoders();
+ }
+
+ @Override
+ public List<Class<? extends Decoder>> getDecoders()
+ {
+ return delegate.getDecoders();
+ }
+
+ @Override
+ public Map<String, Object> getUserProperties()
+ {
+ return delegate.getUserProperties();
+ }
+ }
+
+ /**
+ * A custom Configurator that collects all available information from the HandshakeRequest
+ */
+ private static class JavaxWebSocketConfigurator extends ServerEndpointConfig.Configurator
+ {
+ private final ServerEndpointConfig.Configurator delegate;
+
+ public JavaxWebSocketConfigurator(ServerEndpointConfig.Configurator delegate)
+ {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response)
+ {
+ delegate.modifyHandshake(sec, request, response);
+
+ // do not store null keys/values because Tomcat 8 uses ConcurrentMap for UserProperties
+
+ Map<String, Object> userProperties = sec.getUserProperties();
+ Object httpSession = request.getHttpSession();
+ if (httpSession != null)
+ {
+ userProperties.put("session", httpSession);
+ }
+
+ Map<String, List<String>> headers = request.getHeaders();
+ if (headers != null)
+ {
+ userProperties.put("headers", headers);
+ }
+
+
+ Map<String, List<String>> parameterMap = request.getParameterMap();
+ if (parameterMap != null)
+ {
+ userProperties.put("parameterMap", parameterMap);
+ }
+
+
+ String queryString = request.getQueryString();
+ if (queryString != null)
+ {
+ userProperties.put("queryString", queryString);
+ }
+
+
+ URI requestURI = request.getRequestURI();
+ if (requestURI != null)
+ {
+ userProperties.put("requestURI", requestURI);
+ }
+
+ Principal userPrincipal = request.getUserPrincipal();
+ if (userPrincipal != null)
+ {
+ userProperties.put("userPrincipal", userPrincipal);
+ }
+ }
+
+ @Override
+ public String getNegotiatedSubprotocol(List<String> supported, List<String> requested)
+ {
+ return delegate.getNegotiatedSubprotocol(supported, requested);
+ }
+
+ @Override
+ public List<Extension> getNegotiatedExtensions(List<Extension> installed, List<Extension> requested)
+ {
+ return delegate.getNegotiatedExtensions(installed, requested);
+ }
+
+ @Override
+ public boolean checkOrigin(String originHeaderValue)
+ {
+ return delegate.checkOrigin(originHeaderValue);
+ }
+
+ @Override
+ public <T> T getEndpointInstance(Class<T> endpointClass) throws InstantiationException
+ {
+ return super.getEndpointInstance(endpointClass);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketProcessor.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketProcessor.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketProcessor.java
new file mode 100644
index 0000000..1fa18a9
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/JavaxWebSocketProcessor.java
@@ -0,0 +1,83 @@
+/*
+ * 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.wicket.protocol.ws.javax;
+
+import java.nio.ByteBuffer;
+
+import javax.websocket.MessageHandler;
+import javax.websocket.Session;
+
+import org.apache.wicket.protocol.http.WebApplication;
+import org.apache.wicket.protocol.ws.api.AbstractWebSocketProcessor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An {@link org.apache.wicket.protocol.ws.api.IWebSocketProcessor processor} that integrates with
+ * Jetty 9.x {@link Session web socket} implementation.
+ *
+ * @since 6.2
+ */
+public class JavaxWebSocketProcessor extends AbstractWebSocketProcessor
+{
+ private static final Logger LOG = LoggerFactory.getLogger(JavaxWebSocketProcessor.class);
+
+ /**
+ * Constructor.
+ *
+ * @param session
+ * the WebSocket session
+ * @param application
+ * the current Wicket Application
+ */
+ public JavaxWebSocketProcessor(final Session session, final WebApplication application)
+ {
+ super(new JavaxUpgradeHttpRequest(session), application);
+
+ onConnect(new JavaxWebSocketConnection(session, this));
+
+ session.addMessageHandler(new StringMessageHandler());
+ session.addMessageHandler(new BinaryMessageHandler());
+ }
+
+
+ @Override
+ public void onOpen(Object containerConnection)
+ {
+ }
+
+ private class StringMessageHandler implements MessageHandler.Whole<String>
+ {
+ @Override
+ public void onMessage(String message)
+ {
+ JavaxWebSocketProcessor.this.onMessage(message);
+ }
+ }
+
+ private class BinaryMessageHandler implements MessageHandler.Whole<ByteBuffer>
+ {
+ @Override
+ public void onMessage(ByteBuffer message)
+ {
+ byte[] array = message.array();
+ JavaxWebSocketProcessor.this.onMessage(array, 0, array.length);
+ }
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java
new file mode 100644
index 0000000..57b4e0b
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/main/java/org/apache/wicket/protocol/ws/javax/WicketEndpoint.java
@@ -0,0 +1,67 @@
+/*
+ * 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.wicket.protocol.ws.javax;
+
+import javax.websocket.CloseReason;
+import javax.websocket.Endpoint;
+import javax.websocket.EndpointConfig;
+import javax.websocket.Session;
+
+import org.apache.wicket.ThreadContext;
+import org.apache.wicket.protocol.http.WebApplication;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WicketEndpoint extends Endpoint
+{
+ private static final Logger LOG = LoggerFactory.getLogger(WicketEndpoint.class);
+
+ private JavaxWebSocketProcessor javaxWebSocketProcessor;
+
+ @Override
+ public void onOpen(Session session, EndpointConfig endpointConfig)
+ {
+ WebApplication app = (WebApplication) session.getUserProperties().get(JavaxWebSocketFilter.APPLICATION_KEY);
+
+ try
+ {
+ ThreadContext.setApplication(app);
+ javaxWebSocketProcessor = new JavaxWebSocketProcessor(session, app);
+ }
+ finally
+ {
+ ThreadContext.detach();
+ }
+
+ }
+
+ @Override
+ public void onClose(Session session, CloseReason closeReason)
+ {
+ super.onClose(session, closeReason);
+
+ javaxWebSocketProcessor.onClose(closeReason.getCloseCode().getCode(), closeReason.getReasonPhrase());
+ }
+
+ @Override
+ public void onError(Session session, Throwable t)
+ {
+ super.onError(session, t);
+
+ LOG.error("An error occurred in web socket connection with id : " + session.getId(), t);
+ }
+}
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/test/java/log4j.properties
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/test/java/log4j.properties b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/test/java/log4j.properties
new file mode 100644
index 0000000..976b5c8
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/test/java/log4j.properties
@@ -0,0 +1,16 @@
+log4j.debug=false
+
+log4j.rootLogger=INFO,Stdout
+
+# please keep this setting FATAL to avoid questions from users
+# why there are stacktraces in the test output. You can turn it
+# down if you need to when testing, but don't check it in. (eelco)
+
+# changing back to ERROR. Looks like in some cases the log4j.properties
+# in wicket gets picked which results in not printing the exceptions
+# and that can be a bit dangerous (matej)
+log4j.logger.org.apache.wicket=ERROR
+
+log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.Stdout.layout.conversionPattern=%-5p - %-26.26c{1} - %m\n
http://git-wip-us.apache.org/repos/asf/wicket/blob/36ad94dd/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/test/java/org/apache/wicket/protocol/ws/util/licence/ApacheLicenceHeaderTest.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/test/java/org/apache/wicket/protocol/ws/util/licence/ApacheLicenceHeaderTest.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/test/java/org/apache/wicket/protocol/ws/util/licence/ApacheLicenceHeaderTest.java
new file mode 100644
index 0000000..cd3cbf1
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-javax/src/test/java/org/apache/wicket/protocol/ws/util/licence/ApacheLicenceHeaderTest.java
@@ -0,0 +1,34 @@
+/*
+ * 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.wicket.protocol.ws.util.licence;
+
+import org.apache.wicket.util.license.ApacheLicenseHeaderTestCase;
+
+/**
+ * Test that the license headers are in place in this project. The tests are run from
+ * {@link org.apache.wicket.util.license.ApacheLicenseHeaderTestCase}, but you can add project specific tests here if needed.
+ */
+public class ApacheLicenceHeaderTest extends ApacheLicenseHeaderTestCase
+{
+ /**
+ * Construct.
+ */
+ public ApacheLicenceHeaderTest()
+ {
+ // addHeaders = true;
+ }
+}