You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2013/10/20 22:23:57 UTC
svn commit: r1533962 - in /tomcat/trunk:
java/org/apache/tomcat/websocket/Util.java
test/org/apache/tomcat/websocket/TestUtil.java
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-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org