Author: markt Date: Mon Mar 18 21:47:02 2013 New Revision: 1458028 URL: http://svn.apache.org/r1458028 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=54710 Add support for InputStream and Reader to OnMessage Add support for CloseReason to OnClose Based on a patch by Nick Williams
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerBase.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBase.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBinary.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialText.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBase.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBinary.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholePong.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeText.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/LocalStrings.properties Mon Mar 18 21:47:02 2013 @@ -24,7 +24,9 @@ pojoMethodMapping.duplicateSessionParam= pojoMethodMapping.invalidType=Unable to coerce value [{0}] to type [{1}]. That type is not supported. pojoMethodMapping.noPayload=No payload parameter present on the method [{0}] of class [{1}] that was annotated with OnMessage pojoMethodMapping.onErrorNoThrowable=No Throwable parameter was present on the method [{0}] of class [{1}] that was annotated with OnError -pojoMethodMapping.partialPong=Invalid PongMessgae and boolean parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage +pojoMethodMapping.partialInputStream=Invalid InputStream and boolean parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage +pojoMethodMapping.partialPong=Invalid PongMesssge and boolean parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage +pojoMethodMapping.partialReader=Invalid Reader and boolean parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage pojoMethodMapping.pongWithPayload=Invalid PongMessgae and Message parameters present on the method [{0}] of class [{1}] that was annotated with OnMessage pojoMessageHandlerWhole.decodeFail=Failed to decode received message with first matching Decoder instance pojoMessageHandlerWhole.decodeIoFail=IO error while decoding message \ No newline at end of file Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoEndpointBase.java Mon Mar 18 21:47:02 2013 @@ -74,7 +74,7 @@ public abstract class PojoEndpointBase e if (methodMapping.getOnClose() != null) { try { methodMapping.getOnClose().invoke(pojo, - methodMapping.getOnCloseArgs(pathParameters, session)); + methodMapping.getOnCloseArgs(pathParameters, session, closeReason)); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { log.error(sm.getString("pojoEndpointBase.onCloseFail", Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerBase.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerBase.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerBase.java Mon Mar 18 21:47:02 2013 @@ -36,19 +36,19 @@ public abstract class PojoMessageHandler protected final Session session; protected final Object[] params; protected final int indexPayload; - protected final boolean unwrap; + protected final boolean convert; protected final int indexSession; public PojoMessageHandlerBase(Object pojo, Method method, - Session session, Object[] params, int indexPayload, boolean unwrap, + Session session, Object[] params, int indexPayload, boolean convert, int indexSession) { this.pojo = pojo; this.method = method; this.session = session; this.params = params; this.indexPayload = indexPayload; - this.unwrap = unwrap; + this.convert = convert; this.indexSession = indexSession; } Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBase.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBase.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBase.java Mon Mar 18 21:47:02 2013 @@ -36,8 +36,8 @@ public abstract class PojoMessageHandler public PojoMessageHandlerPartialBase(Object pojo, Method method, Session session, Object[] params, int indexPayload, - boolean unwrap, int indexBoolean, int indexSession) { - super(pojo, method, session, params, indexPayload, unwrap, + boolean convert, int indexBoolean, int indexSession) { + super(pojo, method, session, params, indexPayload, convert, indexSession); this.indexBoolean = indexBoolean; } @@ -52,7 +52,7 @@ public abstract class PojoMessageHandler if (indexSession != -1) { parameters[indexSession] = session; } - if (unwrap) { + if (convert) { parameters[indexPayload] = ((ByteBuffer) message).array(); } else { parameters[indexPayload] = message; Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBinary.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBinary.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBinary.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialBinary.java Mon Mar 18 21:47:02 2013 @@ -28,9 +28,9 @@ public class PojoMessageHandlerPartialBi extends PojoMessageHandlerPartialBase<ByteBuffer>{ public PojoMessageHandlerPartialBinary(Object pojo, Method method, - Session session, Object[] params, int indexPayload, boolean unwrap, + Session session, Object[] params, int indexPayload, boolean convert, int indexBoolean, int indexSession) { - super(pojo, method, session, params, indexPayload, unwrap, indexBoolean, + super(pojo, method, session, params, indexPayload, convert, indexBoolean, indexSession); } } Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialText.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialText.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialText.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerPartialText.java Mon Mar 18 21:47:02 2013 @@ -27,9 +27,9 @@ public class PojoMessageHandlerPartialTe extends PojoMessageHandlerPartialBase<String>{ public PojoMessageHandlerPartialText(Object pojo, Method method, - Session session, Object[] params, int indexPayload, boolean unwrap, + Session session, Object[] params, int indexPayload, boolean convert, int indexBoolean, int indexSession) { - super(pojo, method, session, params, indexPayload, unwrap, indexBoolean, + super(pojo, method, session, params, indexPayload, convert, indexBoolean, indexSession); } } Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBase.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBase.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBase.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBase.java Mon Mar 18 21:47:02 2013 @@ -18,7 +18,6 @@ package org.apache.tomcat.websocket.pojo import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.nio.ByteBuffer; import javax.websocket.DecodeException; import javax.websocket.MessageHandler; @@ -42,8 +41,8 @@ public abstract class PojoMessageHandler public PojoMessageHandlerWholeBase(Object pojo, Method method, Session session, Object[] params, int indexPayload, - boolean unwrap, int indexSession) { - super(pojo, method, session, params, indexPayload, unwrap, + boolean convert, int indexSession) { + super(pojo, method, session, params, indexPayload, convert, indexSession); } @@ -63,13 +62,9 @@ public abstract class PojoMessageHandler } if (payload == null) { - // Not decoded. Unwrap if required. Unwrap only ever applies to - // ByteBuffers - if (unwrap) { - ByteBuffer bb = (ByteBuffer) message; - byte[] array = new byte[bb.remaining()]; - bb.get(array); - payload = array; + // Not decoded. Convert if required. + if (convert) { + payload = convert(message); } else { payload = message; } @@ -90,6 +85,10 @@ public abstract class PojoMessageHandler processResult(result); } + protected Object convert(T message) { + return message; + } + protected abstract Object decode(T message) throws DecodeException; protected abstract void onClose(); Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBinary.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBinary.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBinary.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeBinary.java Mon Mar 18 21:47:02 2013 @@ -43,18 +43,21 @@ public class PojoMessageHandlerWholeBina private final List<Decoder> decoders = new ArrayList<>(); + private final boolean isForInputStream; + public PojoMessageHandlerWholeBinary(Object pojo, Method method, Session session, EndpointConfig config, Object[] params, - int indexPayload, boolean unwrap, int indexSession) { - super(pojo, method, session, params, indexPayload, unwrap, indexSession); + int indexPayload, boolean convert, int indexSession, + boolean isForInputStream) { + super(pojo, method, session, params, indexPayload, convert, + indexSession); try { for (Class<? extends Decoder> decoderClazz : config.getDecoders()) { if (Binary.class.isAssignableFrom(decoderClazz)) { Binary<?> decoder = (Binary<?>) decoderClazz.newInstance(); decoder.init(config); decoders.add(decoder); - } else if (Decoder.TextStream.class.isAssignableFrom( - decoderClazz)) { + } else if (BinaryStream.class.isAssignableFrom(decoderClazz)) { BinaryStream<?> decoder = (BinaryStream<?>) decoderClazz.newInstance(); decoder.init(config); @@ -66,6 +69,7 @@ public class PojoMessageHandlerWholeBina } catch (IllegalAccessException | InstantiationException e) { throw new IllegalArgumentException(e); } + this.isForInputStream = isForInputStream; } @@ -93,6 +97,18 @@ public class PojoMessageHandlerWholeBina @Override + protected Object convert(ByteBuffer message) { + byte[] array = new byte[message.remaining()]; + message.get(array); + if (isForInputStream) { + return new ByteArrayInputStream(array); + } else { + return array; + } + } + + + @Override protected void onClose() { for (Decoder decoder : decoders) { decoder.destroy(); Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholePong.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholePong.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholePong.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholePong.java Mon Mar 18 21:47:02 2013 @@ -28,9 +28,9 @@ public class PojoMessageHandlerWholePong extends PojoMessageHandlerWholeBase<PongMessage> { public PojoMessageHandlerWholePong(Object pojo, Method method, - Session session, Object[] params, int indexPayload, boolean unwrap, + Session session, Object[] params, int indexPayload, boolean convert, int indexSession) { - super(pojo, method, session, params, indexPayload, unwrap, indexSession); + super(pojo, method, session, params, indexPayload, convert, indexSession); } @Override Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeText.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeText.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeText.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMessageHandlerWholeText.java Mon Mar 18 21:47:02 2013 @@ -44,8 +44,8 @@ public class PojoMessageHandlerWholeText public PojoMessageHandlerWholeText(Object pojo, Method method, Session session, EndpointConfig config, Object[] params, - int indexPayload, boolean unwrap, int indexSession) { - super(pojo, method, session, params, indexPayload, unwrap, + int indexPayload, boolean convert, int indexSession) { + super(pojo, method, session, params, indexPayload, convert, indexSession); try { for (Class<? extends Decoder> decoderClazz : config.getDecoders()) { @@ -53,8 +53,7 @@ public class PojoMessageHandlerWholeText Text<?> decoder = (Text<?>) decoderClazz.newInstance(); decoder.init(config); decoders.add(decoder); - } else if (Decoder.TextStream.class.isAssignableFrom( - decoderClazz)) { + } else if (TextStream.class.isAssignableFrom(decoderClazz)) { TextStream<?> decoder = (TextStream<?>) decoderClazz.newInstance(); decoder.init(config); @@ -91,6 +90,12 @@ public class PojoMessageHandlerWholeText @Override + protected Object convert(String message) { + return new StringReader(message); + } + + + @Override protected void onClose() { for (Decoder decoder : decoders) { decoder.destroy(); Modified: tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java?rev=1458028&r1=1458027&r2=1458028&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java Mon Mar 18 21:47:02 2013 @@ -16,6 +16,8 @@ */ package org.apache.tomcat.websocket.pojo; +import java.io.InputStream; +import java.io.Reader; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.nio.ByteBuffer; @@ -26,6 +28,7 @@ import java.util.List; import java.util.Map; import java.util.Set; +import javax.websocket.CloseReason; import javax.websocket.Decoder; import javax.websocket.Decoder.Binary; import javax.websocket.Decoder.BinaryStream; @@ -91,9 +94,9 @@ public class PojoMethodMapping { this.onOpen = open; this.onClose = close; this.onError = error; - onOpenParams = getPathParams(onOpen, false); - onCloseParams = getPathParams(onClose, false); - onErrorParams = getPathParams(onError, true); + onOpenParams = getPathParams(onOpen, false, false); + onCloseParams = getPathParams(onClose, false, true); + onErrorParams = getPathParams(onError, true, false); } @@ -109,7 +112,7 @@ public class PojoMethodMapping { public Object[] getOnOpenArgs(Map<String,String> pathParameters, Session session) { - return buildArgs(onOpenParams, pathParameters, session, null); + return buildArgs(onOpenParams, pathParameters, session, null, null); } @@ -119,8 +122,9 @@ public class PojoMethodMapping { public Object[] getOnCloseArgs(Map<String,String> pathParameters, - Session session) { - return buildArgs(onCloseParams, pathParameters, session, null); + Session session, CloseReason closeReason) { + return buildArgs( + onCloseParams, pathParameters, session, null, closeReason); } @@ -131,7 +135,8 @@ public class PojoMethodMapping { public Object[] getOnErrorArgs(Map<String,String> pathParameters, Session session, Throwable throwable) { - return buildArgs(onErrorParams, pathParameters, session, throwable); + return buildArgs( + onErrorParams, pathParameters, session, throwable, null); } @@ -170,7 +175,8 @@ public class PojoMethodMapping { } - private static PojoPathParam[] getPathParams(Method m, boolean isOnError) { + private static PojoPathParam[] getPathParams(Method m, boolean isOnError, + boolean isClose) { if (m == null) { return new PojoPathParam[0]; } @@ -185,6 +191,8 @@ public class PojoMethodMapping { } else if (isOnError && type.equals(Throwable.class)) { foundThrowable = true; result[i] = new PojoPathParam(type, null); + } else if (isClose && type.equals(CloseReason.class)) { + result[i] = new PojoPathParam(type, null); } else { Annotation[] paramAnnotations = paramsAnnotations[i]; for (Annotation paramAnnotation : paramAnnotations) { @@ -212,7 +220,7 @@ public class PojoMethodMapping { private static Object[] buildArgs(PojoPathParam[] pathParams, Map<String,String> pathParameters, Session session, - Throwable throwable) { + Throwable throwable, CloseReason closeReason) { Object[] result = new Object[pathParams.length]; for (int i = 0; i < pathParams.length; i++) { Class<?> type = pathParams[i].getType(); @@ -220,6 +228,8 @@ public class PojoMethodMapping { result[i] = session; } else if (type.equals(Throwable.class)) { result[i] = throwable; + } else if (type.equals(CloseReason.class)) { + result[i] = closeReason; } else { String name = pathParams[i].getName(); String value = pathParameters.get(name); @@ -260,6 +270,7 @@ public class PojoMethodMapping { } } + private static class MessageMethod { private final Method m; @@ -269,6 +280,8 @@ public class PojoMethodMapping { private int indexPong = -1; private int indexBoolean = -1; private int indexSession = -1; + private int indexInputStream = -1; + private int indexReader = -1; private Map<Integer,PojoPathParam> indexPathParams = new HashMap<>(); private int indexPayload = -1; @@ -303,6 +316,14 @@ public class PojoMethodMapping { "pojoMethodMapping.duplicateMessageParam", m.getName(), m.getClass().getName())); } + } else if (types[i] == Reader.class) { + if (indexReader == -1) { + indexReader = i; + } else { + throw new IllegalArgumentException(sm.getString( + "pojoMethodMapping.duplicateMessageParam", + m.getName(), m.getClass().getName())); + } } else if (types[i] == boolean.class) { if (indexBoolean == -1) { indexBoolean = i; @@ -327,6 +348,14 @@ public class PojoMethodMapping { "pojoMethodMapping.duplicateMessageParam", m.getName(), m.getClass().getName())); } + } else if (types[i] == InputStream.class) { + if (indexInputStream == -1) { + indexInputStream = i; + } else { + throw new IllegalArgumentException(sm.getString( + "pojoMethodMapping.duplicateMessageParam", + m.getName(), m.getClass().getName())); + } } else if (types[i] == Session.class) { if (indexSession == -1) { indexSession = i; @@ -376,6 +405,15 @@ public class PojoMethodMapping { if (indexString != -1) { indexPayload = indexString; } + if (indexReader != -1) { + if (indexPayload != -1) { + throw new IllegalArgumentException(sm.getString( + "pojoMethodMapping.duplicateMessageParam", + m.getName(), m.getClass().getName())); + } else { + indexPayload = indexReader; + } + } if (indexByteArray != -1) { if (indexPayload != -1) { throw new IllegalArgumentException(sm.getString( @@ -394,6 +432,15 @@ public class PojoMethodMapping { indexPayload = indexByteBuffer; } } + if (indexInputStream != -1) { + if (indexPayload != -1) { + throw new IllegalArgumentException(sm.getString( + "pojoMethodMapping.duplicateMessageParam", + m.getName(), m.getClass().getName())); + } else { + indexPayload = indexInputStream; + } + } if (indexPong != -1) { if (indexPayload != -1) { throw new IllegalArgumentException(sm.getString( @@ -413,6 +460,16 @@ public class PojoMethodMapping { "pojoMethodMapping.partialPong", m.getName(), m.getClass().getName())); } + if(indexReader != -1 && indexBoolean != -1) { + throw new IllegalArgumentException(sm.getString( + "pojoMethodMapping.partialReader", + m.getName(), m.getClass().getName())); + } + if(indexInputStream != -1 && indexBoolean != -1) { + throw new IllegalArgumentException(sm.getString( + "pojoMethodMapping.partialInputStream", + m.getName(), m.getClass().getName())); + } } @@ -440,11 +497,19 @@ public class PojoMethodMapping { config, params, indexString, false, indexSession); } else if (indexByteArray != -1) { mh = new PojoMessageHandlerWholeBinary(pojo, m, session, - config, params, indexByteArray, true, indexSession); + config, params, indexByteArray, true, indexSession, + false); } else if (indexByteBuffer != -1) { mh = new PojoMessageHandlerWholeBinary(pojo, m, session, config, params, indexByteBuffer, false, - indexSession); + indexSession, false); + } else if (indexInputStream != -1) { + mh = new PojoMessageHandlerWholeBinary(pojo, m, session, + config, params, indexInputStream, true, indexSession, + true); + } else if (indexReader != -1) { + mh = new PojoMessageHandlerWholeText(pojo, m, session, + config, params, indexReader, true, indexSession); } else { mh = new PojoMessageHandlerWholePong(pojo, m, session, params, indexPong, false, indexSession); --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org