Working EventMethod/EventMethods/EventMethodsCache with tests

This commit is contained in:
Joakim Erdfelt 2012-06-27 17:04:37 -07:00
parent 270a04ebd0
commit 08796a7b37
11 changed files with 679 additions and 70 deletions

View File

@ -0,0 +1,106 @@
package org.eclipse.jetty.websocket.annotations;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class EventMethod
{
public static final EventMethod NOOP = new EventMethod();
private static final Logger LOG = Log.getLogger(EventMethod.class);
private static Object[] dropFirstArg(Object[] args)
{
if (args.length == 1)
{
return null;
}
Object ret[] = new Object[args.length - 1];
System.arraycopy(args,1,ret,0,ret.length);
return ret;
}
public static EventMethod findAnnotatedMethod(Object pojo, Class<? extends Annotation> annoClass, Class<?>... paramTypes)
{
Class<?>[] possibleParams = new Class<?>[paramTypes.length];
System.arraycopy(paramTypes,0,possibleParams,0,possibleParams.length);
for (Method method : pojo.getClass().getDeclaredMethods())
{
if (method.getAnnotation(annoClass) == null)
{
// skip, not interested
continue;
}
}
return NOOP;
}
private Class<?> pojo;
private Method method;
private Class<?>[] paramTypes;
private EventMethod()
{
this.method = null;
}
public EventMethod(Class<?> pojo, Method method)
{
this.pojo = pojo;
this.paramTypes = method.getParameterTypes();
this.method = method;
}
public EventMethod(Class<?> pojo, String methodName, Class<?>... paramTypes)
{
try
{
this.pojo = pojo;
this.paramTypes = paramTypes;
this.method = pojo.getClass().getMethod(methodName,paramTypes);
}
catch (NoSuchMethodException | SecurityException e)
{
LOG.debug("Cannot use method {}({}): {}",methodName,paramTypes,e.getMessage(),e);
this.method = null;
}
}
public void call(Object obj, Object... args)
{
if ((this.pojo == null) || (this.method == null))
{
return; // no call event method determined
}
if (obj == null)
{
LOG.warn("Cannot call {} on null object",this.method);
return;
}
if (args.length > paramTypes.length)
{
Object trimArgs[] = dropFirstArg(args);
call(trimArgs);
return;
}
if (args.length < paramTypes.length)
{
throw new IllegalArgumentException("Call arguments length must always be greater than or equal to captured args length");
}
try
{
this.method.invoke(obj,args);
}
catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e)
{
LOG.warn("Cannot call method {} on {} with {}",method,pojo,args,e);
}
}
}

View File

@ -0,0 +1,74 @@
package org.eclipse.jetty.websocket.annotations;
/**
* A representation of the methods available to call for a particular class.
* <p>
* This class used to cache the method lookups via the {@link EventMethodsCache}
*/
public class EventMethods
{
private Class<?> pojoClass;
private boolean isAnnotated = false;
public EventMethod onConnect = EventMethod.NOOP;
public EventMethod onClose = EventMethod.NOOP;
public EventMethod onBinary = EventMethod.NOOP;
public EventMethod onText = EventMethod.NOOP;
public EventMethod onFrame = EventMethod.NOOP;
public EventMethod onException = EventMethod.NOOP;
public EventMethods(Class<?> pojoClass, boolean annotated)
{
this.pojoClass = pojoClass;
this.isAnnotated = annotated;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
EventMethods other = (EventMethods)obj;
if (pojoClass == null)
{
if (other.pojoClass != null)
{
return false;
}
}
else if (!pojoClass.getName().equals(other.pojoClass.getName()))
{
return false;
}
return true;
}
public Class<?> getPojoClass()
{
return pojoClass;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = (prime * result) + ((pojoClass == null)?0:pojoClass.getName().hashCode());
return result;
}
public boolean isAnnotated()
{
return isAnnotated;
}
}

View File

@ -0,0 +1,282 @@
package org.eclipse.jetty.websocket.annotations;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.websocket.api.InvalidWebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketException;
import org.eclipse.jetty.websocket.api.WebSocketListener;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.frames.BinaryFrame;
import org.eclipse.jetty.websocket.frames.CloseFrame;
import org.eclipse.jetty.websocket.frames.ControlFrame;
import org.eclipse.jetty.websocket.frames.DataFrame;
import org.eclipse.jetty.websocket.frames.PingFrame;
import org.eclipse.jetty.websocket.frames.PongFrame;
import org.eclipse.jetty.websocket.frames.TextFrame;
public class EventMethodsCache
{
@SuppressWarnings("serial")
private static class ParamList extends ArrayList<Class<?>[]>
{
public void addParams(Class<?>... paramTypes)
{
this.add(paramTypes);
}
}
/**
* Parameter list for &#064;OnWebSocketBinary
*/
private static final ParamList validBinaryParams;
/**
* Parameter list for &#064;OnWebSocketConnect
*/
private static final ParamList validConnectParams;
private static final ParamList validCloseParams;
private static final ParamList validFrameParams;
private static final ParamList validTextParams;
static
{
validBinaryParams = new ParamList();
validBinaryParams.addParams(ByteBuffer.class);
validBinaryParams.addParams(byte[].class,int.class,int.class);
validBinaryParams.addParams(WebSocketConnection.class,ByteBuffer.class);
validBinaryParams.addParams(WebSocketConnection.class,byte[].class,int.class,int.class);
validConnectParams = new ParamList();
validConnectParams.addParams(WebSocketConnection.class);
validCloseParams = new ParamList();
validCloseParams.addParams(int.class,String.class);
validCloseParams.addParams(WebSocketConnection.class,int.class,String.class);
validTextParams = new ParamList();
validTextParams.addParams(String.class);
validTextParams.addParams(WebSocketConnection.class,String.class);
validFrameParams = new ParamList();
validFrameParams.addParams(BaseFrame.class);
validFrameParams.addParams(BinaryFrame.class);
validFrameParams.addParams(CloseFrame.class);
validFrameParams.addParams(ControlFrame.class);
validFrameParams.addParams(DataFrame.class);
validFrameParams.addParams(PingFrame.class);
validFrameParams.addParams(PongFrame.class);
validFrameParams.addParams(TextFrame.class);
validFrameParams.addParams(WebSocketConnection.class,BaseFrame.class);
validFrameParams.addParams(WebSocketConnection.class,BinaryFrame.class);
validFrameParams.addParams(WebSocketConnection.class,CloseFrame.class);
validFrameParams.addParams(WebSocketConnection.class,ControlFrame.class);
validFrameParams.addParams(WebSocketConnection.class,DataFrame.class);
validFrameParams.addParams(WebSocketConnection.class,PingFrame.class);
validFrameParams.addParams(WebSocketConnection.class,PongFrame.class);
validFrameParams.addParams(WebSocketConnection.class,TextFrame.class);
}
private ConcurrentHashMap<Class<?>, EventMethods> cache;
public EventMethodsCache()
{
cache = new ConcurrentHashMap<>();
}
private void assertUnset(EventMethod event, Class<? extends Annotation> annoClass, Class<?> pojo, Method method)
{
if (event == EventMethod.NOOP)
{
return;
}
}
private void assertValidParams(Class<?> pojo, Method method, Class<? extends Annotation> annoClass, ParamList validParams)
{
boolean valid = false;
Class<?> actual[] = method.getParameterTypes();
for (Class<?> params[] : validParams)
{
if (isSameParameters(actual,params))
{
valid = true;
break;
}
}
if (!valid)
{
// Build big detailed exception to help the developer
StringBuilder err = new StringBuilder();
err.append("Invalid declaration of ");
err.append(method);
err.append(StringUtil.__LINE_SEPARATOR);
err.append("Acceptable method declarations for @");
err.append(annoClass.getSimpleName());
err.append(" are:");
for (Class<?> params[] : validParams)
{
err.append(StringUtil.__LINE_SEPARATOR);
err.append("public void ").append(method.getName());
err.append('(');
boolean delim = false;
for (Class<?> type : params)
{
if (delim)
{
err.append(',');
}
err.append(' ');
err.append(type.getName());
if (type.isArray())
{
err.append("[]");
}
delim = true;
}
err.append(')');
}
throw new InvalidWebSocketException(err.toString());
}
}
/**
* Perform the basic discovery mechanism for WebSocket events from the provided pojo.
*
* @param pojo
* the pojo to scan
* @return the discovered event methods
* @throws InvalidWebSocketException
*/
private EventMethods discoverMethods(Class<?> pojo) throws InvalidWebSocketException
{
if (WebSocketListener.class.isInstance(pojo))
{
return scanListenerMethods(pojo);
}
WebSocket anno = pojo.getAnnotation(WebSocket.class);
if (anno == null)
{
throw new InvalidWebSocketException(pojo.getName() + " does not implement " + WebSocketListener.class.getName() + " or use the @"
+ WebSocket.class.getName() + " annotation");
}
return scanAnnotatedMethods(pojo);
}
public EventMethods getMethods(Class<?> pojo) throws InvalidWebSocketException
{
EventMethods methods = cache.get(pojo);
if (methods == null)
{
methods = discoverMethods(pojo);
cache.put(pojo,methods);
}
return methods;
}
private boolean isSameParameters(Class<?>[] actual, Class<?>[] params)
{
if(actual.length != params.length) {
// skip
return false;
}
int len = params.length;
for(int i=0; i<len; i++) {
if(!actual[i].equals(params[i])) {
return false; // not valid
}
}
return true;
}
/**
* Register a pojo with the cache.
*
* @param pojo
* the pojo to register with the cache.
* @throws InvalidWebSocketException
* if the pojo does not conform to a WebSocket implementation.
*/
public void register(Class<?> pojo) throws InvalidWebSocketException
{
discoverMethods(pojo);
}
private EventMethods scanAnnotatedMethods(Class<?> pojo)
{
EventMethods events = new EventMethods(pojo,true);
for (Method method : pojo.getDeclaredMethods())
{
if (method.getAnnotation(OnWebSocketConnect.class) != null)
{
assertUnset(events.onConnect,OnWebSocketConnect.class,pojo,method);
assertValidParams(pojo,method,OnWebSocketConnect.class,validConnectParams);
events.onConnect = new EventMethod(pojo,method);
continue;
}
if (method.getAnnotation(OnWebSocketBinary.class) != null)
{
assertUnset(events.onBinary,OnWebSocketBinary.class,pojo,method);
assertValidParams(pojo,method,OnWebSocketBinary.class,validBinaryParams);
events.onBinary = new EventMethod(pojo,method);
continue;
}
if (method.getAnnotation(OnWebSocketClose.class) != null)
{
assertUnset(events.onClose,OnWebSocketClose.class,pojo,method);
assertValidParams(pojo,method,OnWebSocketClose.class,validCloseParams);
events.onClose = new EventMethod(pojo,method);
continue;
}
if (method.getAnnotation(OnWebSocketText.class) != null)
{
assertUnset(events.onText,OnWebSocketText.class,pojo,method);
assertValidParams(pojo,method,OnWebSocketText.class,validTextParams);
events.onText = new EventMethod(pojo,method);
continue;
}
if (method.getAnnotation(OnWebSocketFrame.class) != null)
{
assertUnset(events.onFrame,OnWebSocketFrame.class,pojo,method);
assertValidParams(pojo,method,OnWebSocketFrame.class,validFrameParams);
events.onFrame = new EventMethod(pojo,method);
continue;
}
// Not a tagged method we are interested in, ignore
}
return events;
}
private EventMethods scanListenerMethods(Class<?> pojo)
{
EventMethods events = new EventMethods(pojo,false);
// This is a WebSocketListener object
events.onConnect = new EventMethod(pojo,"onWebSocketConnect",WebSocketConnection.class);
events.onClose = new EventMethod(pojo,"onWebSocketClose",Integer.TYPE,String.class);
events.onBinary = new EventMethod(pojo,"onWebSocketBinary",byte[].class,Integer.TYPE,Integer.TYPE);
events.onText = new EventMethod(pojo,"onWebSocketText",WebSocketConnection.class);
events.onException = new EventMethod(pojo,"onWebSocketException",WebSocketException.class);
return events;
}
}

View File

@ -19,5 +19,7 @@ public @interface WebSocket
int maxBufferSize() default 8192;
int maxIdleTime() default 300000;
int maxTextSize() default 8192;
}

View File

@ -0,0 +1,27 @@
package org.eclipse.jetty.websocket.api;
import org.eclipse.jetty.websocket.annotations.WebSocket;
/**
* Indicating that the provided Class is not a valid WebSocket as defined by the API.
* <p>
* A valid WebSocket should do one of the following:
* <ul>
* <li>Implement {@link WebSocketListener}</li>
* <li>Extend {@link WebSocketAdapter}</li>
* <li>Declare the {@link WebSocket &#064;WebSocket} annotation on the type</li>
* </ul>
*/
@SuppressWarnings("serial")
public class InvalidWebSocketException extends WebSocketException
{
public InvalidWebSocketException(String message)
{
super(message);
}
public InvalidWebSocketException(String message, Throwable cause)
{
super(message,cause);
}
}

View File

@ -1,7 +1,10 @@
package org.eclipse.jetty.websocket.api;
import org.eclipse.jetty.websocket.annotations.EventMethods;
import org.eclipse.jetty.websocket.annotations.EventMethodsCache;
import org.eclipse.jetty.websocket.annotations.WebSocket;
import org.eclipse.jetty.websocket.frames.BaseFrame;
import org.eclipse.jetty.websocket.parser.Parser;
/**
* Responsible for routing the internally generated events destined for a specific WebSocket instance to whatever choice of development style the developer has
@ -11,20 +14,38 @@ import org.eclipse.jetty.websocket.frames.BaseFrame;
* <p>
* There will be an instance of the WebSocketEventDriver per connection.
*/
public class WebSocketEventDriver
public class WebSocketEventDriver implements Parser.Listener
{
private Object websocket;
private WebSocketPolicy policy;
private WebSocketConnection connection;
private EventMethods events;
/**
* Establish the driver for the Websocket POJO
*
* @param websocket
*/
public WebSocketEventDriver(Object websocket)
public WebSocketEventDriver(EventMethodsCache methodsCache, WebSocketPolicy policy, Object websocket)
{
this.policy = policy;
this.websocket = websocket;
// TODO Discover and bind what routing is available in the POJO
this.events = methodsCache.getMethods(websocket.getClass());
if (events.isAnnotated())
{
WebSocket anno = websocket.getClass().getAnnotation(WebSocket.class);
// Setup the policy
policy.setBufferSize(anno.maxBufferSize());
policy.setMaxBinaryMessageSize(anno.maxBinarySize());
policy.setMaxTextMessageSize(anno.maxTextSize());
policy.setMaxIdleTime(anno.maxIdleTime());
}
}
public WebSocketPolicy getPolicy()
{
return policy;
}
/**
@ -42,15 +63,7 @@ public class WebSocketEventDriver
*/
public void onConnect()
{
// TODO Auto-generated method stub
}
/**
* Internal entry point for connection disconnected
*/
public void onDisconnect()
{
// TODO Auto-generated method stub
events.onConnect.call(websocket,connection);
}
/**
@ -59,9 +72,18 @@ public class WebSocketEventDriver
* @param frame
* the frame that appeared
*/
@Override
public void onFrame(BaseFrame frame)
{
// TODO Auto-generated method stub
}
@Override
public void onWebSocketException(WebSocketException e)
{
// TODO Auto-generated method stub
}
/**

View File

@ -84,6 +84,17 @@ public class WebSocketPolicy
}
}
public WebSocketPolicy clonePolicy()
{
WebSocketPolicy clone = new WebSocketPolicy(this.behavior);
clone.bufferSize = this.bufferSize;
clone.masker = this.masker;
clone.maxBinaryMessageSize = this.maxBinaryMessageSize;
clone.maxIdleTime = this.maxIdleTime;
clone.maxTextMessageSize = this.maxTextMessageSize;
return clone;
}
public WebSocketBehavior getBehavior()
{
return behavior;

View File

@ -0,0 +1,95 @@
package org.eclipse.jetty.websocket.annotations;
import static org.hamcrest.Matchers.*;
import org.junit.Assert;
import org.junit.Test;
public class EventMethodsCacheTest
{
private void assertHasEventMethod(String message, EventMethod actual)
{
Assert.assertNotSame(message + "Event method should have been discovered",actual,EventMethod.NOOP);
}
private void assertNoEventMethod(String message, EventMethod actual)
{
Assert.assertEquals(message + "Event method should have been NOOP",actual,EventMethod.NOOP);
}
/**
* Test Case for no exceptions and 3 methods
*/
@Test
public void testDiscoverMyEchoSocket()
{
EventMethodsCache cache = new EventMethodsCache();
EventMethods methods = cache.getMethods(MyEchoSocket.class);
Assert.assertThat("EventMethods for MyEchoSocket",methods,notNullValue());
assertNoEventMethod("MyEchoSocket.onBinary",methods.onBinary);
assertHasEventMethod("MyEchoSocket.onClose",methods.onClose);
assertHasEventMethod("MyEchoSocket.onConnect",methods.onConnect);
assertNoEventMethod("MyEchoSocket.onException",methods.onException);
assertNoEventMethod("MyEchoSocket.onFrame",methods.onFrame);
assertHasEventMethod("MyEchoSocket.onText",methods.onText);
}
/**
* Test Case for no exceptions and 1 method
*/
@Test
public void testDiscoverMyStatelessEchoSocket()
{
EventMethodsCache cache = new EventMethodsCache();
EventMethods methods = cache.getMethods(MyStatelessEchoSocket.class);
Assert.assertThat("EventMethods for MyStatelessEchoSocket",methods,notNullValue());
assertNoEventMethod("MyStatelessEchoSocket.onBinary",methods.onBinary);
assertNoEventMethod("MyStatelessEchoSocket.onClose",methods.onClose);
assertNoEventMethod("MyStatelessEchoSocket.onConnect",methods.onConnect);
assertNoEventMethod("MyStatelessEchoSocket.onException",methods.onException);
assertNoEventMethod("MyStatelessEchoSocket.onFrame",methods.onFrame);
assertHasEventMethod("MyStatelessEchoSocket.onText",methods.onText);
}
/**
* Test Case for no exceptions and no methods
*/
@Test
public void testDiscoverNoop()
{
EventMethodsCache cache = new EventMethodsCache();
EventMethods methods = cache.getMethods(NoopSocket.class);
Assert.assertThat("Methods for NoopSocket",methods,notNullValue());
assertNoEventMethod("NoopSocket.onBinary",methods.onBinary);
assertNoEventMethod("NoopSocket.onClose",methods.onClose);
assertNoEventMethod("NoopSocket.onConnect", methods.onConnect);
assertNoEventMethod("NoopSocket.onException",methods.onException);
assertNoEventMethod("NoopSocket.onFrame",methods.onFrame);
assertNoEventMethod("NoopSocket.onText",methods.onText);
}
/**
* Test Case for no exceptions and 3 methods
*/
@Test
public void testDiscoverOnFrame()
{
EventMethodsCache cache = new EventMethodsCache();
EventMethods methods = cache.getMethods(FrameSocket.class);
Assert.assertThat("EventMethods for MyEchoSocket",methods,notNullValue());
assertNoEventMethod("MyEchoSocket.onBinary",methods.onBinary);
assertNoEventMethod("MyEchoSocket.onClose",methods.onClose);
assertNoEventMethod("MyEchoSocket.onConnect",methods.onConnect);
assertNoEventMethod("MyEchoSocket.onException",methods.onException);
assertHasEventMethod("MyEchoSocket.onFrame",methods.onFrame);
assertNoEventMethod("MyEchoSocket.onText",methods.onText);
}
}

View File

@ -0,0 +1,13 @@
package org.eclipse.jetty.websocket.annotations;
import org.eclipse.jetty.websocket.frames.BaseFrame;
@WebSocket
public class FrameSocket
{
@OnWebSocketFrame
public void frameMe(BaseFrame frame)
{
/* ignore */
}
}

View File

@ -1,44 +0,0 @@
package org.eclipse.jetty.websocket.annotations;
import org.eclipse.jetty.websocket.api.LocalWebSocketConnection;
import org.eclipse.jetty.websocket.api.StatusCode;
import org.eclipse.jetty.websocket.api.WebSocketConnection;
import org.eclipse.jetty.websocket.api.WebSocketEventDriver;
import org.eclipse.jetty.websocket.frames.CloseFrame;
import org.eclipse.jetty.websocket.frames.TextFrame;
import org.junit.Test;
public class WebSocketAnnotationTest
{
/**
* Test Case for no exceptions
*/
@Test
public void testCapture()
{
WebSocketEventDriver driver = new WebSocketEventDriver(new NoopSocket());
WebSocketConnection conn = new LocalWebSocketConnection();
driver.setConnection(conn);
driver.onConnect();
driver.onFrame(new TextFrame("Hello World"));
driver.onFrame(new CloseFrame(StatusCode.NORMAL));
driver.onDisconnect();
}
/**
* Test Case for no exceptions
*/
@Test
public void testNoop()
{
WebSocketEventDriver driver = new WebSocketEventDriver(new NoopSocket());
WebSocketConnection conn = new LocalWebSocketConnection();
driver.setConnection(conn);
driver.onConnect();
driver.onFrame(new TextFrame("Hello World"));
driver.onFrame(new CloseFrame(StatusCode.NORMAL));
driver.onDisconnect();
}
}

View File

@ -32,6 +32,8 @@ import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.annotations.EventMethodsCache;
import org.eclipse.jetty.websocket.annotations.WebSocket;
import org.eclipse.jetty.websocket.api.ExtensionConfig;
import org.eclipse.jetty.websocket.api.WebSocketEventDriver;
import org.eclipse.jetty.websocket.api.WebSocketPolicy;
@ -65,11 +67,14 @@ public class WebSocketServerFactory extends AbstractLifeCycle
}
private final String supportedVersions;
private WebSocketPolicy policy;
private WebSocketPolicy basePolicy;
private WebSocketCreator creator;
private EventMethodsCache methodsCache;
public WebSocketServerFactory(WebSocketPolicy policy)
{
this.policy = policy;
this.basePolicy = policy;
this.methodsCache = new EventMethodsCache();
// Create supportedVersions
List<Integer> versions = new ArrayList<>();
@ -109,7 +114,8 @@ public class WebSocketServerFactory extends AbstractLifeCycle
// TODO: discover type, create proxy
// Send the upgrade
WebSocketEventDriver websocket = new WebSocketEventDriver(websocketPojo);
WebSocketPolicy objPolicy = this.basePolicy.clonePolicy();
WebSocketEventDriver websocket = new WebSocketEventDriver(methodsCache,objPolicy,websocketPojo);
return upgrade(sockreq,sockresp,websocket);
}
@ -134,8 +140,7 @@ public class WebSocketServerFactory extends AbstractLifeCycle
public WebSocketCreator getCreator()
{
// TODO: implement
return null;
return this.creator;
}
/**
@ -147,13 +152,15 @@ public class WebSocketServerFactory extends AbstractLifeCycle
}
/**
* Get the policy in use for WebSockets.
* Get the base policy in use for WebSockets.
* <p>
* Note: individual WebSocket implementations can override some of the values in here by using the {@link WebSocket &#064;WebSocket} annotation.
*
* @return
* @return the base policy
*/
public WebSocketPolicy getPolicy()
{
return policy;
return basePolicy;
}
public List<Extension> initExtensions(List<ExtensionConfig> requested)
@ -179,12 +186,26 @@ public class WebSocketServerFactory extends AbstractLifeCycle
public boolean isUpgradeRequest(HttpServletRequest request, HttpServletResponse response)
{
// TODO: other checks against the spec?
String upgrade = request.getHeader("Upgrade");
if (upgrade == null)
{
// Quietly fail
return false;
}
if (!"websocket".equalsIgnoreCase(upgrade))
{
LOG.warn("Not a 'Upgrade: WebSocket' (was [Upgrade: " + upgrade + "])");
return false;
}
if (!"HTTP/1.1".equals(request.getProtocol()))
{
throw new IllegalStateException("Not a 'HTTP/1.1' request");
LOG.warn("Not a 'HTTP/1.1' request (was [" + request.getProtocol() + "])");
return false;
}
return ("websocket".equalsIgnoreCase(request.getHeader("Upgrade")));
return true;
}
private Extension newExtension(String name)
@ -226,7 +247,7 @@ public class WebSocketServerFactory extends AbstractLifeCycle
public void register(Class<?> websocketClass)
{
// TODO: implement
methodsCache.register(websocketClass);
}
protected boolean removeConnection(AsyncWebSocketConnection connection)
@ -236,7 +257,7 @@ public class WebSocketServerFactory extends AbstractLifeCycle
public void setCreator(WebSocketCreator creator)
{
// TODO: implement
this.creator = creator;
}
/**
@ -287,7 +308,7 @@ public class WebSocketServerFactory extends AbstractLifeCycle
HttpConnection http = HttpConnection.getCurrentConnection();
AsyncEndPoint endp = http.getEndPoint();
Executor executor = http.getConnector().findExecutor();
final AsyncWebSocketConnection connection = new AsyncWebSocketConnection(endp,executor,policy);
final AsyncWebSocketConnection connection = new AsyncWebSocketConnection(endp,executor,websocket.getPolicy());
endp.setAsyncConnection(connection);
// Notify POJO of connection