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 2012/10/01 14:42:09 UTC

git commit: WICKET-4793 Support Jetty 9.x websocket implementation

Updated Branches:
  refs/heads/master 8fe07e5de -> 77ac60071


WICKET-4793 Support Jetty 9.x websocket implementation


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/77ac6007
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/77ac6007
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/77ac6007

Branch: refs/heads/master
Commit: 77ac60071dee246ab634ec49eb67b8544b173838
Parents: 8fe07e5
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Mon Oct 1 15:41:22 2012 +0300
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Mon Oct 1 15:41:22 2012 +0300

----------------------------------------------------------------------
 pom.xml                                            |    1 +
 .../wicket-native-websocket/pom.xml                |    1 +
 .../wicket-native-websocket-jetty9/pom.xml         |   82 ++++++++++
 .../protocol/http/Jetty9WebSocketFilter.java       |  119 +++++++++++++++
 .../ws/jetty/Jetty9WebSocketConnection.java        |  110 +++++++++++++
 .../ws/jetty/Jetty9WebSocketProcessor.java         |  102 ++++++++++++
 .../ws/util/license/ApacheLicenceHeaderTest.java   |   34 ++++
 7 files changed, 449 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/77ac6007/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index eb7eb5b..ce18916 100644
--- a/pom.xml
+++ b/pom.xml
@@ -31,6 +31,7 @@
 	<properties>
 		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
 		<jetty.version>7.6.3.v20120416</jetty.version>
+		<jetty9.version>9.0.0.M0</jetty9.version>
 		<spring.version>3.0.7.RELEASE</spring.version>
 		<maven.javadoc.version>2.8.1</maven.javadoc.version>
 		<maven.surefire.version>2.12.2</maven.surefire.version>

http://git-wip-us.apache.org/repos/asf/wicket/blob/77ac6007/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 9593ab6..e080d83 100644
--- a/wicket-experimental/wicket-native-websocket/pom.xml
+++ b/wicket-experimental/wicket-native-websocket/pom.xml
@@ -31,6 +31,7 @@
 	<modules>
 		<module>wicket-native-websocket-core</module>
 		<module>wicket-native-websocket-jetty</module>
+		<module>wicket-native-websocket-jetty9</module>
 		<module>wicket-native-websocket-tomcat</module>
 	</modules>
     <dependencyManagement>

http://git-wip-us.apache.org/repos/asf/wicket/blob/77ac6007/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/pom.xml b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/pom.xml
new file mode 100644
index 0000000..1f58eef
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/pom.xml
@@ -0,0 +1,82 @@
+<?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.4-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+    <artifactId>wicket-native-websocket-jetty9</artifactId>
+    <packaging>jar</packaging>
+    <version>0.4-SNAPSHOT</version>
+    <name>Wicket Native WebSocket Jetty 9</name>
+    <description>Provides the code specific to integrate with Jetty 9 web container</description>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.wicket</groupId>
+            <artifactId>wicket-native-websocket-core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.eclipse.jetty.websocket</groupId>
+            <artifactId>websocket-server</artifactId>
+            <version>${jetty9.version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+    </dependencies>
+    <build>
+	<pluginManagement>
+		<plugins>
+			<!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.-->
+			<plugin>
+				<groupId>org.eclipse.m2e</groupId>
+				<artifactId>lifecycle-mapping</artifactId>
+				<version>1.0.0</version>
+				<configuration>
+					<lifecycleMappingMetadata>
+						<pluginExecutions>
+							<pluginExecution>
+								<pluginExecutionFilter>
+									<groupId>
+										org.apache.felix
+									</groupId>
+									<artifactId>
+										maven-bundle-plugin
+									</artifactId>
+									<versionRange>
+										[2.3.7,)
+									</versionRange>
+									<goals>
+										<goal>manifest</goal>
+									</goals>
+								</pluginExecutionFilter>
+								<action>
+									<ignore />
+								</action>
+							</pluginExecution>
+						</pluginExecutions>
+					</lifecycleMappingMetadata>
+				</configuration>
+			</plugin>
+		</plugins>
+	</pluginManagement>
+    </build>
+</project>

http://git-wip-us.apache.org/repos/asf/wicket/blob/77ac6007/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/http/Jetty9WebSocketFilter.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/http/Jetty9WebSocketFilter.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/http/Jetty9WebSocketFilter.java
new file mode 100644
index 0000000..2ecfb7a
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/http/Jetty9WebSocketFilter.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.http;
+
+import java.io.IOException;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.protocol.ws.jetty.Jetty9WebSocketProcessor;
+import org.eclipse.jetty.websocket.core.api.UpgradeRequest;
+import org.eclipse.jetty.websocket.core.api.UpgradeResponse;
+import org.eclipse.jetty.websocket.core.api.WebSocketPolicy;
+import org.eclipse.jetty.websocket.server.WebSocketCreator;
+import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An upgrade filter that uses Jetty9's WebSocketServerFactory to decide whether to upgrade or not.
+ */
+public class Jetty9WebSocketFilter extends AbstractUpgradeFilter
+{
+	private static final Logger LOG = LoggerFactory.getLogger(Jetty9WebSocketFilter.class);
+
+	private WebSocketServerFactory _webSocketFactory;
+
+	@Override
+	public void init(final boolean isServlet, final FilterConfig filterConfig)
+		throws ServletException
+	{
+		super.init(isServlet, filterConfig);
+
+		try
+		{
+			WebSocketPolicy serverPolicy = WebSocketPolicy.newServerPolicy();
+			String bs = filterConfig.getInitParameter("bufferSize");
+			if (bs != null)
+				serverPolicy.setBufferSize(Integer.parseInt(bs));
+			String max = filterConfig.getInitParameter("maxIdleTime");
+			if (max != null)
+				serverPolicy.setIdleTimeout(Integer.parseInt(max));
+
+			max = filterConfig.getInitParameter("maxTextMessageSize");
+			if (max != null)
+				serverPolicy.setMaxTextMessageSize(Integer.parseInt(max));
+
+			max = filterConfig.getInitParameter("maxBinaryMessageSize");
+			if (max != null)
+				serverPolicy.setMaxBinaryMessageSize(Integer.parseInt(max));
+			_webSocketFactory = new WebSocketServerFactory(serverPolicy);
+
+			_webSocketFactory.setCreator(new WebSocketCreator()
+			{
+				@Override
+				public Object createWebSocket(UpgradeRequest upgradeRequest,
+					UpgradeResponse upgradeResponse)
+				{
+					return new Jetty9WebSocketProcessor(upgradeRequest, upgradeResponse,
+						getApplication());
+				}
+			});
+
+			_webSocketFactory.start();
+		}
+		catch (ServletException x)
+		{
+			throw x;
+		}
+		catch (Exception x)
+		{
+			throw new ServletException(x);
+		}
+	}
+
+	@Override
+	protected boolean acceptWebSocket(HttpServletRequest req, HttpServletResponse resp,
+		Application application) throws ServletException, IOException
+	{
+		return super.acceptWebSocket(req, resp, application) &&
+			_webSocketFactory.acceptWebSocket(req, resp);
+	}
+
+	/* ------------------------------------------------------------ */
+	@Override
+	public void destroy()
+	{
+		try
+		{
+			if (_webSocketFactory != null)
+			{
+				_webSocketFactory.stop();
+			}
+		}
+		catch (Exception x)
+		{
+			LOG.warn("A problem occurred while stopping the web socket factory", x);
+		}
+
+		super.destroy();
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/77ac6007/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/ws/jetty/Jetty9WebSocketConnection.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/ws/jetty/Jetty9WebSocketConnection.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/ws/jetty/Jetty9WebSocketConnection.java
new file mode 100644
index 0000000..bfc5d01
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/ws/jetty/Jetty9WebSocketConnection.java
@@ -0,0 +1,110 @@
+/*
+ * 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.jetty;
+
+import java.io.IOException;
+import java.io.InterruptedIOException;
+import java.util.concurrent.ExecutionException;
+
+import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
+import org.apache.wicket.util.lang.Args;
+import org.eclipse.jetty.util.Callback;
+import org.eclipse.jetty.util.FutureCallback;
+import org.eclipse.jetty.websocket.core.api.WebSocketConnection;
+
+/**
+ * A wrapper around Jetty9's native WebSocket.Connection
+ *
+ * @since 6.2
+ */
+public class Jetty9WebSocketConnection implements IWebSocketConnection
+{
+	private final WebSocketConnection connection;
+
+	/**
+	 * Constructor.
+	 *
+	 * @param connection
+	 *            the jetty websocket connection
+	 */
+	public Jetty9WebSocketConnection(WebSocketConnection connection)
+	{
+		this.connection = Args.notNull(connection, "connection");
+	}
+
+	@Override
+	public boolean isOpen()
+	{
+		return connection.isOpen();
+	}
+
+	@Override
+	public void close(int code, String reason)
+	{
+		if (isOpen())
+		{
+			connection.close(code, reason);
+		}
+	}
+
+	@Override
+	public IWebSocketConnection sendMessage(String message) throws IOException
+	{
+		checkClosed();
+
+		FutureCallback<Void> waiter = new FutureCallback<Void>();
+		connection.write(null, waiter, message);
+		waitForMessageSent(waiter);
+		return this;
+	}
+
+	@Override
+	public IWebSocketConnection sendMessage(byte[] message, int offset, int length)
+		throws IOException
+	{
+		checkClosed();
+
+		FutureCallback<Void> waiter = new FutureCallback<Void>();
+		connection.write(null, new Callback.Empty<Void>(), message, offset, length);
+		waitForMessageSent(waiter);
+		return this;
+	}
+
+	private void waitForMessageSent(FutureCallback<?> waiter) throws IOException
+	{
+		try
+		{
+			waiter.get();
+		}
+		catch (InterruptedException e)
+		{
+			throw new InterruptedIOException();
+		}
+		catch (ExecutionException e)
+		{
+			FutureCallback.rethrow(e);
+		}
+	}
+
+	private void checkClosed()
+	{
+		if (!isOpen())
+		{
+			throw new IllegalStateException("The connection is closed.");
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/77ac6007/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/ws/jetty/Jetty9WebSocketProcessor.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/ws/jetty/Jetty9WebSocketProcessor.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/ws/jetty/Jetty9WebSocketProcessor.java
new file mode 100644
index 0000000..7a5b1d4
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/main/java/org/apache/wicket/protocol/ws/jetty/Jetty9WebSocketProcessor.java
@@ -0,0 +1,102 @@
+/*
+ * 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.jetty;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.protocol.ws.api.AbstractWebSocketProcessor;
+import org.eclipse.jetty.websocket.core.annotations.WebSocket;
+import org.eclipse.jetty.websocket.core.api.UpgradeRequest;
+import org.eclipse.jetty.websocket.core.api.UpgradeResponse;
+import org.eclipse.jetty.websocket.core.api.WebSocketConnection;
+import org.eclipse.jetty.websocket.core.api.WebSocketException;
+import org.eclipse.jetty.websocket.core.api.WebSocketListener;
+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 WebSocket web socket} implementation.
+ *
+ * @since 6.2
+ */
+public class Jetty9WebSocketProcessor extends AbstractWebSocketProcessor
+	implements
+		WebSocketListener
+{
+	private static final Logger LOG = LoggerFactory.getLogger(Jetty9WebSocketProcessor.class);
+
+	/**
+	 * Constructor.
+	 *
+	 * @param upgradeRequest
+	 *            the jetty upgrade request
+	 * @param upgradeResponse
+	 *            the jetty upgrade response
+	 * @param application
+	 *            the current Wicket Application
+	 */
+	public Jetty9WebSocketProcessor(final UpgradeRequest upgradeRequest,
+		final UpgradeResponse upgradeResponse, final Application application)
+	{
+		super((HttpServletRequest)((HttpServletRequestWrapper)upgradeRequest).getRequest(),
+			application);
+	}
+
+	@Override
+	public void onWebSocketConnect(WebSocketConnection connection)
+	{
+		onConnect(new Jetty9WebSocketConnection(connection));
+	}
+
+	@Override
+	public void onWebSocketText(String message)
+	{
+		onMessage(message);
+	}
+
+	@Override
+	public void onWebSocketBinary(byte[] payload, int offset, int len)
+	{
+		onMessage(payload, offset, len);
+	}
+
+	@Override
+	public void onWebSocketClose(int statusCode, String reason)
+	{
+		onClose(statusCode, reason);
+	}
+
+	@Override
+	public void onWebSocketException(WebSocketException error)
+	{
+		LOG.error("An error occurred when using WebSocket.", error);
+	}
+
+	@Override
+	public void onOpen(Object connection)
+	{
+		if (!(connection instanceof WebSocketConnection))
+		{
+			throw new IllegalArgumentException(WebSocketConnection.class.getName() +
+				" can work only with " + WebSocketConnection.class.getName());
+		}
+		onWebSocketConnect((WebSocketConnection)connection);
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/wicket/blob/77ac6007/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/test/java/org/apache/wicket/protocol/ws/util/license/ApacheLicenceHeaderTest.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/test/java/org/apache/wicket/protocol/ws/util/license/ApacheLicenceHeaderTest.java b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/test/java/org/apache/wicket/protocol/ws/util/license/ApacheLicenceHeaderTest.java
new file mode 100644
index 0000000..9e3759d
--- /dev/null
+++ b/wicket-experimental/wicket-native-websocket/wicket-native-websocket-jetty9/src/test/java/org/apache/wicket/protocol/ws/util/license/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.license;
+
+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;
+	}
+}