From d8a6bed74ae78c54101192ac30917316b8c08c64 Mon Sep 17 00:00:00 2001 From: Jesse McConnell Date: Thu, 7 Apr 2016 10:43:12 -0500 Subject: [PATCH 1/4] set proper scm info --- pom.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pom.xml b/pom.xml index a93de594f94..a2ab73b26c5 100644 --- a/pom.xml +++ b/pom.xml @@ -23,9 +23,9 @@ undefined - scm:git:http://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git - scm:git:ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git - http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree + scm:git:https://github.com/eclipse/jetty.project.git + scm:git:git@github.com:eclipse/jetty.project.git + https://github.com/eclipse/jetty.project HEAD From 3630f623d89254c0777bf7174481645c8521b951 Mon Sep 17 00:00:00 2001 From: Pavel Baranchikov Date: Tue, 22 Mar 2016 16:33:38 +0300 Subject: [PATCH 2/4] Fix #437 Avoid NPE on receiving empty message though MessageHandler.Partial Signed-off-by: Pavel Baranchikov --- .../jsr356/messages/BinaryPartialMessage.java | 6 +- .../jsr356/MessageReceivingTest.java | 308 ++++++++++++++++++ 2 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageReceivingTest.java diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/BinaryPartialMessage.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/BinaryPartialMessage.java index 5f94de7966b..7acb6807514 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/BinaryPartialMessage.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/BinaryPartialMessage.java @@ -51,14 +51,16 @@ public class BinaryPartialMessage implements MessageAppender // Supported Partial<> Type #1: ByteBuffer if (msgWrapper.isMessageType(ByteBuffer.class)) { - partialHandler.onMessage(payload.slice(),isLast); + partialHandler.onMessage(payload==null?ByteBuffer.allocate(0): + payload.slice(),isLast); return; } // Supported Partial<> Type #2: byte[] if (msgWrapper.isMessageType(byte[].class)) { - partialHandler.onMessage(BufferUtil.toArray(payload),isLast); + partialHandler.onMessage(payload==null?new byte[0]: + BufferUtil.toArray(payload),isLast); return; } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageReceivingTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageReceivingTest.java new file mode 100644 index 00000000000..92676d2c06a --- /dev/null +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageReceivingTest.java @@ -0,0 +1,308 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.websocket.jsr356; + +import static org.hamcrest.Matchers.instanceOf; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import javax.websocket.ContainerProvider; +import javax.websocket.Endpoint; +import javax.websocket.EndpointConfig; +import javax.websocket.MessageHandler; +import javax.websocket.Session; +import javax.websocket.WebSocketContainer; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.handler.ContextHandler; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; + +/** + * This class tests receiving of messages by different types of {@link MessageHandler} + */ +public class MessageReceivingTest { + private static final Logger LOG = Log.getLogger(EndpointEchoTest.class); + private static Server server; + private static EchoHandler handler; + private static URI serverUri; + private WebSocketContainer container; + private final String VERY_LONG_STRING; + + public MessageReceivingTest() { + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < 1024 * 1024; i++) { + sb.append(i & 1); + } + VERY_LONG_STRING = sb.toString(); + } + + @BeforeClass + public static void startServer() throws Exception { + server = new Server(); + ServerConnector connector = new ServerConnector(server); + server.addConnector(connector); + + handler = new EchoHandler(); + + ContextHandler context = new ContextHandler(); + context.setContextPath("/"); + context.setHandler(handler); + server.setHandler(context); + + // Start Server + server.start(); + + String host = connector.getHost(); + if (host == null) { + host = "localhost"; + } + int port = connector.getLocalPort(); + serverUri = new URI(String.format("ws://%s:%d/", host, port)); + } + + @AfterClass + public static void stopServer() { + try { + server.stop(); + } catch (Exception e) { + e.printStackTrace(System.err); + } + } + + @Before + public void configureTest() { + container = ContainerProvider.getWebSocketContainer(); + } + + /** + * Method tests receiving of text messages at once. + * + * @throws Exception on exception occur + */ + @Test + public void testWholeTextMessage() throws Exception { + final TestEndpoint echoer = new TestEndpoint(new WholeStringCaptureHandler()); + Assert.assertThat(echoer, instanceOf(javax.websocket.Endpoint.class)); + // Issue connect using instance of class that extends Endpoint + final Session session = container.connectToServer(echoer, serverUri); + if (LOG.isDebugEnabled()) + LOG.debug("Client Connected: {}", session); + session.getBasicRemote().sendText(""); + session.getBasicRemote().sendText("Echo"); + session.getBasicRemote().sendText(VERY_LONG_STRING); + session.getBasicRemote().sendText("Echo"); + if (LOG.isDebugEnabled()) + LOG.debug("Client Message Sent"); + echoer.handler.getMessageQueue().awaitMessages(2, 1000, TimeUnit.MILLISECONDS); + } + + /** + * Method tests receiving of text messages by parts. + * + * @throws Exception on exception occur + */ + @Test + public void testPartialTextMessage() throws Exception { + final TestEndpoint echoer = new TestEndpoint(new PartialStringCaptureHandler()); + Assert.assertThat(echoer, instanceOf(javax.websocket.Endpoint.class)); + // Issue connect using instance of class that extends Endpoint + final Session session = container.connectToServer(echoer, serverUri); + if (LOG.isDebugEnabled()) + LOG.debug("Client Connected: {}", session); + session.getBasicRemote().sendText(""); + session.getBasicRemote().sendText("Echo"); + if (LOG.isDebugEnabled()) + LOG.debug("Client Message Sent"); + echoer.handler.getMessageQueue().awaitMessages(2, 1000, TimeUnit.MILLISECONDS); + } + + /** + * Method tests receiving of binary messages at once. + * + * @throws Exception on exception occur + */ + @Test + public void testWholeBinaryMessage() throws Exception { + final TestEndpoint echoer = new TestEndpoint(new WholeByteBufferCaptureHandler()); + Assert.assertThat(echoer, instanceOf(javax.websocket.Endpoint.class)); + // Issue connect using instance of class that extends Endpoint + final Session session = container.connectToServer(echoer, serverUri); + if (LOG.isDebugEnabled()) + LOG.debug("Client Connected: {}", session); + sendBinary(session, ""); + sendBinary(session, "Echo"); + if (LOG.isDebugEnabled()) + LOG.debug("Client Message Sent"); + echoer.handler.getMessageQueue().awaitMessages(2, 1000, TimeUnit.MILLISECONDS); + } + + /** + * Method tests receiving of binary messages by parts. + * + * @throws Exception on exception occur + */ + @Test + public void testPartialBinaryMessage() throws Exception { + final TestEndpoint echoer = new TestEndpoint(new PartialByteBufferCaptureHandler()); + Assert.assertThat(echoer, instanceOf(javax.websocket.Endpoint.class)); + // Issue connect using instance of class that extends Endpoint + final Session session = container.connectToServer(echoer, serverUri); + if (LOG.isDebugEnabled()) + LOG.debug("Client Connected: {}", session); + sendBinary(session, ""); + sendBinary(session, "Echo"); + if (LOG.isDebugEnabled()) + LOG.debug("Client Message Sent"); + echoer.handler.getMessageQueue().awaitMessages(2, 1000, TimeUnit.MILLISECONDS); + } + + private static void sendBinary(Session session, String message) throws IOException { + final ByteBuffer bb = ByteBuffer.wrap(message.getBytes()); + session.getBasicRemote().sendBinary(bb); + } + + private static class TestEndpoint extends Endpoint { + public final AbstractHandler handler; + + public TestEndpoint(AbstractHandler handler) { + this.handler = handler; + } + + @Override + public void onOpen(Session session, EndpointConfig config) { + session.addMessageHandler(handler); + } + + } + + /** + * Abstract message handler implementation, used for tests. + */ + private static abstract class AbstractHandler implements MessageHandler { + /** + * Message queue to put the result messages. + */ + private final MessageQueue messageQueue = new MessageQueue(); + + /** + * Returns message queue to test received messages count. + * + * @return message queue object + */ + public MessageQueue getMessageQueue() { + return messageQueue; + } + } + + /** + * Partial message handler for receiving binary messages. + */ + public static class PartialByteBufferCaptureHandler extends AbstractHandler implements + MessageHandler.Partial { + + /** + * Parts of the current message. This list is appended with every non-last part and is + * cleared after last part of a message has been received. + */ + private final List currentMessage = new ArrayList<>(); + + @Override + public void onMessage(ByteBuffer messagePart, boolean last) { + final ByteBuffer bufferCopy = ByteBuffer.allocate(messagePart.capacity()); + bufferCopy.put(messagePart); + currentMessage.add(bufferCopy); + if (last) { + int totalSize = 0; + for (ByteBuffer bb : currentMessage) { + totalSize += bb.capacity(); + } + final ByteBuffer result = ByteBuffer.allocate(totalSize); + for (ByteBuffer bb : currentMessage) { + result.put(bb); + } + final String stringResult = new String(result.array()); + getMessageQueue().add(stringResult); + currentMessage.clear(); + } + + } + + } + /** + * Whole message handler for receiving binary messages. + */ + public class WholeByteBufferCaptureHandler extends AbstractHandler implements + MessageHandler.Whole { + + @Override + public void onMessage(ByteBuffer message) { + final String stringResult = new String(message.array()); + getMessageQueue().add(stringResult); + + } + } + + /** + * Partial message handler for receiving text messages. + */ + public static class PartialStringCaptureHandler extends AbstractHandler implements + MessageHandler.Partial { + + /** + * Parts of the current message. This list is appended with every non-last part and is + * cleared after last part of a message has been received. + */ + private StringBuilder sb = new StringBuilder(); + + @Override + public void onMessage(String messagePart, boolean last) { + sb.append(messagePart); + if (last) { + getMessageQueue().add(sb.toString()); + sb = new StringBuilder(); + } + } + + } + /** + * Whole message handler for receiving text messages. + */ + public class WholeStringCaptureHandler extends AbstractHandler implements + MessageHandler.Whole { + + @Override + public void onMessage(String message) { + getMessageQueue().add(message); + + } + } + +} From 76476b6d285b006caa419412e2558020be4c6ac8 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Tue, 22 Mar 2016 12:51:04 -0700 Subject: [PATCH 3/4] Issue #437 - Avoid NPE on receiving empty message though MessageHandler.Partial Minor updates to use features elsewhere in Jetty. --- .../jsr356/messages/BinaryPartialMessage.java | 2 +- .../websocket/jsr356/MessageReceivingTest.java | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/BinaryPartialMessage.java b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/BinaryPartialMessage.java index 7acb6807514..2dd077e5574 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/BinaryPartialMessage.java +++ b/jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/messages/BinaryPartialMessage.java @@ -51,7 +51,7 @@ public class BinaryPartialMessage implements MessageAppender // Supported Partial<> Type #1: ByteBuffer if (msgWrapper.isMessageType(ByteBuffer.class)) { - partialHandler.onMessage(payload==null?ByteBuffer.allocate(0): + partialHandler.onMessage(payload==null?BufferUtil.EMPTY_BUFFER: payload.slice(),isLast); return; } diff --git a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageReceivingTest.java b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageReceivingTest.java index 92676d2c06a..485ef0a4bf5 100644 --- a/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageReceivingTest.java +++ b/jetty-websocket/javax-websocket-client-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/MessageReceivingTest.java @@ -18,12 +18,12 @@ package org.eclipse.jetty.websocket.jsr356; -import static org.hamcrest.Matchers.instanceOf; - import java.io.IOException; import java.net.URI; import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.concurrent.TimeUnit; @@ -45,6 +45,8 @@ import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import static org.hamcrest.Matchers.instanceOf; + /** * This class tests receiving of messages by different types of {@link MessageHandler} */ @@ -57,11 +59,9 @@ public class MessageReceivingTest { private final String VERY_LONG_STRING; public MessageReceivingTest() { - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 1024 * 1024; i++) { - sb.append(i & 1); - } - VERY_LONG_STRING = sb.toString(); + byte raw[] = new byte[1024 * 1024]; + Arrays.fill(raw, (byte)'x'); + VERY_LONG_STRING = new String(raw, StandardCharsets.UTF_8); } @BeforeClass From 210f9a8d7c7d96eafaaa8e03373921b6782f3ba7 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Wed, 13 Apr 2016 11:50:57 -0700 Subject: [PATCH 4/4] Fixes #510 - Module [depend] property expansion should support eg foo/${bar}/${bar}-xxx --- .../java/org/eclipse/jetty/start/Props.java | 8 ++++---- .../org/eclipse/jetty/start/PropsTest.java | 20 ++++++++++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/jetty-start/src/main/java/org/eclipse/jetty/start/Props.java b/jetty-start/src/main/java/org/eclipse/jetty/start/Props.java index c3dc4f43e21..72343ba3197 100644 --- a/jetty-start/src/main/java/org/eclipse/jetty/start/Props.java +++ b/jetty-start/src/main/java/org/eclipse/jetty/start/Props.java @@ -18,8 +18,6 @@ package org.eclipse.jetty.start; -import static org.eclipse.jetty.start.UsageException.*; - import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; @@ -34,6 +32,8 @@ import java.util.regex.Pattern; import org.eclipse.jetty.start.Props.Prop; +import static org.eclipse.jetty.start.UsageException.ERR_BAD_ARG; + /** * Management of Properties. *

@@ -225,8 +225,6 @@ public final class Props implements Iterable throw new PropsException(err.toString()); } - seenStack.push(property); - // find property name expanded.append(str.subSequence(offset,mat.start(1))); // get property value @@ -239,7 +237,9 @@ public final class Props implements Iterable else { // recursively expand + seenStack.push(property); value = expand(value,seenStack); + seenStack.pop(); expanded.append(value); } // update offset diff --git a/jetty-start/src/test/java/org/eclipse/jetty/start/PropsTest.java b/jetty-start/src/test/java/org/eclipse/jetty/start/PropsTest.java index 62a229349de..d68a0d17c46 100644 --- a/jetty-start/src/test/java/org/eclipse/jetty/start/PropsTest.java +++ b/jetty-start/src/test/java/org/eclipse/jetty/start/PropsTest.java @@ -18,12 +18,15 @@ package org.eclipse.jetty.start; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.*; - import org.eclipse.jetty.start.Props.Prop; import org.junit.Test; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.notNullValue; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + public class PropsTest { private static final String FROM_TEST = "(test)"; @@ -118,6 +121,17 @@ public class PropsTest assertThat(props.expand("server-id=corporate-${id}"),is("server-id=corporate-jetty-9.1")); } + @Test + public void testExpandDouble() + { + Props props = new Props(); + props.setProperty("bar","apple",FROM_TEST); + props.setProperty("foo","foo/${bar}/${bar}-xx",FROM_TEST); + + // Should expand + assertThat(props.expand("foo/${bar}/${bar}-xx"),is("foo/apple/apple-xx")); + } + @Test public void testExpandLoop() {