JSR-356 - Cleaning up sendObject(Object) behavior between Basic & Async
This commit is contained in:
parent
5667928921
commit
5d45486b8d
|
@ -0,0 +1,194 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
//
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
//
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
//
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
//
|
||||
|
||||
package org.eclipse.jetty.websocket.jsr356;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.websocket.EncodeException;
|
||||
import javax.websocket.Encoder;
|
||||
import javax.websocket.RemoteEndpoint;
|
||||
import javax.websocket.SendHandler;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint;
|
||||
import org.eclipse.jetty.websocket.common.io.FutureWriteCallback;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageOutputStream;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageWriter;
|
||||
import org.eclipse.jetty.websocket.jsr356.encoders.EncodeFailedFuture;
|
||||
|
||||
public abstract class AbstractJsrRemote implements RemoteEndpoint
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(AbstractJsrRemote.class);
|
||||
|
||||
protected final JsrSession session;
|
||||
protected final WebSocketRemoteEndpoint jettyRemote;
|
||||
protected final EncoderFactory encoders;
|
||||
|
||||
protected AbstractJsrRemote(JsrSession session)
|
||||
{
|
||||
this.session = session;
|
||||
if (!(session.getRemote() instanceof WebSocketRemoteEndpoint))
|
||||
{
|
||||
StringBuilder err = new StringBuilder();
|
||||
err.append("Unexpected implementation [");
|
||||
err.append(session.getRemote().getClass().getName());
|
||||
err.append("]. Expected an instanceof [");
|
||||
err.append(WebSocketRemoteEndpoint.class.getName());
|
||||
err.append("]");
|
||||
throw new IllegalStateException(err.toString());
|
||||
}
|
||||
this.jettyRemote = (WebSocketRemoteEndpoint)session.getRemote();
|
||||
this.encoders = session.getEncoderFactory();
|
||||
}
|
||||
|
||||
protected void assertMessageNotNull(Object data)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
throw new IllegalArgumentException("message cannot be null");
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertSendHandlerNotNull(SendHandler handler)
|
||||
{
|
||||
if (handler == null)
|
||||
{
|
||||
throw new IllegalArgumentException("SendHandler cannot be null");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatch() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBatchingAllowed()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings(
|
||||
{ "rawtypes", "unchecked" })
|
||||
public Future<Void> sendObjectViaFuture(Object data)
|
||||
{
|
||||
assertMessageNotNull(data);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendObject({})",data);
|
||||
}
|
||||
|
||||
Encoder encoder = encoders.getEncoderFor(data.getClass());
|
||||
if (encoder == null)
|
||||
{
|
||||
throw new IllegalArgumentException("No encoder for type: " + data.getClass());
|
||||
}
|
||||
|
||||
if (encoder instanceof Encoder.Text)
|
||||
{
|
||||
Encoder.Text etxt = (Encoder.Text)encoder;
|
||||
try
|
||||
{
|
||||
String msg = etxt.encode(data);
|
||||
return jettyRemote.sendStringByFuture(msg);
|
||||
}
|
||||
catch (EncodeException e)
|
||||
{
|
||||
return new EncodeFailedFuture(data,etxt,Encoder.Text.class,e);
|
||||
}
|
||||
}
|
||||
else if (encoder instanceof Encoder.TextStream)
|
||||
{
|
||||
Encoder.TextStream etxt = (Encoder.TextStream)encoder;
|
||||
FutureWriteCallback callback = new FutureWriteCallback();
|
||||
try (MessageWriter writer = new MessageWriter(session))
|
||||
{
|
||||
writer.setCallback(callback);
|
||||
etxt.encode(data,writer);
|
||||
return callback;
|
||||
}
|
||||
catch (EncodeException | IOException e)
|
||||
{
|
||||
return new EncodeFailedFuture(data,etxt,Encoder.Text.class,e);
|
||||
}
|
||||
}
|
||||
else if (encoder instanceof Encoder.Binary)
|
||||
{
|
||||
Encoder.Binary ebin = (Encoder.Binary)encoder;
|
||||
try
|
||||
{
|
||||
ByteBuffer buf = ebin.encode(data);
|
||||
return jettyRemote.sendBytesByFuture(buf);
|
||||
}
|
||||
catch (EncodeException e)
|
||||
{
|
||||
return new EncodeFailedFuture(data,ebin,Encoder.Binary.class,e);
|
||||
}
|
||||
}
|
||||
else if (encoder instanceof Encoder.BinaryStream)
|
||||
{
|
||||
Encoder.BinaryStream ebin = (Encoder.BinaryStream)encoder;
|
||||
FutureWriteCallback callback = new FutureWriteCallback();
|
||||
try (MessageOutputStream out = new MessageOutputStream(session))
|
||||
{
|
||||
out.setCallback(callback);
|
||||
ebin.encode(data,out);
|
||||
return callback;
|
||||
}
|
||||
catch (EncodeException | IOException e)
|
||||
{
|
||||
return new EncodeFailedFuture(data,ebin,Encoder.Binary.class,e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown encoder type: " + encoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPing(ByteBuffer data) throws IOException, IllegalArgumentException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendPing({})",BufferUtil.toDetailString(data));
|
||||
}
|
||||
jettyRemote.sendPing(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPong(ByteBuffer data) throws IOException, IllegalArgumentException
|
||||
{
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendPong({})",BufferUtil.toDetailString(data));
|
||||
}
|
||||
jettyRemote.sendPong(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchingAllowed(boolean allowed) throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
}
|
|
@ -28,67 +28,22 @@ import javax.websocket.RemoteEndpoint;
|
|||
import javax.websocket.SendHandler;
|
||||
import javax.websocket.SendResult;
|
||||
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketFrame;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketRemoteEndpoint;
|
||||
import org.eclipse.jetty.websocket.common.io.FutureWriteCallback;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageOutputStream;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageWriter;
|
||||
import org.eclipse.jetty.websocket.jsr356.encoders.EncodeFailedFuture;
|
||||
import org.eclipse.jetty.websocket.common.util.TextUtil;
|
||||
import org.eclipse.jetty.websocket.jsr356.messages.SendHandlerWriteCallback;
|
||||
|
||||
public class JsrAsyncRemote implements RemoteEndpoint.Async
|
||||
public class JsrAsyncRemote extends AbstractJsrRemote implements RemoteEndpoint.Async
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(JsrAsyncRemote.class);
|
||||
private final JsrSession session;
|
||||
private final WebSocketRemoteEndpoint jettyRemote;
|
||||
private final EncoderFactory encoders;
|
||||
static final Logger LOG = Log.getLogger(JsrAsyncRemote.class);
|
||||
|
||||
protected JsrAsyncRemote(JsrSession session)
|
||||
{
|
||||
this.session = session;
|
||||
if (!(session.getRemote() instanceof WebSocketRemoteEndpoint))
|
||||
{
|
||||
StringBuilder err = new StringBuilder();
|
||||
err.append("Unexpected implementation [");
|
||||
err.append(session.getRemote().getClass().getName());
|
||||
err.append("]. Expected an instanceof [");
|
||||
err.append(WebSocketRemoteEndpoint.class.getName());
|
||||
err.append("]");
|
||||
throw new IllegalStateException(err.toString());
|
||||
}
|
||||
this.jettyRemote = (WebSocketRemoteEndpoint)session.getRemote();
|
||||
this.encoders = session.getEncoderFactory();
|
||||
}
|
||||
|
||||
private void assertMessageNotNull(Object data)
|
||||
{
|
||||
if (data == null)
|
||||
{
|
||||
throw new IllegalArgumentException("message cannot be null");
|
||||
}
|
||||
}
|
||||
|
||||
private void assertSendHandlerNotNull(SendHandler handler)
|
||||
{
|
||||
if (handler == null)
|
||||
{
|
||||
throw new IllegalArgumentException("SendHandler cannot be null");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatch() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBatchingAllowed()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -102,6 +57,10 @@ public class JsrAsyncRemote implements RemoteEndpoint.Async
|
|||
public Future<Void> sendBinary(ByteBuffer data)
|
||||
{
|
||||
assertMessageNotNull(data);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendBinary({})",BufferUtil.toDetailString(data));
|
||||
}
|
||||
return jettyRemote.sendBytesByFuture(data);
|
||||
}
|
||||
|
||||
|
@ -110,82 +69,18 @@ public class JsrAsyncRemote implements RemoteEndpoint.Async
|
|||
{
|
||||
assertMessageNotNull(data);
|
||||
assertSendHandlerNotNull(handler);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendBinary({},{})",BufferUtil.toDetailString(data),handler);
|
||||
}
|
||||
WebSocketFrame frame = WebSocketFrame.binary().setPayload(data).setFin(true);
|
||||
jettyRemote.sendFrame(frame,new SendHandlerWriteCallback(handler));
|
||||
}
|
||||
|
||||
@SuppressWarnings(
|
||||
{ "rawtypes", "unchecked" })
|
||||
@Override
|
||||
public Future<Void> sendObject(Object data)
|
||||
{
|
||||
LOG.debug("sendObject({})",data);
|
||||
assertMessageNotNull(data);
|
||||
|
||||
Encoder encoder = encoders.getEncoderFor(data.getClass());
|
||||
if (encoder == null)
|
||||
{
|
||||
throw new IllegalArgumentException("No encoder for type: " + data.getClass());
|
||||
}
|
||||
|
||||
if (encoder instanceof Encoder.Text)
|
||||
{
|
||||
Encoder.Text etxt = (Encoder.Text)encoder;
|
||||
try
|
||||
{
|
||||
String msg = etxt.encode(data);
|
||||
return jettyRemote.sendStringByFuture(msg);
|
||||
}
|
||||
catch (EncodeException e)
|
||||
{
|
||||
return new EncodeFailedFuture(data,etxt,Encoder.Text.class,e);
|
||||
}
|
||||
}
|
||||
else if (encoder instanceof Encoder.TextStream)
|
||||
{
|
||||
Encoder.TextStream etxt = (Encoder.TextStream)encoder;
|
||||
FutureWriteCallback callback = new FutureWriteCallback();
|
||||
try (MessageWriter writer = new MessageWriter(session))
|
||||
{
|
||||
writer.setCallback(callback);
|
||||
etxt.encode(data,writer);
|
||||
return callback;
|
||||
}
|
||||
catch (EncodeException | IOException e)
|
||||
{
|
||||
return new EncodeFailedFuture(data,etxt,Encoder.Text.class,e);
|
||||
}
|
||||
}
|
||||
else if (encoder instanceof Encoder.Binary)
|
||||
{
|
||||
Encoder.Binary ebin = (Encoder.Binary)encoder;
|
||||
try
|
||||
{
|
||||
ByteBuffer buf = ebin.encode(data);
|
||||
return jettyRemote.sendBytesByFuture(buf);
|
||||
}
|
||||
catch (EncodeException e)
|
||||
{
|
||||
return new EncodeFailedFuture(data,ebin,Encoder.Binary.class,e);
|
||||
}
|
||||
}
|
||||
else if (encoder instanceof Encoder.BinaryStream)
|
||||
{
|
||||
Encoder.BinaryStream ebin = (Encoder.BinaryStream)encoder;
|
||||
FutureWriteCallback callback = new FutureWriteCallback();
|
||||
try (MessageOutputStream out = new MessageOutputStream(session))
|
||||
{
|
||||
out.setCallback(callback);
|
||||
ebin.encode(data,out);
|
||||
return callback;
|
||||
}
|
||||
catch (EncodeException | IOException e)
|
||||
{
|
||||
return new EncodeFailedFuture(data,ebin,Encoder.Binary.class,e);
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException("Unknown encoder type: " + encoder);
|
||||
return sendObjectViaFuture(data);
|
||||
}
|
||||
|
||||
@SuppressWarnings(
|
||||
|
@ -193,9 +88,12 @@ public class JsrAsyncRemote implements RemoteEndpoint.Async
|
|||
@Override
|
||||
public void sendObject(Object data, SendHandler handler)
|
||||
{
|
||||
LOG.debug("sendObject({},{})",data,handler);
|
||||
assertMessageNotNull(data);
|
||||
assertSendHandlerNotNull(handler);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendObject({},{})",data,handler);
|
||||
}
|
||||
|
||||
Encoder encoder = encoders.getEncoderFor(data.getClass());
|
||||
if (encoder == null)
|
||||
|
@ -265,22 +163,14 @@ public class JsrAsyncRemote implements RemoteEndpoint.Async
|
|||
throw new IllegalArgumentException("Unknown encoder type: " + encoder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPing(ByteBuffer applicationData) throws IOException, IllegalArgumentException
|
||||
{
|
||||
jettyRemote.sendPing(applicationData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPong(ByteBuffer applicationData) throws IOException, IllegalArgumentException
|
||||
{
|
||||
jettyRemote.sendPong(applicationData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Future<Void> sendText(String text)
|
||||
{
|
||||
assertMessageNotNull(text);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendText({})",TextUtil.hint(text));
|
||||
}
|
||||
return jettyRemote.sendStringByFuture(text);
|
||||
}
|
||||
|
||||
|
@ -289,16 +179,14 @@ public class JsrAsyncRemote implements RemoteEndpoint.Async
|
|||
{
|
||||
assertMessageNotNull(text);
|
||||
assertSendHandlerNotNull(handler);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendText({},{})",TextUtil.hint(text),handler);
|
||||
}
|
||||
WebSocketFrame frame = WebSocketFrame.text(text).setFin(true);
|
||||
jettyRemote.sendFrame(frame,new SendHandlerWriteCallback(handler));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchingAllowed(boolean allowed) throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSendTimeout(long timeoutmillis)
|
||||
{
|
||||
|
|
|
@ -22,95 +22,99 @@ import java.io.IOException;
|
|||
import java.io.OutputStream;
|
||||
import java.io.Writer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import javax.websocket.EncodeException;
|
||||
import javax.websocket.RemoteEndpoint;
|
||||
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSession;
|
||||
import org.eclipse.jetty.util.BufferUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageOutputStream;
|
||||
import org.eclipse.jetty.websocket.common.message.MessageWriter;
|
||||
import org.eclipse.jetty.websocket.common.util.TextUtil;
|
||||
|
||||
public class JsrBasicRemote implements RemoteEndpoint.Basic
|
||||
public class JsrBasicRemote extends AbstractJsrRemote implements RemoteEndpoint.Basic
|
||||
{
|
||||
private final WebSocketSession jettySession;
|
||||
private final org.eclipse.jetty.websocket.api.RemoteEndpoint jettyRemote;
|
||||
private boolean batchingAllowed = false;
|
||||
private static final Logger LOG = Log.getLogger(JsrBasicRemote.class);
|
||||
|
||||
protected JsrBasicRemote(WebSocketSession session)
|
||||
protected JsrBasicRemote(JsrSession session)
|
||||
{
|
||||
this.jettySession = session;
|
||||
this.jettyRemote = jettySession.getRemote();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flushBatch() throws IOException
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getBatchingAllowed()
|
||||
{
|
||||
return batchingAllowed;
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream getSendStream() throws IOException
|
||||
{
|
||||
return new MessageOutputStream(jettySession);
|
||||
return new MessageOutputStream(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Writer getSendWriter() throws IOException
|
||||
{
|
||||
return new MessageWriter(jettySession);
|
||||
return new MessageWriter(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBinary(ByteBuffer data) throws IOException
|
||||
{
|
||||
assertMessageNotNull(data);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendBinary({})",BufferUtil.toDetailString(data));
|
||||
}
|
||||
jettyRemote.sendBytes(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException
|
||||
{
|
||||
assertMessageNotNull(partialByte);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendBinary({},{})",BufferUtil.toDetailString(partialByte),isLast);
|
||||
}
|
||||
jettyRemote.sendPartialBytes(partialByte,isLast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendObject(Object o) throws IOException, EncodeException
|
||||
public void sendObject(Object data) throws IOException, EncodeException
|
||||
{
|
||||
// TODO Find appropriate Encoder and encode for output
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPing(ByteBuffer applicationData) throws IOException, IllegalArgumentException
|
||||
{
|
||||
jettyRemote.sendPing(applicationData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPong(ByteBuffer applicationData) throws IOException, IllegalArgumentException
|
||||
{
|
||||
jettyRemote.sendPong(applicationData);
|
||||
Future<Void> fut = sendObjectViaFuture(data);
|
||||
try
|
||||
{
|
||||
fut.get(); // block till done
|
||||
}
|
||||
catch (ExecutionException e)
|
||||
{
|
||||
throw new IOException("Failed to write object",e.getCause());
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
throw new IOException("Failed to write object",e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendText(String text) throws IOException
|
||||
{
|
||||
assertMessageNotNull(text);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendText({})",TextUtil.hint(text));
|
||||
}
|
||||
jettyRemote.sendString(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendText(String partialMessage, boolean isLast) throws IOException
|
||||
{
|
||||
assertMessageNotNull(partialMessage);
|
||||
if (LOG.isDebugEnabled())
|
||||
{
|
||||
LOG.debug("sendText({},{})",TextUtil.hint(partialMessage),isLast);
|
||||
}
|
||||
jettyRemote.sendPartialString(partialMessage,isLast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBatchingAllowed(boolean allowed)
|
||||
{
|
||||
this.batchingAllowed = allowed;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.common.events.annotated.AbstractMethodAnnotationScanner;
|
||||
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
|
||||
import org.eclipse.jetty.websocket.jsr356.utils.MethodUtils;
|
||||
import org.eclipse.jetty.websocket.jsr356.utils.ReflectUtils;
|
||||
|
||||
public class AnnotatedEndpointScanner<T extends Annotation, C extends EndpointConfig> extends AbstractMethodAnnotationScanner<AnnotatedEndpointMetadata<T, C>>
|
||||
{
|
||||
|
@ -78,9 +78,9 @@ public class AnnotatedEndpointScanner<T extends Annotation, C extends EndpointCo
|
|||
err.append("Encountered duplicate method annotations @");
|
||||
err.append(methodAnnotationClass.getSimpleName());
|
||||
err.append(" on ");
|
||||
err.append(MethodUtils.toString(pojo,callable.getMethod()));
|
||||
err.append(ReflectUtils.toString(pojo,callable.getMethod()));
|
||||
err.append(" and ");
|
||||
err.append(MethodUtils.toString(pojo,method));
|
||||
err.append(ReflectUtils.toString(pojo,method));
|
||||
|
||||
throw new InvalidSignatureException(err.toString());
|
||||
}
|
||||
|
@ -179,7 +179,7 @@ public class AnnotatedEndpointScanner<T extends Annotation, C extends EndpointCo
|
|||
err.append("> on @");
|
||||
err.append(methodAnnotationClass.getSimpleName());
|
||||
err.append(" annotated method: ");
|
||||
err.append(MethodUtils.toString(pojo,method));
|
||||
err.append(ReflectUtils.toString(pojo,method));
|
||||
|
||||
throw new InvalidSignatureException(err.toString());
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ import javax.websocket.OnMessage;
|
|||
import javax.websocket.OnOpen;
|
||||
import javax.websocket.RemoteEndpoint;
|
||||
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
||||
|
||||
/**
|
||||
|
@ -40,6 +42,7 @@ import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
|||
*/
|
||||
public class JsrEvents<T extends Annotation, C extends EndpointConfig>
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(JsrEvents.class);
|
||||
private final AnnotatedEndpointMetadata<T, C> metadata;
|
||||
|
||||
/**
|
||||
|
@ -105,6 +108,7 @@ public class JsrEvents<T extends Annotation, C extends EndpointConfig>
|
|||
Object ret = onBinary.call(websocket,buf,fin);
|
||||
if (ret != null)
|
||||
{
|
||||
LOG.debug("returning: {}",ret);
|
||||
endpoint.sendObject(ret);
|
||||
}
|
||||
}
|
||||
|
@ -119,6 +123,7 @@ public class JsrEvents<T extends Annotation, C extends EndpointConfig>
|
|||
Object ret = onBinaryStream.call(websocket,stream);
|
||||
if (ret != null)
|
||||
{
|
||||
LOG.debug("returning: {}",ret);
|
||||
endpoint.sendObject(ret);
|
||||
}
|
||||
}
|
||||
|
@ -159,6 +164,7 @@ public class JsrEvents<T extends Annotation, C extends EndpointConfig>
|
|||
Object ret = onText.call(websocket,text,fin);
|
||||
if (ret != null)
|
||||
{
|
||||
LOG.debug("returning: {}",ret);
|
||||
endpoint.sendObject(ret);
|
||||
}
|
||||
}
|
||||
|
@ -172,6 +178,7 @@ public class JsrEvents<T extends Annotation, C extends EndpointConfig>
|
|||
Object ret = onTextStream.call(websocket,reader);
|
||||
if (ret != null)
|
||||
{
|
||||
LOG.debug("returning: {}",ret);
|
||||
endpoint.sendObject(ret);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureExcep
|
|||
import org.eclipse.jetty.websocket.jsr356.EncoderFactory;
|
||||
import org.eclipse.jetty.websocket.jsr356.InitException;
|
||||
import org.eclipse.jetty.websocket.jsr356.JsrSession;
|
||||
import org.eclipse.jetty.websocket.jsr356.utils.MethodUtils;
|
||||
import org.eclipse.jetty.websocket.jsr356.utils.ReflectUtils;
|
||||
|
||||
public class OnMessageCallable extends JsrCallable
|
||||
|
@ -67,7 +66,7 @@ public class OnMessageCallable extends JsrCallable
|
|||
Param param = params[idxMessageObject];
|
||||
err.append(param.index);
|
||||
err.append(" [").append(param.type).append("] in method: ");
|
||||
err.append(MethodUtils.toString(pojo,method));
|
||||
err.append(ReflectUtils.toString(pojo,method));
|
||||
throw new InvalidSignatureException(err.toString());
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +78,7 @@ public class OnMessageCallable extends JsrCallable
|
|||
StringBuilder err = new StringBuilder();
|
||||
err.append("Unable to find parameter with role [");
|
||||
err.append(description).append("] in method: ");
|
||||
err.append(MethodUtils.toString(pojo,method));
|
||||
err.append(ReflectUtils.toString(pojo,method));
|
||||
throw new InvalidSignatureException(err.toString());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,114 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2013 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.utils;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Collection of common {@link Type} utility methods used during Deployment of the Endpoint
|
||||
*/
|
||||
public class DeploymentTypeUtils
|
||||
{
|
||||
public static Class<?> getPrimitiveClass(Class<?> primitiveType)
|
||||
{
|
||||
return Primitives.getPrimitiveClass(primitiveType);
|
||||
}
|
||||
|
||||
public static Set<Class<?>> getPrimitiveClasses()
|
||||
{
|
||||
return Primitives.getPrimitiveClasses();
|
||||
}
|
||||
|
||||
public static Set<Class<?>> getPrimitives()
|
||||
{
|
||||
return Primitives.getPrimitives();
|
||||
}
|
||||
|
||||
public static boolean isAssignableClass(Class<?> type, Class<?> targetClass)
|
||||
{
|
||||
if ((type == null) || (targetClass == null))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Casting from primitive
|
||||
if (type.isPrimitive())
|
||||
{
|
||||
// Primitive to Class (autoboxing)
|
||||
if (!targetClass.isPrimitive())
|
||||
{
|
||||
// going from primitive to class, make sure it matches
|
||||
Class<?> primitive = Primitives.getPrimitiveType(targetClass);
|
||||
return primitive.equals(type);
|
||||
}
|
||||
|
||||
// Primitive to Primitive
|
||||
|
||||
/**
|
||||
* After reading the javadoc for the various primitive class implementations. It is determined that the appropriate allowable casting from one
|
||||
* primitive to another can be discovered via the existence (or not) of various .*Value() methods.
|
||||
*
|
||||
* The table:
|
||||
*
|
||||
* <pre>
|
||||
* | :From:
|
||||
* :To: | Bool | Byte | Char | Double | Float | Int | Long | Short
|
||||
* ------------------------------------------------------------------
|
||||
* Bool | Y | | | | | | |
|
||||
* Byte | | Y | | Y | Y | Y | Y | Y
|
||||
* Char | | | Y | | | | |
|
||||
* Double | | Y | | Y | Y | Y | Y | Y
|
||||
* Float | | Y | | Y | Y | Y | Y | Y
|
||||
* Int | | Y | | Y | Y | Y | Y | Y
|
||||
* Long | | Y | | Y | Y | Y | Y | Y
|
||||
* Short | | Y | | Y | Y | Y | Y | Y
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
if (Byte.TYPE.equals(type) || Double.TYPE.equals(type) || Float.TYPE.equals(type) || Integer.TYPE.equals(type) || Long.TYPE.equals(type)
|
||||
|| Short.TYPE.equals(type))
|
||||
{
|
||||
return Byte.TYPE.equals(targetClass) || Double.TYPE.equals(targetClass) || Float.TYPE.equals(targetClass) || Integer.TYPE.equals(targetClass)
|
||||
|| Long.TYPE.equals(targetClass) || Short.TYPE.equals(targetClass);
|
||||
}
|
||||
|
||||
// All others are not valid
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (targetClass.isPrimitive())
|
||||
{
|
||||
// Class to Primitive (autoboxing)
|
||||
Class<?> targetPrimitive = Primitives.getPrimitiveType(type);
|
||||
return targetClass.equals(targetPrimitive);
|
||||
}
|
||||
}
|
||||
|
||||
// Basic class check
|
||||
if (type.equals(targetClass))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Basic form
|
||||
return targetClass.isAssignableFrom(type);
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2013 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.utils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public final class MethodUtils
|
||||
{
|
||||
public static String toString(Class<?> pojo, Method method)
|
||||
{
|
||||
return ReflectUtils.toString(pojo,method);
|
||||
}
|
||||
}
|
|
@ -1,131 +0,0 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2013 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.utils;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.FilterReader;
|
||||
import java.io.Reader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.MappedByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import javax.websocket.DeploymentException;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Parameterized;
|
||||
import org.junit.runners.Parameterized.Parameters;
|
||||
|
||||
@RunWith(Parameterized.class)
|
||||
public class DeploymentTypeUtils_IsAssignableTest
|
||||
{
|
||||
private static class Case
|
||||
{
|
||||
Class<?> type;
|
||||
Class<?> targetType;
|
||||
boolean expectedResult;
|
||||
|
||||
public Case(Class<?> type, Class<?> targetType)
|
||||
{
|
||||
this.type = type;
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
public Case[] expecting(boolean expect)
|
||||
{
|
||||
this.expectedResult = expect;
|
||||
return new Case[]
|
||||
{ this };
|
||||
}
|
||||
}
|
||||
|
||||
@Parameters
|
||||
public static Collection<Case[]> data()
|
||||
{
|
||||
List<Case[]> data = new ArrayList<>();
|
||||
|
||||
// Null to anything is false
|
||||
data.add(new Case(null,Object.class).expecting(false));
|
||||
data.add(new Case(null,Integer.class).expecting(false));
|
||||
data.add(new Case(null,String.class).expecting(false));
|
||||
data.add(new Case(null,Integer.TYPE).expecting(false));
|
||||
data.add(new Case(null,Character.TYPE).expecting(false));
|
||||
|
||||
// Anything to null is false
|
||||
data.add(new Case(Object.class,null).expecting(false));
|
||||
data.add(new Case(Integer.class,null).expecting(false));
|
||||
data.add(new Case(String.class,null).expecting(false));
|
||||
data.add(new Case(Integer.TYPE,null).expecting(false));
|
||||
data.add(new Case(Character.TYPE,null).expecting(false));
|
||||
|
||||
// String to Object or String is ok
|
||||
data.add(new Case(String.class,Object.class).expecting(true));
|
||||
data.add(new Case(String.class,String.class).expecting(true));
|
||||
// ... but not the reverse
|
||||
data.add(new Case(Object.class,String.class).expecting(false));
|
||||
|
||||
// Primitive to same Primitive
|
||||
data.add(new Case(Integer.TYPE,Integer.TYPE).expecting(true));
|
||||
data.add(new Case(Float.TYPE,Float.TYPE).expecting(true));
|
||||
data.add(new Case(Byte.TYPE,Byte.TYPE).expecting(true));
|
||||
|
||||
// Primitive to Class of same Type (autoboxing)
|
||||
data.add(new Case(Integer.TYPE,Integer.class).expecting(true));
|
||||
data.add(new Case(Float.TYPE,Float.class).expecting(true));
|
||||
data.add(new Case(Byte.TYPE,Byte.class).expecting(true));
|
||||
|
||||
// Class Primitive to Primitive type (autoboxing)
|
||||
data.add(new Case(Integer.class,Integer.TYPE).expecting(true));
|
||||
data.add(new Case(Float.class,Float.TYPE).expecting(true));
|
||||
data.add(new Case(Byte.class,Byte.TYPE).expecting(true));
|
||||
|
||||
// byte array
|
||||
data.add(new Case(byte[].class,Object.class).expecting(true));
|
||||
data.add(new Case(byte[].class,byte[].class).expecting(true));
|
||||
|
||||
// ByteBuffer
|
||||
data.add(new Case(ByteBuffer.class,ByteBuffer.class).expecting(true));
|
||||
data.add(new Case(MappedByteBuffer.class,ByteBuffer.class).expecting(true));
|
||||
|
||||
// Reader
|
||||
data.add(new Case(Reader.class,Reader.class).expecting(true));
|
||||
data.add(new Case(BufferedReader.class,Reader.class).expecting(true));
|
||||
data.add(new Case(FilterReader.class,Reader.class).expecting(true));
|
||||
|
||||
return data;
|
||||
}
|
||||
private Case testcase;
|
||||
|
||||
public DeploymentTypeUtils_IsAssignableTest(Case testcase)
|
||||
{
|
||||
this.testcase = testcase;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsAssignable() throws DeploymentException
|
||||
{
|
||||
boolean actual = DeploymentTypeUtils.isAssignableClass(testcase.type,testcase.targetType);
|
||||
Assert.assertThat("isAssignable(" + testcase.type + ", " + testcase.targetType + ")",actual,is(testcase.expectedResult));
|
||||
}
|
||||
}
|
|
@ -50,6 +50,7 @@ import org.eclipse.jetty.websocket.client.io.ConnectionManager;
|
|||
import org.eclipse.jetty.websocket.client.io.UpgradeListener;
|
||||
import org.eclipse.jetty.websocket.client.masks.Masker;
|
||||
import org.eclipse.jetty.websocket.client.masks.RandomMasker;
|
||||
import org.eclipse.jetty.websocket.client.masks.ZeroMasker;
|
||||
import org.eclipse.jetty.websocket.common.SessionFactory;
|
||||
import org.eclipse.jetty.websocket.common.WebSocketSessionFactory;
|
||||
import org.eclipse.jetty.websocket.common.events.EventDriver;
|
||||
|
@ -87,7 +88,12 @@ public class WebSocketClient extends ContainerLifeCycle
|
|||
this.sslContextFactory = sslContextFactory;
|
||||
this.policy = WebSocketPolicy.newClientPolicy();
|
||||
this.extensionRegistry = new WebSocketExtensionFactory(policy,bufferPool);
|
||||
this.masker = new RandomMasker();
|
||||
if(LOG.isDebugEnabled()) {
|
||||
LOG.debug("Using ZeroMasker (DEBUG)");
|
||||
this.masker = new ZeroMasker();
|
||||
} else {
|
||||
this.masker = new RandomMasker();
|
||||
}
|
||||
this.eventDriverFactory = new EventDriverFactory(policy);
|
||||
this.sessionFactory = new WebSocketSessionFactory();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
//
|
||||
// ========================================================================
|
||||
// Copyright (c) 1995-2013 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.common.util;
|
||||
|
||||
/**
|
||||
* Collection of utility methods for Text content
|
||||
*/
|
||||
public final class TextUtil
|
||||
{
|
||||
/**
|
||||
* Create a hint of what the text is like.
|
||||
* <p>
|
||||
* Used by logging and error messages to get a hint of what the text is like.
|
||||
*
|
||||
* @param text
|
||||
* the text to abbreviate, quote, and generally give you a hint of what the value is.
|
||||
* @return the abbreviated text
|
||||
*/
|
||||
public static String hint(String text)
|
||||
{
|
||||
if (text == null)
|
||||
{
|
||||
return "<null>";
|
||||
}
|
||||
return '"' + maxStringLength(30,text) + '"';
|
||||
}
|
||||
|
||||
/**
|
||||
* Smash a long string to fit within the max string length, by taking the middle section of the string and replacing them with an ellipsis "..."
|
||||
* <p>
|
||||
*
|
||||
* <pre>
|
||||
* Examples:
|
||||
* .maxStringLength( 9, "Eatagramovabits") == "Eat...its"
|
||||
* .maxStringLength(10, "Eatagramovabits") == "Eat...bits"
|
||||
* .maxStringLength(11, "Eatagramovabits") == "Eata...bits"
|
||||
* </pre>
|
||||
*
|
||||
* @param max
|
||||
* the maximum size of the string (minimum size supported is 9)
|
||||
* @param raw
|
||||
* the raw string to smash
|
||||
* @return the ellipsis'd version of the string.
|
||||
*/
|
||||
public static String maxStringLength(int max, String raw)
|
||||
{
|
||||
int length = raw.length();
|
||||
if (length <= max)
|
||||
{
|
||||
// already short enough
|
||||
return raw;
|
||||
}
|
||||
|
||||
if (max < 9)
|
||||
{
|
||||
// minimum supported
|
||||
return raw.substring(0,max);
|
||||
}
|
||||
|
||||
StringBuilder ret = new StringBuilder();
|
||||
int startLen = (int)Math.round((double)max / (double)3);
|
||||
ret.append(raw.substring(0,startLen));
|
||||
ret.append("...");
|
||||
ret.append(raw.substring(length - (max - startLen - 3)));
|
||||
|
||||
return ret.toString();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue