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:25:43 UTC

svn commit: r1533964 - in /tomcat/tc7.0.x/trunk: ./ java/org/apache/tomcat/websocket/Util.java test/org/apache/tomcat/websocket/TestUtil.java webapps/docs/changelog.xml

Author: markt
Date: Sun Oct 20 20:25:43 2013
New Revision: 1533964

URL: http://svn.apache.org/r1533964
Log:
Handle arrays of generic types in encoders, decoders and MessageHandlers.

Modified:
    tomcat/tc7.0.x/trunk/   (props changed)
    tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Util.java
    tomcat/tc7.0.x/trunk/test/org/apache/tomcat/websocket/TestUtil.java
    tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml

Propchange: tomcat/tc7.0.x/trunk/
------------------------------------------------------------------------------
  Merged /tomcat/trunk:r1533962

Modified: tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Util.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Util.java?rev=1533964&r1=1533963&r2=1533964&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Util.java (original)
+++ tomcat/tc7.0.x/trunk/java/org/apache/tomcat/websocket/Util.java Sun Oct 20 20:25:43 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 generic MessageHandler<>
@@ -201,24 +202,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
             // MessageHandler<>
-            return result;
-        } else if (result instanceof Integer) {
+            return superClassTypeResult;
+        }
+
+        if (superClassTypeResult.getIndex() > -1) {
             // Superclass implements interface and defines unknown type for
             // MessageHandler<>
             // 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;
     }
 
 
@@ -226,16 +255,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;
@@ -482,4 +516,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/tc7.0.x/trunk/test/org/apache/tomcat/websocket/TestUtil.java
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/test/org/apache/tomcat/websocket/TestUtil.java?rev=1533964&r1=1533963&r2=1533964&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/test/org/apache/tomcat/websocket/TestUtil.java (original)
+++ tomcat/tc7.0.x/trunk/test/org/apache/tomcat/websocket/TestUtil.java Sun Oct 20 20:25:43 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;
+        }
+    }
 }

Modified: tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml?rev=1533964&r1=1533963&r2=1533964&view=diff
==============================================================================
--- tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/tc7.0.x/trunk/webapps/docs/changelog.xml Sun Oct 20 20:25:43 2013
@@ -69,6 +69,11 @@
         <code>Encoder.Text&lt;List&lt;String&gt;&gt;</code>. Includes a test
         case by Niki Dokovski. (markt)
       </fix>
+      <fix>
+        Correctly handle WebSocket <code>Encoder</code>s, <code>Decoder</code>s
+        and <code>MessageHandler</code>s that use arrays of generic types.
+        (markt)
+      </fix>
     </changelog>
   </subsection>
 </section>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org