Issue #207 - Support javax.websocket version 1.1
+ Removing more EventDriver references + Fixing bad implementation exposed by testcases # Conflicts: # jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/AbstractJsrEventDriver.java # jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrAnnotatedEventDriver.java # jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointEventDriver.java # jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEndpointImpl.java # jetty-websocket/javax-websocket-client-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/endpoints/JsrEventDriverFactory.java
This commit is contained in:
parent
c03037e757
commit
2fac7f07aa
|
@ -238,6 +238,7 @@ public class ConfigurationAssert
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
public static void assertOrdered(String msg, List<String> expectedList, List<String> actualList)
|
public static void assertOrdered(String msg, List<String> expectedList, List<String> actualList)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -23,6 +23,7 @@ import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
@ -56,11 +57,14 @@ import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
|
||||||
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
import org.eclipse.jetty.websocket.client.WebSocketClient;
|
||||||
import org.eclipse.jetty.websocket.client.io.UpgradeListener;
|
import org.eclipse.jetty.websocket.client.io.UpgradeListener;
|
||||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||||
import org.eclipse.jetty.websocket.common.scopes.DelegatedContainerScope;
|
import org.eclipse.jetty.websocket.common.function.EndpointFunctions;
|
||||||
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
|
import org.eclipse.jetty.websocket.common.scopes.SimpleContainerScope;
|
||||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
||||||
import org.eclipse.jetty.websocket.jsr356.client.AnnotatedClientEndpointConfig;
|
import org.eclipse.jetty.websocket.jsr356.client.AnnotatedClientEndpointConfig;
|
||||||
import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig;
|
import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.decoders.AvailableDecoders;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.encoders.AvailableEncoders;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.function.JsrEndpointFunctions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Container for Client use of the javax.websocket API.
|
* Container for Client use of the javax.websocket API.
|
||||||
|
@ -100,6 +104,21 @@ public class ClientContainer extends ContainerLifeCycle implements WebSocketCont
|
||||||
ShutdownThread.register(this);
|
ShutdownThread.register(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public EndpointFunctions newJsrEndpointFunction(Object endpoint,
|
||||||
|
AvailableEncoders availableEncoders,
|
||||||
|
AvailableDecoders availableDecoders,
|
||||||
|
Map<String, String> pathParameters,
|
||||||
|
EndpointConfig config)
|
||||||
|
{
|
||||||
|
return new JsrEndpointFunctions(endpoint,
|
||||||
|
getPolicy(),
|
||||||
|
getExecutor(),
|
||||||
|
availableEncoders,
|
||||||
|
availableDecoders,
|
||||||
|
pathParameters,
|
||||||
|
config);
|
||||||
|
}
|
||||||
|
|
||||||
private Session connect(ConfiguredEndpoint instance, URI path) throws IOException
|
private Session connect(ConfiguredEndpoint instance, URI path) throws IOException
|
||||||
{
|
{
|
||||||
Objects.requireNonNull(instance, "EndpointInstance cannot be null");
|
Objects.requireNonNull(instance, "EndpointInstance cannot be null");
|
||||||
|
|
|
@ -95,9 +95,9 @@ public class JsrSession extends WebSocketSession implements javax.websocket.Sess
|
||||||
@Override
|
@Override
|
||||||
public EndpointFunctions newEndpointFunctions(Object endpoint)
|
public EndpointFunctions newEndpointFunctions(Object endpoint)
|
||||||
{
|
{
|
||||||
return new JsrEndpointFunctions(endpoint,
|
// Delegate to container to obtain correct version of JsrEndpointFunctions
|
||||||
getPolicy(),
|
// Could be a Client version, or a Server version
|
||||||
getExecutor(),
|
return container.newJsrEndpointFunction(endpoint,
|
||||||
availableEncoders,
|
availableEncoders,
|
||||||
availableDecoders,
|
availableDecoders,
|
||||||
pathParameters,
|
pathParameters,
|
||||||
|
|
|
@ -85,6 +85,7 @@ public class AvailableDecoders implements Predicate<Class<?>>
|
||||||
registerPrimitive(CharacterDecoder.class, Decoder.Text.class, Character.class);
|
registerPrimitive(CharacterDecoder.class, Decoder.Text.class, Character.class);
|
||||||
registerPrimitive(DoubleDecoder.class, Decoder.Text.class, Double.class);
|
registerPrimitive(DoubleDecoder.class, Decoder.Text.class, Double.class);
|
||||||
registerPrimitive(FloatDecoder.class, Decoder.Text.class, Float.class);
|
registerPrimitive(FloatDecoder.class, Decoder.Text.class, Float.class);
|
||||||
|
registerPrimitive(ShortDecoder.class, Decoder.Text.class, Short.class);
|
||||||
registerPrimitive(IntegerDecoder.class, Decoder.Text.class, Integer.class);
|
registerPrimitive(IntegerDecoder.class, Decoder.Text.class, Integer.class);
|
||||||
registerPrimitive(LongDecoder.class, Decoder.Text.class, Long.class);
|
registerPrimitive(LongDecoder.class, Decoder.Text.class, Long.class);
|
||||||
registerPrimitive(StringDecoder.class, Decoder.Text.class, String.class);
|
registerPrimitive(StringDecoder.class, Decoder.Text.class, String.class);
|
||||||
|
@ -95,6 +96,7 @@ public class AvailableDecoders implements Predicate<Class<?>>
|
||||||
registerPrimitive(CharacterDecoder.class, Decoder.Text.class, Character.TYPE);
|
registerPrimitive(CharacterDecoder.class, Decoder.Text.class, Character.TYPE);
|
||||||
registerPrimitive(DoubleDecoder.class, Decoder.Text.class, Double.TYPE);
|
registerPrimitive(DoubleDecoder.class, Decoder.Text.class, Double.TYPE);
|
||||||
registerPrimitive(FloatDecoder.class, Decoder.Text.class, Float.TYPE);
|
registerPrimitive(FloatDecoder.class, Decoder.Text.class, Float.TYPE);
|
||||||
|
registerPrimitive(ShortDecoder.class, Decoder.Text.class, Short.TYPE);
|
||||||
registerPrimitive(IntegerDecoder.class, Decoder.Text.class, Integer.TYPE);
|
registerPrimitive(IntegerDecoder.class, Decoder.Text.class, Integer.TYPE);
|
||||||
registerPrimitive(LongDecoder.class, Decoder.Text.class, Long.TYPE);
|
registerPrimitive(LongDecoder.class, Decoder.Text.class, Long.TYPE);
|
||||||
|
|
||||||
|
|
|
@ -83,6 +83,7 @@ public class AvailableEncoders implements Predicate<Class<?>>
|
||||||
registerPrimitive(CharacterEncoder.class, Encoder.Text.class, Character.class);
|
registerPrimitive(CharacterEncoder.class, Encoder.Text.class, Character.class);
|
||||||
registerPrimitive(DoubleEncoder.class, Encoder.Text.class, Double.class);
|
registerPrimitive(DoubleEncoder.class, Encoder.Text.class, Double.class);
|
||||||
registerPrimitive(FloatEncoder.class, Encoder.Text.class, Float.class);
|
registerPrimitive(FloatEncoder.class, Encoder.Text.class, Float.class);
|
||||||
|
registerPrimitive(ShortEncoder.class, Encoder.Text.class, Short.class);
|
||||||
registerPrimitive(IntegerEncoder.class, Encoder.Text.class, Integer.class);
|
registerPrimitive(IntegerEncoder.class, Encoder.Text.class, Integer.class);
|
||||||
registerPrimitive(LongEncoder.class, Encoder.Text.class, Long.class);
|
registerPrimitive(LongEncoder.class, Encoder.Text.class, Long.class);
|
||||||
registerPrimitive(StringEncoder.class, Encoder.Text.class, String.class);
|
registerPrimitive(StringEncoder.class, Encoder.Text.class, String.class);
|
||||||
|
@ -93,6 +94,7 @@ public class AvailableEncoders implements Predicate<Class<?>>
|
||||||
registerPrimitive(CharacterEncoder.class, Encoder.Text.class, Character.TYPE);
|
registerPrimitive(CharacterEncoder.class, Encoder.Text.class, Character.TYPE);
|
||||||
registerPrimitive(DoubleEncoder.class, Encoder.Text.class, Double.TYPE);
|
registerPrimitive(DoubleEncoder.class, Encoder.Text.class, Double.TYPE);
|
||||||
registerPrimitive(FloatEncoder.class, Encoder.Text.class, Float.TYPE);
|
registerPrimitive(FloatEncoder.class, Encoder.Text.class, Float.TYPE);
|
||||||
|
registerPrimitive(ShortEncoder.class, Encoder.Text.class, Short.TYPE);
|
||||||
registerPrimitive(IntegerEncoder.class, Encoder.Text.class, Integer.TYPE);
|
registerPrimitive(IntegerEncoder.class, Encoder.Text.class, Integer.TYPE);
|
||||||
registerPrimitive(LongEncoder.class, Encoder.Text.class, Long.TYPE);
|
registerPrimitive(LongEncoder.class, Encoder.Text.class, Long.TYPE);
|
||||||
|
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 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.endpoints;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public abstract class AbstractJsrEventDriver /*extends AbstractEventDriver*/
|
|
||||||
{
|
|
||||||
/* protected final EndpointMetadata metadata;
|
|
||||||
protected final Executor executor;
|
|
||||||
protected final EndpointConfig config;
|
|
||||||
protected JsrSession jsrsession;
|
|
||||||
private boolean hasCloseBeenCalled = false;
|
|
||||||
|
|
||||||
public AbstractJsrEventDriver(WebSocketPolicy policy, ConfiguredEndpoint endpointInstance, Executor executor)
|
|
||||||
{
|
|
||||||
super(policy,endpointInstance.getEndpoint());
|
|
||||||
this.config = endpointInstance.getConfig();
|
|
||||||
this.metadata = endpointInstance.getMetadata();
|
|
||||||
this.executor = executor;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EndpointConfig getConfig()
|
|
||||||
{
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Session getJsrSession()
|
|
||||||
{
|
|
||||||
return this.jsrsession;
|
|
||||||
}
|
|
||||||
|
|
||||||
public EndpointMetadata getMetadata()
|
|
||||||
{
|
|
||||||
return metadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void init(JsrSession jsrsession);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void onClose(CloseInfo close)
|
|
||||||
{
|
|
||||||
if (hasCloseBeenCalled)
|
|
||||||
{
|
|
||||||
// avoid duplicate close events (possible when using harsh Session.disconnect())
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
hasCloseBeenCalled = true;
|
|
||||||
|
|
||||||
CloseCode closecode = CloseCodes.getCloseCode(close.getStatusCode());
|
|
||||||
CloseReason closereason = new CloseReason(closecode,close.getReason());
|
|
||||||
onClose(closereason);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract void onClose(CloseReason closereason);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFrame(Frame frame)
|
|
||||||
{
|
|
||||||
*//* Ignored, not supported by JSR-356 *//*
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void openSession(WebSocketSession session)
|
|
||||||
{
|
|
||||||
// Cast should be safe, as it was created by JsrSessionFactory
|
|
||||||
this.jsrsession = (JsrSession)session;
|
|
||||||
|
|
||||||
// Allow jsr session to init
|
|
||||||
this.jsrsession.init(config);
|
|
||||||
|
|
||||||
// Allow event driver to init itself
|
|
||||||
init(jsrsession);
|
|
||||||
|
|
||||||
// Allow end-user socket to adjust configuration
|
|
||||||
super.openSession(session);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setEndpointconfig(EndpointConfig endpointconfig)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Why are you reconfiguring the endpoint?");
|
|
||||||
// this.config = endpointconfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void setPathParameters(Map<String, String> pathParameters);
|
|
||||||
|
|
||||||
public void dispatch(Runnable runnable)
|
|
||||||
{
|
|
||||||
executor.execute(runnable);
|
|
||||||
}*/
|
|
||||||
}
|
|
|
@ -1,389 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 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.endpoints;
|
|
||||||
|
|
||||||
import javax.websocket.MessageHandler.Whole;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base implementation for JSR-356 Annotated event drivers.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class JsrAnnotatedEventDriver /*extends AbstractJsrEventDriver*/
|
|
||||||
{
|
|
||||||
/* private static final Logger LOG = Log.getLogger(JsrAnnotatedEventDriver.class);
|
|
||||||
private final JsrEvents<?, ?> events;
|
|
||||||
|
|
||||||
public JsrAnnotatedEventDriver(WebSocketPolicy policy, ConfiguredEndpoint endpointInstance, JsrEvents<?, ?> events, Executor executor)
|
|
||||||
{
|
|
||||||
super(policy,endpointInstance,executor);
|
|
||||||
this.events = events;
|
|
||||||
|
|
||||||
EndpointMetadata metadata = endpointInstance.getMetadata();
|
|
||||||
|
|
||||||
if (metadata.maxTextMessageSize() >= 1)
|
|
||||||
policy.setMaxTextMessageSize((int) metadata.maxTextMessageSize());
|
|
||||||
if (metadata.maxBinaryMessageSize() >= 1)
|
|
||||||
policy.setMaxBinaryMessageSize((int) metadata.maxBinaryMessageSize());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(JsrSession jsrsession)
|
|
||||||
{
|
|
||||||
this.events.init(jsrsession);
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Entry point for all incoming binary frames.
|
|
||||||
*//*
|
|
||||||
@Override
|
|
||||||
public void onBinaryFrame(ByteBuffer buffer, boolean fin) throws IOException
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("onBinaryFrame({}, {})",BufferUtil.toDetailString(buffer),fin);
|
|
||||||
LOG.debug("events.onBinary={}",events.hasBinary());
|
|
||||||
LOG.debug("events.onBinaryStream={}",events.hasBinaryStream());
|
|
||||||
}
|
|
||||||
boolean handled = false;
|
|
||||||
|
|
||||||
if (events.hasBinary())
|
|
||||||
{
|
|
||||||
handled = true;
|
|
||||||
if (activeMessage == null)
|
|
||||||
{
|
|
||||||
if (events.isBinaryPartialSupported())
|
|
||||||
{
|
|
||||||
// Partial Message Support (does not use messageAppender)
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("Partial Binary Message: fin={}",fin);
|
|
||||||
}
|
|
||||||
activeMessage = new BinaryPartialOnMessage(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Whole Message Support
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("Whole Binary Message");
|
|
||||||
}
|
|
||||||
activeMessage = new ByteArrayMessageSink(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events.hasBinaryStream())
|
|
||||||
{
|
|
||||||
handled = true;
|
|
||||||
// Streaming Message Support
|
|
||||||
if (activeMessage == null)
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("Binary Message InputStream");
|
|
||||||
}
|
|
||||||
final MessageInputStream stream = new MessageInputStream();
|
|
||||||
activeMessage = stream;
|
|
||||||
|
|
||||||
// Always dispatch streaming read to another thread.
|
|
||||||
dispatch(new Runnable()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
events.callBinaryStream(jsrsession.getAsyncRemote(),websocket,stream);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
onFatalError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("handled = {}",handled);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process any active MessageAppender
|
|
||||||
if (handled && (activeMessage != null))
|
|
||||||
{
|
|
||||||
appendMessage(buffer,fin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Entry point for binary frames destined for {@link Whole}
|
|
||||||
*//*
|
|
||||||
@Override
|
|
||||||
public void onBinaryMessage(byte[] data)
|
|
||||||
{
|
|
||||||
if (data == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer buf = ByteBuffer.wrap(data);
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("onBinaryMessage({})",BufferUtil.toDetailString(buf));
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// FIN is always true here
|
|
||||||
events.callBinary(jsrsession.getAsyncRemote(),websocket,buf,true);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
onFatalError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onObject(Object obj)
|
|
||||||
{
|
|
||||||
// TODO Auto-generated method stub
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onClose(CloseReason closereason)
|
|
||||||
{
|
|
||||||
events.callClose(websocket,closereason);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnect()
|
|
||||||
{
|
|
||||||
events.callOpen(websocket,config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable cause)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
events.callError(websocket,cause);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
LOG.warn("Unable to call onError with cause", cause);
|
|
||||||
LOG.warn("Call to onError resulted in exception", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onFatalError(Throwable t)
|
|
||||||
{
|
|
||||||
onError(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFrame(Frame frame)
|
|
||||||
{
|
|
||||||
*//* Ignored in JSR-356 *//*
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInputStream(InputStream stream) throws IOException
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
events.callBinaryStream(jsrsession.getAsyncRemote(),websocket,stream);
|
|
||||||
}
|
|
||||||
catch (DecodeException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Unable decode input stream", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPartialBinaryMessage(ByteBuffer buffer, boolean fin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
events.callBinary(jsrsession.getAsyncRemote(),websocket,buffer,fin);
|
|
||||||
}
|
|
||||||
catch (DecodeException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Unable decode partial binary message", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onPartialTextMessage(String message, boolean fin)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
events.callText(jsrsession.getAsyncRemote(),websocket,message,fin);
|
|
||||||
}
|
|
||||||
catch (DecodeException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Unable decode partial text message", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPing(ByteBuffer buffer)
|
|
||||||
{
|
|
||||||
// Call pong, as there is no "onPing" method in the JSR
|
|
||||||
events.callPong(jsrsession.getAsyncRemote(),websocket,buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPong(ByteBuffer buffer)
|
|
||||||
{
|
|
||||||
events.callPong(jsrsession.getAsyncRemote(),websocket,buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReader(Reader reader) throws IOException
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
events.callTextStream(jsrsession.getAsyncRemote(),websocket,reader);
|
|
||||||
}
|
|
||||||
catch (DecodeException e)
|
|
||||||
{
|
|
||||||
throw new RuntimeException("Unable decode reader", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Entry point for all incoming text frames.
|
|
||||||
*//*
|
|
||||||
@Override
|
|
||||||
public void onTextFrame(ByteBuffer buffer, boolean fin) throws IOException
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("onTextFrame({}, {})",BufferUtil.toDetailString(buffer),fin);
|
|
||||||
LOG.debug("events.hasText={}",events.hasText());
|
|
||||||
LOG.debug("events.hasTextStream={}",events.hasTextStream());
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean handled = false;
|
|
||||||
|
|
||||||
if (events.hasText())
|
|
||||||
{
|
|
||||||
handled = true;
|
|
||||||
if (activeMessage == null)
|
|
||||||
{
|
|
||||||
if (events.isTextPartialSupported())
|
|
||||||
{
|
|
||||||
// Partial Message Support
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("Partial Text Message: fin={}",fin);
|
|
||||||
}
|
|
||||||
activeMessage = new TextPartialOnMessage(this);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Whole Message Support
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("Whole Text Message");
|
|
||||||
}
|
|
||||||
activeMessage = new StringMessageSink(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (events.hasTextStream())
|
|
||||||
{
|
|
||||||
handled = true;
|
|
||||||
// Streaming Message Support
|
|
||||||
if (activeMessage == null)
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("Text Message Writer");
|
|
||||||
}
|
|
||||||
|
|
||||||
final MessageReader stream = new MessageReader(new MessageInputStream());
|
|
||||||
activeMessage = stream;
|
|
||||||
|
|
||||||
// Always dispatch streaming read to another thread.
|
|
||||||
dispatch(new Runnable()
|
|
||||||
{
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
events.callTextStream(jsrsession.getAsyncRemote(),websocket,stream);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
onFatalError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("handled = {}", handled);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Process any active MessageAppender
|
|
||||||
if (handled && (activeMessage != null))
|
|
||||||
{
|
|
||||||
appendMessage(buffer,fin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Entry point for whole text messages
|
|
||||||
*//*
|
|
||||||
@Override
|
|
||||||
public void onTextMessage(String message)
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("onText({})",message);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// FIN is always true here
|
|
||||||
events.callText(jsrsession.getAsyncRemote(),websocket,message,true);
|
|
||||||
}
|
|
||||||
catch (Throwable e)
|
|
||||||
{
|
|
||||||
onFatalError(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPathParameters(Map<String, String> pathParameters)
|
|
||||||
{
|
|
||||||
events.setPathParameters(pathParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return String.format("%s[websocket=%s]",this.getClass().getSimpleName(),websocket);
|
|
||||||
}*/
|
|
||||||
}
|
|
|
@ -1,270 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 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.endpoints;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EventDriver for websocket that extend from {@link javax.websocket.Endpoint}
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public class JsrEndpointEventDriver extends AbstractJsrEventDriver
|
|
||||||
{
|
|
||||||
/*private static final Logger LOG = Log.getLogger(JsrEndpointEventDriver.class);
|
|
||||||
|
|
||||||
private final Endpoint endpoint;
|
|
||||||
private Map<String, String> pathParameters;
|
|
||||||
|
|
||||||
public JsrEndpointEventDriver(WebSocketPolicy policy, Executor executor, ConfiguredEndpoint endpointInstance)
|
|
||||||
{
|
|
||||||
super(policy,executor,endpointInstance);
|
|
||||||
this.endpoint = (Endpoint)endpointInstance.getEndpoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(JsrSession jsrsession)
|
|
||||||
{
|
|
||||||
jsrsession.setPathParameters(pathParameters);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBinaryFrame(ByteBuffer buffer, boolean fin) throws IOException
|
|
||||||
{
|
|
||||||
if (activeMessage == null)
|
|
||||||
{
|
|
||||||
activeMessage = jsrsession.newMessageAppenderFor(MessageType.BINARY);
|
|
||||||
if (activeMessage == null)
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("No BINARY MessageHandler declared");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
*//*
|
|
||||||
if (wrapper.wantsPartialMessages())
|
|
||||||
{
|
|
||||||
activeMessage = new BinaryPartialMessage(wrapper);
|
|
||||||
}
|
|
||||||
else if (wrapper.wantsStreams())
|
|
||||||
{
|
|
||||||
final MessageInputStream stream = new MessageInputStream();
|
|
||||||
activeMessage = stream;
|
|
||||||
dispatch(new Runnable()
|
|
||||||
{
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public void run()
|
|
||||||
{
|
|
||||||
MessageHandler.Whole<InputStream> handler = (Whole<InputStream>)wrapper.getHandler();
|
|
||||||
handler.onMessage(stream);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
activeMessage = new BinaryWholeMessage(this,wrapper);
|
|
||||||
}
|
|
||||||
*//*
|
|
||||||
}
|
|
||||||
|
|
||||||
activeMessage.appendFrame(buffer,fin);
|
|
||||||
|
|
||||||
if (fin)
|
|
||||||
{
|
|
||||||
activeMessage.messageComplete();
|
|
||||||
activeMessage = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBinaryMessage(byte[] data)
|
|
||||||
{
|
|
||||||
*//* Ignored, handled by BinaryWholeMessage *//*
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onObject(Object o)
|
|
||||||
{
|
|
||||||
// TODO: deliver to message handler
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onClose(CloseReason closereason)
|
|
||||||
{
|
|
||||||
endpoint.onClose(this.jsrsession,closereason);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onConnect()
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("onConnect({}, {})",jsrsession,config);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Let unhandled exceptions flow out
|
|
||||||
endpoint.onOpen(jsrsession,config);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Throwable cause)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
endpoint.onError(jsrsession,cause);
|
|
||||||
}
|
|
||||||
catch (Throwable t)
|
|
||||||
{
|
|
||||||
LOG.warn("Unable to report to onError due to exception",t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFrame(Frame frame)
|
|
||||||
{
|
|
||||||
*//* Ignored, not supported by JSR-356 *//*
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInputStream(InputStream stream)
|
|
||||||
{
|
|
||||||
*//* Ignored, handled by BinaryStreamMessage *//*
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReader(Reader reader)
|
|
||||||
{
|
|
||||||
*//* Ignored, handled by TextStreamMessage *//*
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextFrame(ByteBuffer buffer, boolean fin) throws IOException
|
|
||||||
{
|
|
||||||
if (activeMessage == null)
|
|
||||||
{
|
|
||||||
activeMessage = jsrsession.newMessageAppenderFor(MessageType.TEXT);
|
|
||||||
if (activeMessage == null)
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("No TEXT MessageHandler declared");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (wrapper.wantsPartialMessages())
|
|
||||||
// {
|
|
||||||
// activeMessage = new TextPartialMessage(wrapper);
|
|
||||||
// }
|
|
||||||
// else if (wrapper.wantsStreams())
|
|
||||||
// {
|
|
||||||
// final MessageReader stream = new MessageReader(new MessageInputStream());
|
|
||||||
// activeMessage = stream;
|
|
||||||
//
|
|
||||||
// dispatch(new Runnable()
|
|
||||||
// {
|
|
||||||
// @SuppressWarnings("unchecked")
|
|
||||||
// @Override
|
|
||||||
// public void run()
|
|
||||||
// {
|
|
||||||
// MessageHandler.Whole<Reader> handler = (Whole<Reader>)wrapper.getHandler();
|
|
||||||
// handler.onMessage(stream);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// else
|
|
||||||
// {
|
|
||||||
// activeMessage = new TextWholeMessage(this,wrapper);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
activeMessage.appendFrame(buffer,fin);
|
|
||||||
|
|
||||||
if (fin)
|
|
||||||
{
|
|
||||||
activeMessage.messageComplete();
|
|
||||||
activeMessage = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onTextMessage(String message)
|
|
||||||
{
|
|
||||||
*//* Ignored, handled by TextWholeMessage *//*
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPing(ByteBuffer buffer)
|
|
||||||
{
|
|
||||||
onPongMessage(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onPong(ByteBuffer buffer)
|
|
||||||
{
|
|
||||||
onPongMessage(buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void onPongMessage(ByteBuffer buffer)
|
|
||||||
{
|
|
||||||
MessageSink appender = jsrsession.newMessageAppenderFor(MessageType.PONG);
|
|
||||||
if (appender == null)
|
|
||||||
{
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
{
|
|
||||||
LOG.debug("No PONG MessageHandler declared");
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer pongBuf = null;
|
|
||||||
|
|
||||||
if (BufferUtil.isEmpty(buffer))
|
|
||||||
{
|
|
||||||
pongBuf = BufferUtil.EMPTY_BUFFER;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pongBuf = ByteBuffer.allocate(buffer.remaining());
|
|
||||||
BufferUtil.put(buffer,pongBuf);
|
|
||||||
BufferUtil.flipToFlush(pongBuf,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
appender.appendFrame(pongBuf,true);
|
|
||||||
}
|
|
||||||
catch (IOException e)
|
|
||||||
{
|
|
||||||
LOG.debug(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setPathParameters(Map<String, String> pathParameters)
|
|
||||||
{
|
|
||||||
this.pathParameters = pathParameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString()
|
|
||||||
{
|
|
||||||
return String.format("%s[%s]",JsrEndpointEventDriver.class.getSimpleName(),endpoint.getClass().getName());
|
|
||||||
}*/
|
|
||||||
}
|
|
|
@ -1,53 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 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.endpoints;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public class JsrEndpointImpl /*implements EventDriverImpl*/
|
|
||||||
{
|
|
||||||
/*public EventDriver create(Object websocket, WebSocketPolicy policy)
|
|
||||||
{
|
|
||||||
if (!(websocket instanceof ConfiguredEndpoint))
|
|
||||||
{
|
|
||||||
throw new IllegalStateException(String.format("Websocket %s must be an %s",websocket.getClass().getName(),ConfiguredEndpoint.class.getName()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new JsrEndpointEventDriver(policy,(ConfiguredEndpoint)websocket);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String describeRule()
|
|
||||||
{
|
|
||||||
return "class extends " + javax.websocket.Endpoint.class.getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean supports(Object websocket)
|
|
||||||
{
|
|
||||||
if (!(websocket instanceof ConfiguredEndpoint))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConfiguredEndpoint ei = (ConfiguredEndpoint)websocket;
|
|
||||||
Object endpoint = ei.getEndpoint();
|
|
||||||
|
|
||||||
return (endpoint instanceof javax.websocket.Endpoint);
|
|
||||||
}*/
|
|
||||||
}
|
|
|
@ -1,48 +0,0 @@
|
||||||
//
|
|
||||||
// ========================================================================
|
|
||||||
// Copyright (c) 1995-2017 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.endpoints;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public class JsrEventDriverFactory /*extends EventDriverFactory*/
|
|
||||||
{
|
|
||||||
/* public JsrEventDriverFactory(WebSocketPolicy policy)
|
|
||||||
{
|
|
||||||
// super(policy);
|
|
||||||
|
|
||||||
*//*clearImplementations();
|
|
||||||
// Classes that extend javax.websocket.Endpoint
|
|
||||||
addImplementation(new JsrEndpointImpl());
|
|
||||||
// Classes annotated with @javax.websocket.ClientEndpoint
|
|
||||||
addImplementation(new JsrClientEndpointImpl());*//*
|
|
||||||
}
|
|
||||||
|
|
||||||
*//**
|
|
||||||
* Unwrap ConfiguredEndpoint for end-user.
|
|
||||||
*//*
|
|
||||||
protected String getClassName(Object websocket)
|
|
||||||
{
|
|
||||||
if (websocket instanceof ConfiguredEndpoint)
|
|
||||||
{
|
|
||||||
ConfiguredEndpoint ce = (ConfiguredEndpoint)websocket;
|
|
||||||
return ce.getEndpoint().getClass().getName();
|
|
||||||
}
|
|
||||||
|
|
||||||
return websocket.getClass().getName();
|
|
||||||
}*/
|
|
||||||
}
|
|
|
@ -149,8 +149,8 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final AvailableEncoders encoders;
|
protected final AvailableEncoders encoders;
|
||||||
private final AvailableDecoders decoders;
|
protected final AvailableDecoders decoders;
|
||||||
private final EndpointConfig endpointConfig;
|
private final EndpointConfig endpointConfig;
|
||||||
private List<StaticArg> staticArgs;
|
private List<StaticArg> staticArgs;
|
||||||
|
|
||||||
|
@ -424,6 +424,7 @@ public class JsrEndpointFunctions extends CommonEndpointFunctions<JsrSession>
|
||||||
*
|
*
|
||||||
* @param endpoint the endpoint object
|
* @param endpoint the endpoint object
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
protected void discoverAnnotatedEndpointFunctions(Object endpoint)
|
protected void discoverAnnotatedEndpointFunctions(Object endpoint)
|
||||||
{
|
{
|
||||||
Class<?> endpointClass = endpoint.getClass();
|
Class<?> endpointClass = endpoint.getClass();
|
||||||
|
|
|
@ -18,17 +18,33 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.websocket.jsr356.endpoints;
|
package org.eclipse.jetty.websocket.jsr356.endpoints;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import javax.websocket.ClientEndpointConfig;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.toolchain.test.EventQueue;
|
||||||
|
import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
||||||
|
import org.eclipse.jetty.websocket.api.StatusCode;
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
|
import org.eclipse.jetty.websocket.common.CloseInfo;
|
||||||
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
|
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseEndpointConfigSocket;
|
import org.eclipse.jetty.websocket.jsr356.client.EmptyClientEndpointConfig;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.decoders.AvailableDecoders;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.encoders.AvailableEncoders;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseReasonSessionSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseReasonSessionSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseReasonSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseReasonSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseSessionReasonSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseSessionReasonSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseSessionSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseSessionSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseSocket;
|
import org.eclipse.jetty.websocket.jsr356.endpoints.samples.close.CloseSocket;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.function.JsrEndpointFunctions;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.Parameterized;
|
import org.junit.runners.Parameterized;
|
||||||
|
@ -44,69 +60,81 @@ public class OnCloseTest
|
||||||
Case tcase = new Case();
|
Case tcase = new Case();
|
||||||
tcase.closeClass = closeClass;
|
tcase.closeClass = closeClass;
|
||||||
data.add(new Case[]
|
data.add(new Case[]
|
||||||
{ tcase });
|
{tcase});
|
||||||
return tcase;
|
return tcase;
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> closeClass;
|
Class<?> closeClass;
|
||||||
String expectedCloseEvent;
|
String expectedCloseEvent;
|
||||||
|
|
||||||
public Case expect(String expectedEvent)
|
public Case expect(String expectedEvent)
|
||||||
{
|
{
|
||||||
this.expectedCloseEvent = expectedEvent;
|
this.expectedCloseEvent = expectedEvent;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return closeClass.getSimpleName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClientContainer container = new ClientContainer();
|
private static ClientContainer container = new ClientContainer();
|
||||||
|
|
||||||
@Parameters
|
@Parameters(name = "{0}")
|
||||||
public static Collection<Case[]> data() throws Exception
|
public static Collection<Case[]> data() throws Exception
|
||||||
{
|
{
|
||||||
List<Case[]> data = new ArrayList<>();
|
List<Case[]> data = new ArrayList<>();
|
||||||
|
|
||||||
Case.add(data,CloseSocket.class).expect("onClose()");
|
Case.add(data, CloseSocket.class).expect("onClose()");
|
||||||
Case.add(data,CloseReasonSocket.class).expect("onClose(CloseReason)");
|
Case.add(data, CloseReasonSocket.class).expect("onClose(CloseReason)");
|
||||||
Case.add(data,CloseSessionSocket.class).expect("onClose(Session)");
|
Case.add(data, CloseSessionSocket.class).expect("onClose(Session)");
|
||||||
Case.add(data,CloseReasonSessionSocket.class).expect("onClose(CloseReason,Session)");
|
Case.add(data, CloseReasonSessionSocket.class).expect("onClose(CloseReason,Session)");
|
||||||
Case.add(data,CloseSessionReasonSocket.class).expect("onClose(Session,CloseReason)");
|
Case.add(data, CloseSessionReasonSocket.class).expect("onClose(Session,CloseReason)");
|
||||||
Case.add(data,CloseEndpointConfigSocket.class).expect("onClose(EndpointConfig)");
|
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final Case testcase;
|
private final Case testcase;
|
||||||
|
|
||||||
public OnCloseTest(Case testcase)
|
public OnCloseTest(Case testcase)
|
||||||
{
|
{
|
||||||
this.testcase = testcase;
|
this.testcase = testcase;
|
||||||
System.err.printf("Testing @OnClose for %s%n",testcase.closeClass.getName());
|
System.err.printf("Testing @OnClose for %s%n", testcase.closeClass.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOnCloseCall() throws Exception
|
public void testOnCloseCall() throws Exception
|
||||||
{
|
{
|
||||||
/*// Scan annotations
|
|
||||||
AnnotatedClientEndpointMetadata metadata = new AnnotatedClientEndpointMetadata(container,testcase.closeClass);
|
|
||||||
AnnotatedEndpointScanner<ClientEndpoint, ClientEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
|
|
||||||
scanner.scan();
|
|
||||||
|
|
||||||
// Build up EventDriver
|
// Build up EventDriver
|
||||||
WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();
|
WebSocketPolicy policy = WebSocketPolicy.newClientPolicy();
|
||||||
ClientEndpointConfig config = metadata.getConfig();
|
TrackingSocket endpoint = (TrackingSocket) testcase.closeClass.newInstance();
|
||||||
TrackingSocket endpoint = (TrackingSocket)testcase.closeClass.newInstance();
|
|
||||||
ConfiguredEndpoint ei = new ConfiguredEndpoint(endpoint,config,metadata);
|
Executor executor = new QueuedThreadPool();
|
||||||
JsrEvents<ClientEndpoint, ClientEndpointConfig> jsrevents = new JsrEvents<>(metadata);
|
ClientEndpointConfig config = new EmptyClientEndpointConfig();
|
||||||
|
AvailableEncoders encoders = new AvailableEncoders(config);
|
||||||
EventDriver driver = new JsrAnnotatedEventDriver(policy,ei,jsrevents);
|
AvailableDecoders decoders = new AvailableDecoders(config);
|
||||||
|
Map<String, String> uriParams = new HashMap<>();
|
||||||
// Execute onClose call
|
|
||||||
driver.onClose(new CloseInfo(StatusCode.NORMAL,"normal"));
|
JsrEndpointFunctions jsrFunctions = new JsrEndpointFunctions(endpoint, policy,
|
||||||
|
executor, encoders, decoders, uriParams, config);
|
||||||
// Test captured event
|
try
|
||||||
EventQueue<String> events = endpoint.eventQueue;
|
{
|
||||||
Assert.assertThat("Number of Events Captured",events.size(),is(1));
|
jsrFunctions.start();
|
||||||
String closeEvent = events.poll();
|
|
||||||
Assert.assertThat("Close Event",closeEvent,is(testcase.expectedCloseEvent)); */
|
// Execute onClose call
|
||||||
|
jsrFunctions.onClose(new CloseInfo(StatusCode.NORMAL, "normal"));
|
||||||
|
|
||||||
|
// Test captured event
|
||||||
|
EventQueue<String> events = endpoint.eventQueue;
|
||||||
|
assertThat("Number of Events Captured", events.size(), is(1));
|
||||||
|
String closeEvent = events.poll();
|
||||||
|
assertThat("Close Event", closeEvent, is(testcase.expectedCloseEvent));
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
jsrFunctions.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,10 +27,10 @@ import org.eclipse.jetty.websocket.jsr356.endpoints.TrackingSocket;
|
||||||
@ClientEndpoint
|
@ClientEndpoint
|
||||||
public class CloseEndpointConfigSocket extends TrackingSocket
|
public class CloseEndpointConfigSocket extends TrackingSocket
|
||||||
{
|
{
|
||||||
|
// Intentionally Invalid Declaration
|
||||||
@OnClose
|
@OnClose
|
||||||
public void onClose(EndpointConfig config)
|
public void onClose(EndpointConfig config)
|
||||||
{
|
{
|
||||||
addEvent("onClose(EndpointConfig)");
|
throw new RuntimeException("Should not have worked. Invalid declaration: " + this.getClass().getName());
|
||||||
closeLatch.countDown();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
import org.eclipse.jetty.websocket.api.extensions.ExtensionConfig;
|
||||||
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
import org.eclipse.jetty.websocket.api.extensions.ExtensionFactory;
|
||||||
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
import org.eclipse.jetty.websocket.common.scopes.WebSocketContainerScope;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.ConfiguredEndpoint;
|
||||||
import org.eclipse.jetty.websocket.jsr356.JsrExtension;
|
import org.eclipse.jetty.websocket.jsr356.JsrExtension;
|
||||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeRequest;
|
||||||
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
import org.eclipse.jetty.websocket.servlet.ServletUpgradeResponse;
|
||||||
|
@ -162,7 +163,7 @@ public class JsrCreator implements WebSocketCreator
|
||||||
Object endpoint = config.getConfigurator().getEndpointInstance(endpointClass);
|
Object endpoint = config.getConfigurator().getEndpointInstance(endpointClass);
|
||||||
// Do not decorate here (let the Connection and Session start first)
|
// Do not decorate here (let the Connection and Session start first)
|
||||||
// This will allow CDI to see Session for injection into Endpoint classes.
|
// This will allow CDI to see Session for injection into Endpoint classes.
|
||||||
return endpoint;
|
return new ConfiguredEndpoint(endpoint,config);
|
||||||
}
|
}
|
||||||
catch (InstantiationException e)
|
catch (InstantiationException e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
//
|
||||||
|
// ========================================================================
|
||||||
|
// 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.server;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
import javax.websocket.DecodeException;
|
||||||
|
import javax.websocket.EndpointConfig;
|
||||||
|
import javax.websocket.server.ServerEndpoint;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
|
||||||
|
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.decoders.AvailableDecoders;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.encoders.AvailableEncoders;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.function.JsrEndpointFunctions;
|
||||||
|
|
||||||
|
public class JsrServerEndpointFunctions extends JsrEndpointFunctions
|
||||||
|
{
|
||||||
|
public JsrServerEndpointFunctions(Object endpoint, WebSocketPolicy policy, Executor executor,
|
||||||
|
AvailableEncoders encoders, AvailableDecoders decoders,
|
||||||
|
Map<String, String> uriParams, EndpointConfig endpointConfig)
|
||||||
|
{
|
||||||
|
super(endpoint, policy, executor, encoders, decoders, uriParams, endpointConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generic discovery of annotated endpoint functions.
|
||||||
|
*
|
||||||
|
* @param endpoint the endpoint object
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
|
protected void discoverAnnotatedEndpointFunctions(Object endpoint)
|
||||||
|
{
|
||||||
|
Class<?> endpointClass = endpoint.getClass();
|
||||||
|
|
||||||
|
// Use the JSR/Server annotation
|
||||||
|
ServerEndpoint websocket = endpointClass.getAnnotation(ServerEndpoint.class);
|
||||||
|
|
||||||
|
if (websocket != null)
|
||||||
|
{
|
||||||
|
encoders.registerAll(websocket.encoders());
|
||||||
|
decoders.registerAll(websocket.decoders());
|
||||||
|
|
||||||
|
// From here, the discovery of endpoint method is standard across
|
||||||
|
// both JSR356/Client and JSR356/Server endpoints
|
||||||
|
try
|
||||||
|
{
|
||||||
|
discoverJsrAnnotatedEndpointFunctions(endpoint);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
catch (DecodeException e)
|
||||||
|
{
|
||||||
|
throw new InvalidWebSocketException("Cannot instantiate WebSocket", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not a ServerEndpoint, let the ClientEndpoint test proceed
|
||||||
|
super.discoverAnnotatedEndpointFunctions(endpoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.jsr356.server;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
@ -38,8 +39,11 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||||
|
import org.eclipse.jetty.websocket.common.function.EndpointFunctions;
|
||||||
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
|
import org.eclipse.jetty.websocket.jsr356.ClientContainer;
|
||||||
import org.eclipse.jetty.websocket.jsr356.JsrSessionFactory;
|
import org.eclipse.jetty.websocket.jsr356.JsrSessionFactory;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.decoders.AvailableDecoders;
|
||||||
|
import org.eclipse.jetty.websocket.jsr356.encoders.AvailableEncoders;
|
||||||
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
|
import org.eclipse.jetty.websocket.server.MappedWebSocketCreator;
|
||||||
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
import org.eclipse.jetty.websocket.server.WebSocketServerFactory;
|
||||||
|
|
||||||
|
@ -157,6 +161,22 @@ public class ServerContainer extends ClientContainer implements javax.websocket.
|
||||||
mappedCreator.addMapping(new UriTemplatePathSpec(config.getPath()), creator);
|
mappedCreator.addMapping(new UriTemplatePathSpec(config.getPath()), creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EndpointFunctions newJsrEndpointFunction(Object endpoint,
|
||||||
|
AvailableEncoders availableEncoders,
|
||||||
|
AvailableDecoders availableDecoders,
|
||||||
|
Map<String, String> pathParameters,
|
||||||
|
EndpointConfig config)
|
||||||
|
{
|
||||||
|
return new JsrServerEndpointFunctions(endpoint,
|
||||||
|
getPolicy(),
|
||||||
|
getExecutor(),
|
||||||
|
availableEncoders,
|
||||||
|
availableDecoders,
|
||||||
|
pathParameters,
|
||||||
|
config);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void doStart() throws Exception
|
protected void doStart() throws Exception
|
||||||
{
|
{
|
||||||
|
|
|
@ -124,7 +124,7 @@ public class EchoCase
|
||||||
StringBuilder str = new StringBuilder();
|
StringBuilder str = new StringBuilder();
|
||||||
str.append("EchoCase['");
|
str.append("EchoCase['");
|
||||||
str.append(path);
|
str.append(path);
|
||||||
str.append("',").append(serverPojo.getName());
|
str.append("',").append(serverPojo.getSimpleName());
|
||||||
str.append(",messages[").append(messages.size());
|
str.append(",messages[").append(messages.size());
|
||||||
str.append("]=");
|
str.append("]=");
|
||||||
boolean delim = false;
|
boolean delim = false;
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.websocket.jsr356.server;
|
package org.eclipse.jetty.websocket.jsr356.server;
|
||||||
|
|
||||||
import static org.eclipse.jetty.toolchain.test.ExtraMatchers.ordered;
|
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -77,7 +76,9 @@ import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.InputStreamSo
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderParamSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderParamSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderSocket;
|
||||||
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.StringReturnReaderParamSocket;
|
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.StringReturnReaderParamSocket;
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
@ -280,7 +281,7 @@ public class EchoTest
|
||||||
server.stop();
|
server.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Parameters
|
@Parameters(name = "{0}")
|
||||||
public static Collection<EchoCase[]> data() throws Exception
|
public static Collection<EchoCase[]> data() throws Exception
|
||||||
{
|
{
|
||||||
return TESTCASES;
|
return TESTCASES;
|
||||||
|
@ -339,7 +340,7 @@ public class EchoTest
|
||||||
EventQueue<String> received = socket.eventQueue;
|
EventQueue<String> received = socket.eventQueue;
|
||||||
|
|
||||||
// Validate Responses
|
// Validate Responses
|
||||||
assertThat("Received Events", received, ordered(testcase.expectedStrings));
|
assertOrdered("Received Events", testcase.expectedStrings, received);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -347,4 +348,21 @@ public class EchoTest
|
||||||
socket.close();
|
socket.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("Duplicates")
|
||||||
|
public static void assertOrdered(String msg, List<String> expectedList, EventQueue<String> actualList)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Assert.assertEquals(msg, expectedList.size(), actualList.size());
|
||||||
|
if (!expectedList.isEmpty())
|
||||||
|
assertThat(msg, actualList, Matchers.contains(expectedList.toArray()));
|
||||||
|
}
|
||||||
|
catch (AssertionError e)
|
||||||
|
{
|
||||||
|
System.err.println("Expected: " + expectedList);
|
||||||
|
System.err.println("Actual : " + actualList);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -282,8 +282,8 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new InvalidWebSocketException("Unable to create Session: unrecognized internal EventDriver type: " + websocket.getClass().getName());
|
throw new InvalidWebSocketException("Unable to create Session: unrecognized endpoint type: " + websocket.getClass().getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue