JSR-356 - Cleaning up sendObject(Object) behavior between Basic & Async

This commit is contained in:
Joakim Erdfelt 2013-07-12 11:45:51 -07:00
parent 5667928921
commit 5d45486b8d
11 changed files with 370 additions and 462 deletions

View File

@ -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
}
}

View File

@ -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)
{

View File

@ -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;
}
}

View File

@ -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());
}

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}

View File

@ -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();
}

View File

@ -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();
}
}