diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java
index 445383a38c0..1832ee74e41 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpRequest.java
@@ -510,21 +510,12 @@ public class HttpRequest implements Request
@Override
public Request onResponseContent(final Response.ContentListener listener)
{
- this.responseListeners.add(new Response.DemandedContentListener()
+ this.responseListeners.add(new Response.ContentListener()
{
@Override
- public void onContent(Response response, LongConsumer demand, ByteBuffer content, Callback callback)
+ public void onContent(Response response, ByteBuffer content)
{
- try
- {
- listener.onContent(response, content);
- callback.succeeded();
- demand.accept(1);
- }
- catch (Throwable x)
- {
- callback.failed(x);
- }
+ listener.onContent(response, content);
}
});
return this;
@@ -533,16 +524,12 @@ public class HttpRequest implements Request
@Override
public Request onResponseContentAsync(final Response.AsyncContentListener listener)
{
- this.responseListeners.add(new Response.DemandedContentListener()
+ this.responseListeners.add(new Response.AsyncContentListener()
{
@Override
- public void onContent(Response response, LongConsumer demand, ByteBuffer content, Callback callback)
+ public void onContent(Response response, ByteBuffer content, Callback callback)
{
- listener.onContent(response, content, Callback.from(() ->
- {
- callback.succeeded();
- demand.accept(1);
- }, callback::failed));
+ listener.onContent(response, content, callback);
}
});
return this;
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java
index 31adfc921bb..2f4b87eeb7b 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/api/Response.java
@@ -85,14 +85,14 @@ public interface Response
/**
* Common, empty, super-interface for response listeners
*/
- public interface ResponseListener extends EventListener
+ interface ResponseListener extends EventListener
{
}
/**
* Listener for the response begin event.
*/
- public interface BeginListener extends ResponseListener
+ interface BeginListener extends ResponseListener
{
/**
* Callback method invoked when the response line containing HTTP version,
@@ -102,13 +102,13 @@ public interface Response
*
* @param response the response containing the response line data
*/
- public void onBegin(Response response);
+ void onBegin(Response response);
}
/**
* Listener for a response header event.
*/
- public interface HeaderListener extends ResponseListener
+ interface HeaderListener extends ResponseListener
{
/**
* Callback method invoked when a response header has been received and parsed,
@@ -118,20 +118,20 @@ public interface Response
* @param field the header received
* @return true to process the header, false to skip processing of the header
*/
- public boolean onHeader(Response response, HttpField field);
+ boolean onHeader(Response response, HttpField field);
}
/**
* Listener for the response headers event.
*/
- public interface HeadersListener extends ResponseListener
+ interface HeadersListener extends ResponseListener
{
/**
* Callback method invoked when all the response headers have been received and parsed.
*
* @param response the response containing the response line data and the headers
*/
- public void onHeaders(Response response);
+ void onHeaders(Response response);
}
/**
@@ -139,7 +139,7 @@ public interface Response
*
* @see AsyncContentListener
*/
- public interface ContentListener extends ResponseListener
+ interface ContentListener extends AsyncContentListener
{
/**
* Callback method invoked when the response content has been received, parsed and there is demand.
@@ -149,7 +149,21 @@ public interface Response
* @param response the response containing the response line data and the headers
* @param content the content bytes received
*/
- public void onContent(Response response, ByteBuffer content);
+ void onContent(Response response, ByteBuffer content);
+
+ @Override
+ default void onContent(Response response, ByteBuffer content, Callback callback)
+ {
+ try
+ {
+ onContent(response, content);
+ callback.succeeded();
+ }
+ catch (Throwable x)
+ {
+ callback.failed(x);
+ }
+ }
}
/**
@@ -157,7 +171,7 @@ public interface Response
*
* @see DemandedContentListener
*/
- public interface AsyncContentListener extends ResponseListener
+ interface AsyncContentListener extends DemandedContentListener
{
/**
* Callback method invoked when the response content has been received, parsed and there is demand.
@@ -168,13 +182,23 @@ public interface Response
* @param content the content bytes received
* @param callback the callback to call when the content is consumed and to demand more content
*/
- public void onContent(Response response, ByteBuffer content, Callback callback);
+ void onContent(Response response, ByteBuffer content, Callback callback);
+
+ @Override
+ default void onContent(Response response, LongConsumer demand, ByteBuffer content, Callback callback)
+ {
+ onContent(response, content, Callback.from(() ->
+ {
+ callback.succeeded();
+ demand.accept(1);
+ }, callback::failed));
+ }
}
/**
* Asynchronous listener for the response content events.
*/
- public interface DemandedContentListener extends ResponseListener
+ interface DemandedContentListener extends ResponseListener
{
/**
* Callback method invoked before response content events.
@@ -186,7 +210,7 @@ public interface Response
* @param response the response containing the response line data and the headers
* @param demand the object that allows to demand content buffers
*/
- public default void onBeforeContent(Response response, LongConsumer demand)
+ default void onBeforeContent(Response response, LongConsumer demand)
{
demand.accept(1);
}
@@ -203,26 +227,26 @@ public interface Response
* @param content the content bytes received
* @param callback the callback to call when the content is consumed
*/
- public void onContent(Response response, LongConsumer demand, ByteBuffer content, Callback callback);
+ void onContent(Response response, LongConsumer demand, ByteBuffer content, Callback callback);
}
/**
* Listener for the response succeeded event.
*/
- public interface SuccessListener extends ResponseListener
+ interface SuccessListener extends ResponseListener
{
/**
* Callback method invoked when the whole response has been successfully received.
*
* @param response the response containing the response line data and the headers
*/
- public void onSuccess(Response response);
+ void onSuccess(Response response);
}
/**
* Listener for the response failure event.
*/
- public interface FailureListener extends ResponseListener
+ interface FailureListener extends ResponseListener
{
/**
* Callback method invoked when the response has failed in the process of being received
@@ -230,13 +254,13 @@ public interface Response
* @param response the response containing data up to the point the failure happened
* @param failure the failure happened
*/
- public void onFailure(Response response, Throwable failure);
+ void onFailure(Response response, Throwable failure);
}
/**
* Listener for the request and response completed event.
*/
- public interface CompleteListener extends ResponseListener
+ interface CompleteListener extends ResponseListener
{
/**
* Callback method invoked when the request and the response have been processed,
@@ -252,13 +276,13 @@ public interface Response
*
* @param result the result of the request / response exchange
*/
- public void onComplete(Result result);
+ void onComplete(Result result);
}
/**
* Listener for all response events.
*/
- public interface Listener extends BeginListener, HeaderListener, HeadersListener, ContentListener, AsyncContentListener, DemandedContentListener, SuccessListener, FailureListener, CompleteListener
+ interface Listener extends BeginListener, HeaderListener, HeadersListener, ContentListener, SuccessListener, FailureListener, CompleteListener
{
@Override
public default void onBegin(Response response)
@@ -276,41 +300,11 @@ public interface Response
{
}
- @Override
- public default void onBeforeContent(Response response, LongConsumer demand)
- {
- demand.accept(1);
- }
-
@Override
public default void onContent(Response response, ByteBuffer content)
{
}
- @Override
- public default void onContent(Response response, ByteBuffer content, Callback callback)
- {
- try
- {
- onContent(response, content);
- callback.succeeded();
- }
- catch (Throwable x)
- {
- callback.failed(x);
- }
- }
-
- @Override
- public default void onContent(Response response, LongConsumer demand, ByteBuffer content, Callback callback)
- {
- onContent(response, content, Callback.from(() ->
- {
- callback.succeeded();
- demand.accept(1);
- }, callback::failed));
- }
-
@Override
public default void onSuccess(Response response)
{
@@ -329,7 +323,7 @@ public interface Response
/**
* An empty implementation of {@link Listener}
*/
- public static class Adapter implements Listener
+ class Adapter implements Listener
{
}
}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
index 0330431a0de..f865b884272 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
@@ -18,6 +18,7 @@
package org.eclipse.jetty.client;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -84,6 +85,7 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.Net;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
+import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.IO;
@@ -1784,6 +1786,57 @@ public class HttpClientTest extends AbstractHttpClientServerTest
}
}
+ @ParameterizedTest
+ @ArgumentsSource(ScenarioProvider.class)
+ public void testContentListenerAsCompleteListener(Scenario scenario) throws Exception
+ {
+ byte[] bytes = new byte[1024];
+ new Random().nextBytes(bytes);
+ start(scenario, new AbstractHandler()
+ {
+ @Override
+ public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+ ServletOutputStream output = response.getOutputStream();
+ output.write(bytes);
+ }
+ });
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ CountDownLatch latch = new CountDownLatch(1);
+ class L implements Response.ContentListener, Response.CompleteListener
+ {
+ @Override
+ public void onContent(Response response, ByteBuffer content)
+ {
+ try
+ {
+ BufferUtil.writeTo(content, baos);
+ }
+ catch (IOException x)
+ {
+ baos.reset();
+ x.printStackTrace();
+ }
+ }
+
+ @Override
+ public void onComplete(Result result)
+ {
+ if (result.isSucceeded())
+ latch.countDown();
+ }
+ }
+
+ client.newRequest("localhost", connector.getLocalPort())
+ .scheme(scenario.getScheme())
+ .send(new L());
+
+ assertTrue(latch.await(5, TimeUnit.SECONDS));
+ assertArrayEquals(bytes, baos.toByteArray());
+ }
+
private void assertCopyRequest(Request original)
{
Request copy = client.copyRequest((HttpRequest)original, original.getURI());
diff --git a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/AnnotatedClientEndpointConfig.java b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/AnnotatedClientEndpointConfig.java
index de554162f9c..1923f29afea 100644
--- a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/AnnotatedClientEndpointConfig.java
+++ b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/AnnotatedClientEndpointConfig.java
@@ -18,101 +18,41 @@
package org.eclipse.jetty.websocket.javax.client;
-import java.util.Arrays;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import javax.websocket.ClientEndpoint;
import javax.websocket.ClientEndpointConfig;
-import javax.websocket.Decoder;
-import javax.websocket.Encoder;
-import javax.websocket.Extension;
+import org.eclipse.jetty.websocket.javax.common.ClientEndpointConfigWrapper;
import org.eclipse.jetty.websocket.javax.common.InvalidWebSocketException;
-public class AnnotatedClientEndpointConfig implements ClientEndpointConfig
+public class AnnotatedClientEndpointConfig extends ClientEndpointConfigWrapper
{
- private final ClientEndpoint annotation;
- private final List> decoders;
- private final List> encoders;
- private final List extensions;
- private final List preferredSubprotocols;
- private final Configurator configurator;
- private Map userProperties;
-
public AnnotatedClientEndpointConfig(ClientEndpoint anno)
{
- this.annotation = anno;
- this.decoders = Collections.unmodifiableList(Arrays.asList(anno.decoders()));
- this.encoders = Collections.unmodifiableList(Arrays.asList(anno.encoders()));
- this.preferredSubprotocols = Collections.unmodifiableList(Arrays.asList(anno.subprotocols()));
-
- // no extensions declared in annotation
- this.extensions = Collections.emptyList();
- // no userProperties in annotation
- this.userProperties = new HashMap<>();
-
- if (anno.configurator() == null)
+ Configurator configurator;
+ try
{
- this.configurator = EmptyConfigurator.INSTANCE;
+ configurator = anno.configurator().getDeclaredConstructor().newInstance();
}
- else
+ catch (Exception e)
{
- try
- {
- this.configurator = anno.configurator().getDeclaredConstructor().newInstance();
- }
- catch (Exception e)
- {
- StringBuilder err = new StringBuilder();
- err.append("Unable to instantiate ClientEndpoint.configurator() of ");
- err.append(anno.configurator().getName());
- err.append(" defined as annotation in ");
- err.append(anno.getClass().getName());
- throw new InvalidWebSocketException(err.toString(), e);
- }
+ StringBuilder err = new StringBuilder();
+ err.append("Unable to instantiate ClientEndpoint.configurator() of ");
+ err.append(anno.configurator().getName());
+ err.append(" defined as annotation in ");
+ err.append(anno.getClass().getName());
+ throw new InvalidWebSocketException(err.toString(), e);
}
- }
- public ClientEndpoint getAnnotation()
- {
- return annotation;
- }
+ ClientEndpointConfig build = Builder.create()
+ .encoders(List.of(anno.encoders()))
+ .decoders(List.of(anno.decoders()))
+ .preferredSubprotocols(List.of(anno.subprotocols()))
+ .extensions(Collections.emptyList())
+ .configurator(configurator)
+ .build();
- @Override
- public Configurator getConfigurator()
- {
- return configurator;
- }
-
- @Override
- public List> getDecoders()
- {
- return decoders;
- }
-
- @Override
- public List> getEncoders()
- {
- return encoders;
- }
-
- @Override
- public List getExtensions()
- {
- return extensions;
- }
-
- @Override
- public List getPreferredSubprotocols()
- {
- return preferredSubprotocols;
- }
-
- @Override
- public Map getUserProperties()
- {
- return userProperties;
+ init(build);
}
}
diff --git a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/BasicClientEndpointConfig.java b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/BasicClientEndpointConfig.java
new file mode 100644
index 00000000000..b43021dded6
--- /dev/null
+++ b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/BasicClientEndpointConfig.java
@@ -0,0 +1,29 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2019 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.javax.client;
+
+import org.eclipse.jetty.websocket.javax.common.ClientEndpointConfigWrapper;
+
+public class BasicClientEndpointConfig extends ClientEndpointConfigWrapper
+{
+ public BasicClientEndpointConfig()
+ {
+ init(Builder.create().configurator(EmptyConfigurator.INSTANCE).build());
+ }
+}
diff --git a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/EmptyClientEndpointConfig.java b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/EmptyClientEndpointConfig.java
deleted file mode 100644
index 16718872d74..00000000000
--- a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/EmptyClientEndpointConfig.java
+++ /dev/null
@@ -1,84 +0,0 @@
-//
-// ========================================================================
-// Copyright (c) 1995-2019 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.javax.client;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.websocket.ClientEndpointConfig;
-import javax.websocket.Decoder;
-import javax.websocket.Encoder;
-import javax.websocket.Extension;
-
-public class EmptyClientEndpointConfig implements ClientEndpointConfig
-{
- private final List> decoders;
- private final List> encoders;
- private final List extensions;
- private final List preferredSubprotocols;
- private final Configurator configurator;
- private Map userProperties;
-
- public EmptyClientEndpointConfig()
- {
- this.decoders = new ArrayList<>();
- this.encoders = new ArrayList<>();
- this.preferredSubprotocols = new ArrayList<>();
- this.extensions = new ArrayList<>();
- this.userProperties = new HashMap<>();
- this.configurator = EmptyConfigurator.INSTANCE;
- }
-
- @Override
- public Configurator getConfigurator()
- {
- return configurator;
- }
-
- @Override
- public List> getDecoders()
- {
- return decoders;
- }
-
- @Override
- public List> getEncoders()
- {
- return encoders;
- }
-
- @Override
- public List getExtensions()
- {
- return extensions;
- }
-
- @Override
- public List getPreferredSubprotocols()
- {
- return preferredSubprotocols;
- }
-
- @Override
- public Map getUserProperties()
- {
- return userProperties;
- }
-}
diff --git a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientContainer.java b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientContainer.java
index 51959da8f97..20bd18aa222 100644
--- a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientContainer.java
+++ b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientContainer.java
@@ -215,7 +215,7 @@ public class JavaxWebSocketClientContainer extends JavaxWebSocketContainer imple
{
ClientEndpointConfig config = providedConfig;
if (config == null)
- config = new EmptyClientEndpointConfig();
+ config = new BasicClientEndpointConfig();
ConfiguredEndpoint instance = new ConfiguredEndpoint(endpoint, config);
return connect(instance, path);
diff --git a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientFrameHandlerFactory.java b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientFrameHandlerFactory.java
index d59ada627df..7589a40cd23 100644
--- a/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientFrameHandlerFactory.java
+++ b/jetty-websocket/javax-websocket-client/src/main/java/org/eclipse/jetty/websocket/javax/client/JavaxWebSocketClientFrameHandlerFactory.java
@@ -39,6 +39,12 @@ public class JavaxWebSocketClientFrameHandlerFactory extends JavaxWebSocketFrame
super(container, InvokerUtils.PARAM_IDENTITY);
}
+ @Override
+ public EndpointConfig newDefaultEndpointConfig(Class> endpointClass, String path)
+ {
+ return new BasicClientEndpointConfig();
+ }
+
@Override
public JavaxWebSocketFrameHandlerMetadata createMetadata(Class> endpointClass, EndpointConfig endpointConfig)
{
diff --git a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/ClientEndpointConfigWrapper.java b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/ClientEndpointConfigWrapper.java
new file mode 100644
index 00000000000..a49f0e8d7d1
--- /dev/null
+++ b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/ClientEndpointConfigWrapper.java
@@ -0,0 +1,61 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2019 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.javax.common;
+
+import java.util.List;
+import javax.websocket.ClientEndpointConfig;
+import javax.websocket.Extension;
+
+public class ClientEndpointConfigWrapper extends EndpointConfigWrapper implements ClientEndpointConfig
+{
+ private ClientEndpointConfig _endpointConfig;
+
+ public ClientEndpointConfigWrapper()
+ {
+ }
+
+ public ClientEndpointConfigWrapper(ClientEndpointConfig endpointConfig)
+ {
+ init(endpointConfig);
+ }
+
+ public void init(ClientEndpointConfig endpointConfig)
+ {
+ _endpointConfig = endpointConfig;
+ super.init(endpointConfig);
+ }
+
+ @Override
+ public List getPreferredSubprotocols()
+ {
+ return _endpointConfig.getPreferredSubprotocols();
+ }
+
+ @Override
+ public List getExtensions()
+ {
+ return _endpointConfig.getExtensions();
+ }
+
+ @Override
+ public Configurator getConfigurator()
+ {
+ return _endpointConfig.getConfigurator();
+ }
+}
diff --git a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/BasicEndpointConfig.java b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/EndpointConfigWrapper.java
similarity index 59%
rename from jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/BasicEndpointConfig.java
rename to jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/EndpointConfigWrapper.java
index 3f284352e54..d411b304b53 100644
--- a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/BasicEndpointConfig.java
+++ b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/EndpointConfigWrapper.java
@@ -19,44 +19,57 @@
package org.eclipse.jetty.websocket.javax.common;
import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.websocket.Decoder;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
-/**
- * Basic EndpointConfig (used when no EndpointConfig is provided or discovered)
- */
-public class BasicEndpointConfig implements EndpointConfig
+public abstract class EndpointConfigWrapper implements EndpointConfig, PathParamProvider
{
- private List> decoders;
- private List> encoders;
- private Map userProperties;
+ private EndpointConfig _endpointConfig;
+ private Map _pathParameters;
- public BasicEndpointConfig()
+ public EndpointConfigWrapper()
{
- decoders = Collections.emptyList();
- encoders = Collections.emptyList();
- userProperties = new HashMap<>();
}
- @Override
- public List> getDecoders()
+ public EndpointConfigWrapper(EndpointConfig endpointConfig)
{
- return decoders;
+ init(endpointConfig);
+ }
+
+ public void init(EndpointConfig endpointConfig)
+ {
+ _endpointConfig = endpointConfig;
+
+ if (endpointConfig instanceof PathParamProvider)
+ _pathParameters = ((PathParamProvider)endpointConfig).getPathParams();
+ else
+ _pathParameters = Collections.emptyMap();
}
@Override
public List> getEncoders()
{
- return encoders;
+ return _endpointConfig.getEncoders();
+ }
+
+ @Override
+ public List> getDecoders()
+ {
+ return _endpointConfig.getDecoders();
}
@Override
public Map getUserProperties()
{
- return userProperties;
+ return _endpointConfig.getUserProperties();
+ }
+
+ @Override
+ public Map getPathParams()
+ {
+ return _pathParameters;
}
}
diff --git a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketFrameHandler.java b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketFrameHandler.java
index 8356e064163..378ef535da6 100644
--- a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketFrameHandler.java
+++ b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketFrameHandler.java
@@ -28,11 +28,13 @@ import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
+import javax.websocket.ClientEndpointConfig;
import javax.websocket.CloseReason;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.PongMessage;
+import javax.websocket.server.ServerEndpointConfig;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
@@ -97,7 +99,7 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
private UpgradeRequest upgradeRequest;
private UpgradeResponse upgradeResponse;
- private final EndpointConfig endpointConfig;
+ private EndpointConfig endpointConfig;
private MessageSink textSink;
private MessageSink binarySink;
private MessageSink activeMessageSink;
@@ -155,9 +157,12 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
@Override
public void onOpen(CoreSession coreSession, Callback callback)
{
+ this.coreSession = coreSession;
+
try
{
- this.coreSession = coreSession;
+ // Rewire EndpointConfig to call CoreSession setters if Jetty specific properties are set.
+ endpointConfig = getWrappedEndpointConfig();
session = new JavaxWebSocketSession(container, coreSession, this, endpointConfig);
openHandle = InvokerUtils.bindTo(openHandle, session, endpointConfig);
@@ -206,6 +211,48 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
}
}
+ private EndpointConfig getWrappedEndpointConfig()
+ {
+ final Map listenerMap = new PutListenerMap(this.endpointConfig.getUserProperties(), this::configListener);
+
+ EndpointConfig wrappedConfig;
+ if (endpointConfig instanceof ServerEndpointConfig)
+ {
+ wrappedConfig = new ServerEndpointConfigWrapper((ServerEndpointConfig)endpointConfig)
+ {
+ @Override
+ public Map getUserProperties()
+ {
+ return listenerMap;
+ }
+ };
+ }
+ else if (endpointConfig instanceof ClientEndpointConfig)
+ {
+ wrappedConfig = new ClientEndpointConfigWrapper((ClientEndpointConfig)endpointConfig)
+ {
+ @Override
+ public Map getUserProperties()
+ {
+ return listenerMap;
+ }
+ };
+ }
+ else
+ {
+ wrappedConfig = new EndpointConfigWrapper(endpointConfig)
+ {
+ @Override
+ public Map getUserProperties()
+ {
+ return listenerMap;
+ }
+ };
+ }
+
+ return wrappedConfig;
+ }
+
@Override
public void onFrame(Frame frame, Callback callback)
{
@@ -623,4 +670,29 @@ public class JavaxWebSocketFrameHandler implements FrameHandler
{
return upgradeResponse;
}
+
+ private void configListener(String key, Object value)
+ {
+ if (!key.startsWith("org.eclipse.jetty.websocket."))
+ return;
+
+ switch (key)
+ {
+ case "org.eclipse.jetty.websocket.autoFragment":
+ coreSession.setAutoFragment((Boolean)value);
+ break;
+
+ case "org.eclipse.jetty.websocket.maxFrameSize":
+ coreSession.setMaxFrameSize((Long)value);
+ break;
+
+ case "org.eclipse.jetty.websocket.outputBufferSize":
+ coreSession.setOutputBufferSize((Integer)value);
+ break;
+
+ case "org.eclipse.jetty.websocket.inputBufferSize":
+ coreSession.setInputBufferSize((Integer)value);
+ break;
+ }
+ }
}
diff --git a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketFrameHandlerFactory.java b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketFrameHandlerFactory.java
index 53b7c5f0846..2f000e03e48 100644
--- a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketFrameHandlerFactory.java
+++ b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketFrameHandlerFactory.java
@@ -104,6 +104,8 @@ public abstract class JavaxWebSocketFrameHandlerFactory
return metadata;
}
+ public abstract EndpointConfig newDefaultEndpointConfig(Class> endpointClass, String path);
+
public abstract JavaxWebSocketFrameHandlerMetadata createMetadata(Class> endpointClass, EndpointConfig endpointConfig);
public JavaxWebSocketFrameHandler newJavaxWebSocketFrameHandler(Object endpointInstance, UpgradeRequest upgradeRequest)
@@ -120,7 +122,8 @@ public abstract class JavaxWebSocketFrameHandlerFactory
else
{
endpoint = endpointInstance;
- config = new BasicEndpointConfig();
+ String path = (upgradeRequest.getRequestURI() == null) ? null : upgradeRequest.getRequestURI().getPath();
+ config = newDefaultEndpointConfig(endpoint.getClass(), path);
}
JavaxWebSocketFrameHandlerMetadata metadata = getMetadata(endpoint.getClass(), config);
diff --git a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketSession.java b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketSession.java
index 6ab4809d912..14956e01612 100644
--- a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketSession.java
+++ b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/JavaxWebSocketSession.java
@@ -76,8 +76,7 @@ public class JavaxWebSocketSession implements javax.websocket.Session
this.container = container;
this.coreSession = coreSession;
this.frameHandler = frameHandler;
-
- this.config = endpointConfig == null ? new BasicEndpointConfig() : endpointConfig;
+ this.config = Objects.requireNonNull(endpointConfig);
this.availableDecoders = new AvailableDecoders(this.config);
this.availableEncoders = new AvailableEncoders(this.config);
@@ -92,7 +91,12 @@ public class JavaxWebSocketSession implements javax.websocket.Session
this.pathParameters = Collections.emptyMap();
}
- this.userProperties = new HashMap<>(this.config.getUserProperties());
+ this.userProperties = this.config.getUserProperties();
+ }
+
+ public FrameHandler.CoreSession getCoreSession()
+ {
+ return coreSession;
}
/**
diff --git a/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/PutListenerMap.java b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/PutListenerMap.java
new file mode 100644
index 00000000000..f10e0d40efd
--- /dev/null
+++ b/jetty-websocket/javax-websocket-common/src/main/java/org/eclipse/jetty/websocket/javax/common/PutListenerMap.java
@@ -0,0 +1,118 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2019 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.javax.common;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiConsumer;
+
+public class PutListenerMap implements Map
+{
+ private Map map;
+ private BiConsumer listener;
+
+ public PutListenerMap(Map map, BiConsumer listener)
+ {
+ this.map = map;
+ this.listener = listener;
+
+ // Notify listener for any existing entries in the Map.
+ for (Map.Entry entry : map.entrySet())
+ {
+ listener.accept(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ public int size()
+ {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key)
+ {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value)
+ {
+ return map.containsValue(value);
+ }
+
+ @Override
+ public Object get(Object key)
+ {
+ return map.get(key);
+ }
+
+ @Override
+ public Object put(String key, Object value)
+ {
+ listener.accept(key, value);
+ return map.put(key, value);
+ }
+
+ @Override
+ public Object remove(Object key)
+ {
+ return map.remove(key);
+ }
+
+ @Override
+ public void putAll(Map extends String, ?> m)
+ {
+ for (Map.Entry entry : map.entrySet())
+ {
+ put(entry.getKey(), entry.getValue());
+ }
+ }
+
+ @Override
+ public void clear()
+ {
+ map.clear();
+ }
+
+ @Override
+ public Set keySet()
+ {
+ return map.keySet();
+ }
+
+ @Override
+ public Collection