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 <[email protected]> Authored: Mon Oct 1 15:41:22 2012 +0300 Committer: Martin Tzvetanov Grigorov <[email protected]> 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; + } +}
