Author: remm Date: Tue Dec 2 21:16:51 2014 New Revision: 1643008 URL: http://svn.apache.org/r1643008 Log: Websockets annotations can be located on superclasses, and also improve duplicates detection.
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/Util.java tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java Modified: tomcat/trunk/java/org/apache/tomcat/websocket/Util.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/Util.java?rev=1643008&r1=1643007&r2=1643008&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/Util.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/Util.java Tue Dec 2 21:16:51 2014 @@ -576,9 +576,10 @@ public class Util { new ArrayList<>(); private final List<Class<? extends Decoder>> binaryDecoders = new ArrayList<>(); - + private final Class<?> target; public DecoderMatch(Class<?> target, List<DecoderEntry> decoderEntries) { + this.target = target; for (DecoderEntry decoderEntry : decoderEntries) { if (decoderEntry.getClazz().isAssignableFrom(target)) { if (Binary.class.isAssignableFrom( @@ -624,6 +625,11 @@ public class Util { } + public Class<?> getTarget() { + return target; + } + + public boolean hasMatches() { return (textDecoders.size() > 0) || (binaryDecoders.size() > 0); } 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=1643008&r1=1643007&r2=1643008&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/pojo/PojoMethodMapping.java Tue Dec 2 21:16:51 2014 @@ -22,6 +22,7 @@ import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.ByteBuffer; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -64,7 +65,7 @@ public class PojoMethodMapping { private final PojoPathParam[] onOpenParams; private final PojoPathParam[] onCloseParams; private final PojoPathParam[] onErrorParams; - private final Set<MessageHandlerInfo> onMessage = new HashSet<>(); + private final List<MessageHandlerInfo> onMessage = new ArrayList<>(); private final String wsPath; @@ -78,43 +79,56 @@ public class PojoMethodMapping { Method open = null; Method close = null; Method error = null; - for (Method method : clazzPojo.getDeclaredMethods()) { - if (method.getAnnotation(OnOpen.class) != null) { - checkPublic(method); - if (open == null) { - open = method; - } else { - // Duplicate annotation - throw new DeploymentException(sm.getString( - "pojoMethodMapping.duplicateAnnotation", - OnOpen.class, clazzPojo)); - } - } else if (method.getAnnotation(OnClose.class) != null) { - checkPublic(method); - if (close == null) { - close = method; - } else { - // Duplicate annotation - throw new DeploymentException(sm.getString( - "pojoMethodMapping.duplicateAnnotation", - OnClose.class, clazzPojo)); - } - } else if (method.getAnnotation(OnError.class) != null) { - checkPublic(method); - if (error == null) { - error = method; + Class<?> currentClazz = clazzPojo; + while (!currentClazz.equals(Object.class)) { + for (Method method : currentClazz.getDeclaredMethods()) { + if (method.getAnnotation(OnOpen.class) != null) { + checkPublic(method); + if (open == null) { + open = method; + } else { + // Duplicate annotation + throw new DeploymentException(sm.getString( + "pojoMethodMapping.duplicateAnnotation", + OnOpen.class, clazzPojo)); + } + } else if (method.getAnnotation(OnClose.class) != null) { + checkPublic(method); + if (close == null) { + close = method; + } else { + // Duplicate annotation + throw new DeploymentException(sm.getString( + "pojoMethodMapping.duplicateAnnotation", + OnClose.class, clazzPojo)); + } + } else if (method.getAnnotation(OnError.class) != null) { + checkPublic(method); + if (error == null) { + error = method; + } else { + // Duplicate annotation + throw new DeploymentException(sm.getString( + "pojoMethodMapping.duplicateAnnotation", + OnError.class, clazzPojo)); + } + } else if (method.getAnnotation(OnMessage.class) != null) { + checkPublic(method); + MessageHandlerInfo messageHandler = new MessageHandlerInfo(method, decoders); + for (MessageHandlerInfo otherMessageHandler : onMessage) { + if (messageHandler.equals(otherMessageHandler)) { + // Duplicate annotation + throw new DeploymentException(sm.getString( + "pojoMethodMapping.duplicateAnnotation", + OnMessage.class, clazzPojo)); + } + } + onMessage.add(messageHandler); } else { - // Duplicate annotation - throw new DeploymentException(sm.getString( - "pojoMethodMapping.duplicateAnnotation", - OnError.class, clazzPojo)); + // Method not annotated } - } else if (method.getAnnotation(OnMessage.class) != null) { - checkPublic(method); - onMessage.add(new MessageHandlerInfo(method, decoders)); - } else { - // Method not annotated } + currentClazz = currentClazz.getSuperclass(); } this.onOpen = open; this.onClose = close; @@ -288,6 +302,7 @@ public class PojoMethodMapping { private int indexInputStream = -1; private int indexReader = -1; private int indexPrimitive = -1; + private Class<?> primitiveType = null; private Map<Integer,PojoPathParam> indexPathParams = new HashMap<>(); private int indexPayload = -1; private DecoderMatch decoderMatch = null; @@ -366,6 +381,7 @@ public class PojoMethodMapping { } else if (Util.isPrimitive(types[i])) { if (indexPrimitive == -1) { indexPrimitive = i; + primitiveType = types[i]; } else { throw new IllegalArgumentException(sm.getString( "pojoMethodMapping.duplicateMessageParam", @@ -470,6 +486,7 @@ public class PojoMethodMapping { // The boolean we found is a payload, not a last flag indexPayload = indexBoolean; indexPrimitive = indexBoolean; + primitiveType = Boolean.TYPE; indexBoolean = -1; } if (indexPayload == -1) { @@ -503,6 +520,42 @@ public class PojoMethodMapping { } + @Override + public boolean equals(Object obj) { + if (obj == null || !(obj instanceof MessageHandlerInfo)) { + return false; + } + MessageHandlerInfo otherHandler = (MessageHandlerInfo) obj; + if (indexByteArray >= 0 && otherHandler.indexByteArray >= 0) { + return true; + } + if (indexByteBuffer >= 0 && otherHandler.indexByteBuffer >= 0) { + return true; + } + if (indexInputStream >= 0 && otherHandler.indexInputStream >= 0) { + return true; + } + if (indexPong >= 0 && otherHandler.indexPong >= 0) { + return true; + } + if (indexPrimitive >= 0 && otherHandler.indexPrimitive >= 0 + && primitiveType == otherHandler.primitiveType) { + return true; + } + if (indexReader >= 0 && otherHandler.indexReader >= 0) { + return true; + } + if (indexString >= 0 && otherHandler.indexString >= 0) { + return true; + } + if (decoderMatch != null && otherHandler.decoderMatch != null + && decoderMatch.getTarget().equals(otherHandler.decoderMatch.getTarget())) { + return true; + } + return false; + } + + public Set<MessageHandler> getMessageHandlers(Object pojo, Map<String,String> pathParameters, Session session, EndpointConfig config) { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org