Author: markt Date: Sun Oct 20 20:23:57 2013 New Revision: 1533962 URL: http://svn.apache.org/r1533962 Log: Handle arrays of generic types in encoders, decoders and MessageHandlers.
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/Util.java tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.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=1533962&r1=1533961&r2=1533962&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/tomcat/websocket/Util.java (original) +++ tomcat/trunk/java/org/apache/tomcat/websocket/Util.java Sun Oct 20 20:23:57 2013 @@ -18,6 +18,7 @@ package org.apache.tomcat.websocket; import java.io.InputStream; import java.io.Reader; +import java.lang.reflect.GenericArrayType; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; @@ -159,22 +160,22 @@ public class Util { static Class<?> getMessageType(MessageHandler listener) { - return (Class<?>) Util.getGenericType(MessageHandler.class, - listener.getClass()); + return Util.getGenericType(MessageHandler.class, + listener.getClass()).getClazz(); } public static Class<?> getDecoderType(Class<? extends Decoder> decoder) { - return (Class<?>) Util.getGenericType(Decoder.class, decoder); + return Util.getGenericType(Decoder.class, decoder).getClazz(); } static Class<?> getEncoderType(Class<? extends Encoder> encoder) { - return (Class<?>) Util.getGenericType(Encoder.class, encoder); + return Util.getGenericType(Encoder.class, encoder).getClazz(); } - private static <T> Object getGenericType(Class<T> type, + private static <T> TypeResult getGenericType(Class<T> type, Class<? extends T> clazz) { // Look to see if this class implements the interface of interest @@ -200,24 +201,52 @@ public class Util { Class<? extends T> superClazz = (Class<? extends T>) clazz.getSuperclass(); - Object result = getGenericType(type, superClazz); - if (result instanceof Class<?>) { + TypeResult superClassTypeResult = getGenericType(type, superClazz); + int dimension = superClassTypeResult.getDimension(); + if (superClassTypeResult.getIndex() == -1 && dimension == 0) { // Superclass implements interface and defines explicit type for // the interface of interest - return result; - } else if (result instanceof Integer) { + return superClassTypeResult; + } + + if (superClassTypeResult.getIndex() > -1) { // Superclass implements interface and defines unknown type for // the interface of interest // Map that unknown type to the generic types defined in this class ParameterizedType superClassType = (ParameterizedType) clazz.getGenericSuperclass(); - return getTypeParameter(clazz, + TypeResult result = getTypeParameter(clazz, superClassType.getActualTypeArguments()[ - ((Integer) result).intValue()]); - } else { - // Error will be logged further up the call stack - return null; + superClassTypeResult.getIndex()]); + result.incrementDimension(superClassTypeResult.getDimension()); + if (result.getClazz() != null && result.getDimension() > 0) { + superClassTypeResult = result; + } else { + return result; + } } + + if (superClassTypeResult.getDimension() > 0) { + StringBuilder className = new StringBuilder(); + for (int i = 0; i < dimension; i++) { + className.append('['); + } + className.append('L'); + className.append(superClassTypeResult.getClazz().getCanonicalName()); + className.append(';'); + + Class<?> arrayClazz; + try { + arrayClazz = Class.forName(className.toString()); + } catch (ClassNotFoundException e) { + throw new IllegalArgumentException(e); + } + + return new TypeResult(arrayClazz, -1, 0); + } + + // Error will be logged further up the call stack + return null; } @@ -225,16 +254,21 @@ public class Util { * For a generic parameter, return either the Class used or if the type * is unknown, the index for the type in definition of the class */ - private static Object getTypeParameter(Class<?> clazz, Type argType) { + private static TypeResult getTypeParameter(Class<?> clazz, Type argType) { if (argType instanceof Class<?>) { - return argType; + return new TypeResult((Class<?>) argType, -1, 0); } else if (argType instanceof ParameterizedType) { - return ((ParameterizedType) argType).getRawType(); + return new TypeResult((Class<?>)((ParameterizedType) argType).getRawType(), -1, 0); + } else if (argType instanceof GenericArrayType) { + Type arrayElementType = ((GenericArrayType) argType).getGenericComponentType(); + TypeResult result = getTypeParameter(clazz, arrayElementType); + result.incrementDimension(1); + return result; } else { TypeVariable<?>[] tvs = clazz.getTypeParameters(); for (int i = 0; i < tvs.length; i++) { if (tvs[i].equals(argType)) { - return Integer.valueOf(i); + return new TypeResult(null, i, 0); } } return null; @@ -474,4 +508,33 @@ public class Util { return (textDecoders.size() > 0) || (binaryDecoders.size() > 0); } } + + + private static class TypeResult { + private final Class<?> clazz; + private final int index; + private int dimension; + + public TypeResult(Class<?> clazz, int index, int dimension) { + this.clazz= clazz; + this.index = index; + this.dimension = dimension; + } + + public Class<?> getClazz() { + return clazz; + } + + public int getIndex() { + return index; + } + + public int getDimension() { + return dimension; + } + + public void incrementDimension(int inc) { + dimension += inc; + } + } } Modified: tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java?rev=1533962&r1=1533961&r2=1533962&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java (original) +++ tomcat/trunk/test/org/apache/tomcat/websocket/TestUtil.java Sun Oct 20 20:23:57 2013 @@ -110,6 +110,20 @@ public class TestUtil { } + @Test + public void testGenericArrayEncoderString() { + Assert.assertEquals(String[].class, + Util.getEncoderType(GenericArrayEncoderString.class)); + } + + + @Test + public void testGenericArraySubEncoderString() { + Assert.assertEquals(String[][].class, + Util.getEncoderType(GenericArraySubEncoderString.class)); + } + + private static class SimpleMessageHandler implements MessageHandler.Whole<String> { @Override @@ -310,4 +324,50 @@ public class TestUtil { return null; } } + + + private abstract static class GenericArrayEncoder<T> implements Encoder.Text<T[]> { + } + + + private static class GenericArrayEncoderString extends GenericArrayEncoder<String> { + + @Override + public void init(EndpointConfig endpointConfig) { + // NO-OP + } + + @Override + public void destroy() { + // NO-OP + } + + @Override + public String encode(String[] object) throws EncodeException { + return null; + } + } + + + private abstract static class GenericArraySubEncoder<T> extends GenericArrayEncoder<T[]> { + } + + + private static class GenericArraySubEncoderString extends GenericArraySubEncoder<String> { + + @Override + public void init(EndpointConfig endpointConfig) { + // NO-OP + } + + @Override + public void destroy() { + // NO-OP + } + + @Override + public String encode(String[][] object) throws EncodeException { + return null; + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org