JSR-356 - Fixing @OnMessage message format/decoder detection

This commit is contained in:
Joakim Erdfelt 2013-07-11 11:00:23 -07:00
parent 9a332cf51d
commit 495d2bcd74
19 changed files with 627 additions and 149 deletions

View File

@ -21,17 +21,16 @@ package org.eclipse.jetty.websocket.jsr356.annotations;
import java.lang.annotation.Annotation;
import java.util.LinkedList;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata;
import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadataSet;
import org.eclipse.jetty.websocket.jsr356.metadata.EncoderMetadataSet;
import org.eclipse.jetty.websocket.jsr356.metadata.EndpointMetadata;
import org.eclipse.jetty.websocket.jsr356.utils.ReflectUtils;
/**
* Static reference to a specific annotated classes metadata.
@ -104,37 +103,9 @@ public abstract class AnnotatedEndpointMetadata<T extends Annotation, C extends
public void customizeParamsOnMessage(LinkedList<IJsrParamId> params)
{
for (Class<? extends Decoder> decoder : getDecoders().getList())
for (DecoderMetadata metadata : decoders)
{
if (Decoder.Text.class.isAssignableFrom(decoder))
{
Class<?> type = ReflectUtils.findGenericClassFor(decoder,Decoder.Text.class);
params.add(new JsrParamIdTextDecoder(decoder,type));
continue;
}
if (Decoder.TextStream.class.isAssignableFrom(decoder))
{
Class<?> type = ReflectUtils.findGenericClassFor(decoder,Decoder.TextStream.class);
params.add(new JsrParamIdTextDecoder(decoder,type));
continue;
}
if (Decoder.Binary.class.isAssignableFrom(decoder))
{
Class<?> type = ReflectUtils.findGenericClassFor(decoder,Decoder.Binary.class);
params.add(new JsrParamIdBinaryDecoder(decoder,type));
continue;
}
if (Decoder.BinaryStream.class.isAssignableFrom(decoder))
{
Class<?> type = ReflectUtils.findGenericClassFor(decoder,Decoder.BinaryStream.class);
params.add(new JsrParamIdBinaryDecoder(decoder,type));
continue;
}
throw new IllegalStateException("Invalid Decoder: " + decoder);
params.add(new JsrParamIdDecoder(metadata));
}
}

View File

@ -54,17 +54,19 @@ public class AnnotatedEndpointScanner<T extends Annotation, C extends EndpointCo
paramsOnError = new LinkedList<>();
paramsOnMessage = new LinkedList<>();
paramsOnOpen.add(JsrParamIdOnOpen.INSTANCE);
metadata.customizeParamsOnOpen(paramsOnOpen);
paramsOnClose.add(JsrParamIdOnClose.INSTANCE);
metadata.customizeParamsOnClose(paramsOnClose);
paramsOnError.add(JsrParamIdOnError.INSTANCE);
metadata.customizeParamsOnError(paramsOnError);
paramsOnOpen.add(JsrParamIdOnOpen.INSTANCE);
metadata.customizeParamsOnClose(paramsOnClose);
paramsOnClose.add(JsrParamIdOnClose.INSTANCE);
metadata.customizeParamsOnError(paramsOnError);
paramsOnError.add(JsrParamIdOnError.INSTANCE);
metadata.customizeParamsOnMessage(paramsOnMessage);
paramsOnMessage.add(JsrParamIdBinary.INSTANCE);
paramsOnMessage.add(JsrParamIdText.INSTANCE);
paramsOnMessage.add(JsrParamIdPong.INSTANCE);
metadata.customizeParamsOnMessage(paramsOnMessage);
}
private void assertNotDuplicate(JsrCallable callable, Class<? extends Annotation> methodAnnotationClass, Class<?> pojo, Method method)

View File

@ -1,53 +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.annotations;
import javax.websocket.Decoder;
import javax.websocket.OnMessage;
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
/**
* Param handling for Binary &#064;{@link OnMessage} parameters declared as {@link Decoder}s of type {@link Decoder.Binary} or {@link Decoder.BinaryStream}
*/
public class JsrParamIdBinaryDecoder extends JsrParamIdOnMessage implements IJsrParamId
{
private final Class<? extends Decoder> decoder;
private final Class<?> supportedType;
public JsrParamIdBinaryDecoder(Class<? extends Decoder> decoder, Class<?> supportedType)
{
this.decoder = decoder;
this.supportedType = supportedType;
}
@Override
public boolean process(Param param, JsrCallable callable) throws InvalidSignatureException
{
if (param.type.isAssignableFrom(supportedType))
{
assertPartialMessageSupportDisabled(param,callable);
param.bind(Role.MESSAGE_BINARY);
callable.setDecoderClass(decoder);
return true;
}
return false;
}
}

View File

@ -0,0 +1,78 @@
//
// ========================================================================
// 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.annotations;
import javax.websocket.Decoder;
import javax.websocket.OnMessage;
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata;
/**
* Param handling for Text or Binary &#064;{@link OnMessage} parameters declared as {@link Decoder}s
*/
public class JsrParamIdDecoder extends JsrParamIdOnMessage implements IJsrParamId
{
private final DecoderMetadata metadata;
public JsrParamIdDecoder(DecoderMetadata metadata)
{
this.metadata = metadata;
}
@Override
public boolean process(Param param, JsrCallable callable) throws InvalidSignatureException
{
if (param.type.isAssignableFrom(metadata.getObjectType()))
{
assertPartialMessageSupportDisabled(param,callable);
switch (metadata.getMessageType())
{
case TEXT:
if (metadata.isStreamed())
{
param.bind(Role.MESSAGE_TEXT_STREAM);
}
else
{
param.bind(Role.MESSAGE_TEXT);
}
break;
case BINARY:
if (metadata.isStreamed())
{
param.bind(Role.MESSAGE_BINARY_STREAM);
}
else
{
param.bind(Role.MESSAGE_BINARY);
}
break;
case PONG:
param.bind(Role.MESSAGE_PONG);
break;
}
callable.setDecoderClass(metadata.getCoderClass());
return true;
}
return false;
}
}

View File

@ -1,53 +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.annotations;
import javax.websocket.Decoder;
import javax.websocket.OnMessage;
import org.eclipse.jetty.websocket.common.events.annotated.InvalidSignatureException;
import org.eclipse.jetty.websocket.jsr356.annotations.Param.Role;
/**
* Param handling for Text &#064;{@link OnMessage} parameters declared as {@link Decoder}s of type {@link Decoder.Text} or {@link Decoder.TextStream}
*/
public class JsrParamIdTextDecoder extends JsrParamIdOnMessage implements IJsrParamId
{
private final Class<? extends Decoder> decoder;
private final Class<?> supportedType;
public JsrParamIdTextDecoder(Class<? extends Decoder> decoder, Class<?> supportedType)
{
this.decoder = decoder;
this.supportedType = supportedType;
}
@Override
public boolean process(Param param, JsrCallable callable) throws InvalidSignatureException
{
if (param.type.isAssignableFrom(supportedType))
{
assertPartialMessageSupportDisabled(param,callable);
param.bind(Role.MESSAGE_TEXT_STREAM); // TODO: is this sane? for Text & TextStream ?
callable.setDecoderClass(decoder);
return true;
}
return false;
}
}

View File

@ -28,6 +28,7 @@ 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
{
@ -119,7 +120,8 @@ public class OnMessageCallable extends JsrCallable
if (idxMessageObject < 0)
{
StringBuilder err = new StringBuilder();
err.append("A message type must be specified [TEXT, BINARY, DECODER, or PONG]");
err.append("A message type must be specified [TEXT, BINARY, DECODER, or PONG] : ");
err.append(ReflectUtils.toString(pojo,method));
throw new InvalidSignatureException(err.toString());
}
}

View File

@ -43,6 +43,9 @@ public class AnnotatedClientEndpointMetadata extends AnnotatedEndpointMetadata<C
this.endpoint = anno;
this.config = new AnnotatedClientEndpointConfig(anno);
getDecoders().addAll(anno.decoders());
getEncoders().addAll(anno.encoders());
}
@Override

View File

@ -0,0 +1,57 @@
//
// ========================================================================
// 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.annotations;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.ClientEndpoint;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import org.eclipse.jetty.websocket.jsr356.decoders.DateDecoder;
@ClientEndpoint(decoders =
{ DateDecoder.class })
public class DateTextSocket
{
private Session session;
@OnMessage
public void onMessage(Date d) throws IOException
{
if (d == null)
{
session.getAsyncRemote().sendText("Error: Date is null");
}
else
{
String msg = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT).format(d);
session.getAsyncRemote().sendText(msg);
}
}
@OnOpen
public void onOpen(Session session)
{
this.session = session;
}
}

View File

@ -0,0 +1,57 @@
//
// ========================================================================
// 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.annotations;
import static org.hamcrest.Matchers.*;
import java.lang.reflect.Method;
import java.util.Date;
import org.eclipse.jetty.websocket.jsr356.MessageType;
import org.eclipse.jetty.websocket.jsr356.decoders.DateDecoder;
import org.eclipse.jetty.websocket.jsr356.metadata.DecoderMetadata;
import org.junit.Assert;
import org.junit.Test;
public class JsrParamIdDecoderTest
{
private OnMessageCallable getOnMessageCallableFrom(Class<?> clazz, String methodName)
{
for (Method method : clazz.getMethods())
{
if (method.getName().equals(methodName))
{
return new OnMessageCallable(clazz,method);
}
}
return null;
}
@Test
public void testMatchDateDecoder()
{
DecoderMetadata metadata = new DecoderMetadata(DateDecoder.class,Date.class,MessageType.TEXT,false);
JsrParamIdDecoder paramId = new JsrParamIdDecoder(metadata);
OnMessageCallable callable = getOnMessageCallableFrom(DateTextSocket.class,"onMessage");
Param param = new Param(0,Date.class);
Assert.assertThat("Match for Decoder",paramId.process(param,callable),is(true));
}
}

View File

@ -45,6 +45,9 @@ public class AnnotatedServerEndpointMetadata extends AnnotatedEndpointMetadata<S
this.endpoint = anno;
this.config = new AnnotatedServerEndpointConfig(websocket,anno);
getDecoders().addAll(anno.decoders());
getEncoders().addAll(anno.encoders());
}
@Override

View File

@ -25,6 +25,7 @@ import java.lang.reflect.Field;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.websocket.CloseReason;
@ -50,6 +51,7 @@ import org.eclipse.jetty.websocket.jsr356.server.samples.BasicOpenSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicPongMessageSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.BasicTextMessageStringSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.StatelessTextMessageStringSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.beans.DateTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ByteObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ByteTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.CharTextSocket;
@ -60,6 +62,8 @@ import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.FloatObjectT
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.FloatTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.IntTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.IntegerObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortObjectTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.primitives.ShortTextSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.ReaderParamSocket;
import org.eclipse.jetty.websocket.jsr356.server.samples.streaming.StringReturnReaderParamSocket;
import org.junit.Assert;
@ -139,6 +143,10 @@ public class ServerAnnotatedEndpointScanner_GoodSignaturesTest
Case.add(data, FloatObjectTextSocket.class, fText, Float.class);
Case.add(data, IntTextSocket.class, fText, Integer.TYPE);
Case.add(data, IntegerObjectTextSocket.class, fText, Integer.class);
Case.add(data, ShortTextSocket.class, fText, Short.TYPE);
Case.add(data, ShortObjectTextSocket.class, fText, Short.class);
// -- Beans
Case.add(data, DateTextSocket.class, fText, Date.class);
// -- Reader Events
Case.add(data, ReaderParamSocket.class, fText, Reader.class, String.class);
Case.add(data, StringReturnReaderParamSocket.class, fText, Reader.class, String.class);
@ -163,24 +171,25 @@ public class ServerAnnotatedEndpointScanner_GoodSignaturesTest
public ServerAnnotatedEndpointScanner_GoodSignaturesTest(Case testcase)
{
this.testcase = testcase;
System.err.printf("Testing signature of %s%n",testcase.pojo.getName());
}
@Test
public void testScan_Basic() throws Exception
{
AnnotatedServerEndpointMetadata metadata = new AnnotatedServerEndpointMetadata(container,testcase.pojo);
AnnotatedEndpointScanner<ServerEndpoint,ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
AnnotatedEndpointScanner<ServerEndpoint, ServerEndpointConfig> scanner = new AnnotatedEndpointScanner<>(metadata);
scanner.scan();
Assert.assertThat("Metadata",metadata,notNullValue());
JsrCallable cm = (JsrCallable)testcase.metadataField.get(metadata);
Assert.assertThat(testcase.metadataField.toString(),cm,notNullValue());
JsrCallable method = (JsrCallable)testcase.metadataField.get(metadata);
Assert.assertThat(testcase.metadataField.toString(),method,notNullValue());
int len = testcase.expectedParameters.length;
for (int i = 0; i < len; i++)
{
Class<?> expectedParam = testcase.expectedParameters[i];
Class<?> actualParam = cm.getParamTypes()[i];
Class<?> actualParam = method.getParamTypes()[i];
Assert.assertTrue("Parameter[" + i + "] - expected:[" + expectedParam + "], actual:[" + actualParam + "]",actualParam.equals(expectedParam));
}

View File

@ -0,0 +1,62 @@
//
// ========================================================================
// 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.server.samples.beans;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
/**
* Decode Date
*/
public class DateDecoder implements Decoder.Text<Date>
{
@Override
public Date decode(String s) throws DecodeException
{
try
{
return new SimpleDateFormat("yyyy.MM.dd").parse(s);
}
catch (ParseException e)
{
throw new DecodeException(s,e.getMessage(),e);
}
}
@Override
public void destroy()
{
}
@Override
public void init(EndpointConfig config)
{
}
@Override
public boolean willDecode(String s)
{
return true;
}
}

View File

@ -0,0 +1,48 @@
//
// ========================================================================
// 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.server.samples.beans;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
/**
* Encode Date
*/
public class DateEncoder implements Encoder.Text<Date>
{
@Override
public void destroy()
{
}
@Override
public String encode(Date object) throws EncodeException
{
return new SimpleDateFormat("yyyy.MM.dd").format(object);
}
@Override
public void init(EndpointConfig config)
{
}
}

View File

@ -0,0 +1,69 @@
//
// ========================================================================
// 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.server.samples.beans;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.jsr356.server.StackUtil;
@ServerEndpoint(value = "/echo/beans/date", decoders =
{ DateDecoder.class })
public class DateTextSocket
{
private static final Logger LOG = Log.getLogger(DateTextSocket.class);
private Session session;
@OnOpen
public void onOpen(Session session)
{
this.session = session;
}
@OnMessage
public void onMessage(Date d) throws IOException
{
if (d == null)
{
session.getAsyncRemote().sendText("Error: Date is null");
}
else
{
String msg = SimpleDateFormat.getDateInstance(SimpleDateFormat.SHORT).format(d);
session.getAsyncRemote().sendText(msg);
}
}
@OnError
public void onError(Throwable cause) throws IOException
{
LOG.warn("Error",cause);
session.getBasicRemote().sendText("Exception: " + StackUtil.toString(cause));
}
}

View File

@ -0,0 +1,62 @@
//
// ========================================================================
// 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.server.samples.beans;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
/**
* Decode Date and Time
*/
public class DateTimeDecoder implements Decoder.Text<Date>
{
@Override
public Date decode(String s) throws DecodeException
{
try
{
return new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z").parse(s);
}
catch (ParseException e)
{
throw new DecodeException(s,e.getMessage(),e);
}
}
@Override
public void destroy()
{
}
@Override
public void init(EndpointConfig config)
{
}
@Override
public boolean willDecode(String s)
{
return true;
}
}

View File

@ -0,0 +1,48 @@
//
// ========================================================================
// 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.server.samples.beans;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
/**
* Encode Date
*/
public class DateTimeEncoder implements Encoder.Text<Date>
{
@Override
public void destroy()
{
}
@Override
public String encode(Date object) throws EncodeException
{
return new SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z").format(object);
}
@Override
public void init(EndpointConfig config)
{
}
}

View File

@ -0,0 +1,62 @@
//
// ========================================================================
// 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.server.samples.beans;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
/**
* Decode Time
*/
public class TimeDecoder implements Decoder.Text<Date>
{
@Override
public Date decode(String s) throws DecodeException
{
try
{
return new SimpleDateFormat("HH:mm:ss z").parse(s);
}
catch (ParseException e)
{
throw new DecodeException(s,e.getMessage(),e);
}
}
@Override
public void destroy()
{
}
@Override
public void init(EndpointConfig config)
{
}
@Override
public boolean willDecode(String s)
{
return true;
}
}

View File

@ -0,0 +1,48 @@
//
// ========================================================================
// 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.server.samples.beans;
import java.text.SimpleDateFormat;
import java.util.Date;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
/**
* Encode Time
*/
public class TimeEncoder implements Encoder.Text<Date>
{
@Override
public void destroy()
{
}
@Override
public String encode(Date object) throws EncodeException
{
return new SimpleDateFormat("HH:mm:ss z").format(object);
}
@Override
public void init(EndpointConfig config)
{
}
}

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.websocket.common.events.annotated;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Objects;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -37,6 +38,8 @@ public class CallableMethod
public CallableMethod(Class<?> pojo, Method method)
{
Objects.requireNonNull(pojo, "Pojo cannot be null");
Objects.requireNonNull(method, "Method cannot be null");
this.pojo = pojo;
this.method = method;
this.paramTypes = method.getParameterTypes();