You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by pa...@apache.org on 2017/10/07 09:55:08 UTC

[1/2] [lang] LANG-1348 - StackOverflowError on TypeUtils.toString(...) for a generic return type of Enum.valueOf (closes #292)

Repository: commons-lang
Updated Branches:
  refs/heads/master 36217ee16 -> 00feb98f8


LANG-1348 - StackOverflowError on TypeUtils.toString(...) for a generic return type of Enum.valueOf (closes #292)


Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/cc6beb2d
Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/cc6beb2d
Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/cc6beb2d

Branch: refs/heads/master
Commit: cc6beb2d05347fba64d933906ae2b712b1a43302
Parents: 36217ee
Author: mbusso <ma...@gmail.com>
Authored: Thu Sep 28 21:51:24 2017 -0300
Committer: pascalschumacher <pa...@gmx.net>
Committed: Sat Oct 7 11:50:15 2017 +0200

----------------------------------------------------------------------
 .../apache/commons/lang3/reflect/TypeUtils.java | 46 ++++++++++++++++++--
 .../commons/lang3/reflect/TypeUtilsTest.java    |  6 +++
 2 files changed, 49 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-lang/blob/cc6beb2d/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java b/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
index 54c810d..9e07c33 100644
--- a/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
+++ b/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java
@@ -1788,7 +1788,7 @@ public class TypeUtils {
 
         final Type useOwner = p.getOwnerType();
         final Class<?> raw = (Class<?>) p.getRawType();
-        final Type[] typeArguments = p.getActualTypeArguments();
+
         if (useOwner == null) {
             buf.append(raw.getName());
         } else {
@@ -1800,10 +1800,46 @@ public class TypeUtils {
             buf.append('.').append(raw.getSimpleName());
         }
 
-        appendAllTo(buf.append('<'), ", ", typeArguments).append('>');
+        final int[] recursiveTypeIndexes = findRecursiveTypes(p);
+
+        if (recursiveTypeIndexes.length > 0) {
+            appendRecursiveTypes(buf, recursiveTypeIndexes, p.getActualTypeArguments());
+        } else {
+            appendAllTo(buf.append('<'), ", ", p.getActualTypeArguments()).append('>');
+        }
+
         return buf.toString();
     }
 
+    private static void appendRecursiveTypes(StringBuilder buf, int[] recursiveTypeIndexes, Type[] argumentTypes) {
+        for (int i = 0; i < recursiveTypeIndexes.length; i++) {
+            appendAllTo(buf.append('<'), ", ", argumentTypes[i].toString()).append('>');
+        }
+
+        final Type[] argumentsFiltered = ArrayUtils.removeAll(argumentTypes, recursiveTypeIndexes);
+
+        if (argumentsFiltered.length > 0) {
+            appendAllTo(buf.append('<'), ", ", argumentsFiltered).append('>');
+        }
+    }
+
+    private static int[] findRecursiveTypes(ParameterizedType p) {
+        Type[] filteredArgumentTypes = Arrays.copyOf(p.getActualTypeArguments(), p.getActualTypeArguments().length);
+        int[] indexesToRemove = new int[] {};
+        for (int i = 0; i < filteredArgumentTypes.length; i++) {
+            if (filteredArgumentTypes[i] instanceof TypeVariable<?>) {
+                if (containsVariableTypeSameParametrizedTypeBound(((TypeVariable<?>) filteredArgumentTypes[i]), p)) {
+                    indexesToRemove = ArrayUtils.add(indexesToRemove, i);
+                }
+            }
+        }
+        return indexesToRemove;
+    }
+
+    private static boolean containsVariableTypeSameParametrizedTypeBound(TypeVariable<?> typeVariable, ParameterizedType p) {
+        return ArrayUtils.contains(typeVariable.getBounds(), p);
+    }
+
     /**
      * Format a {@link WildcardType} as a {@link String}.
      * @param w {@code WildcardType} to format
@@ -1840,7 +1876,7 @@ public class TypeUtils {
      * @return {@code buf}
      * @since 3.2
      */
-    private static StringBuilder appendAllTo(final StringBuilder buf, final String sep, final Type... types) {
+    private static <T> StringBuilder appendAllTo(final StringBuilder buf, final String sep, final T... types) {
         Validate.notEmpty(Validate.noNullElements(types));
         if (types.length > 0) {
             buf.append(toString(types[0]));
@@ -1851,4 +1887,8 @@ public class TypeUtils {
         return buf;
     }
 
+    private static <T> String toString(T object) {
+        return object instanceof Type ? toString((Type) object) : object.toString();
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/commons-lang/blob/cc6beb2d/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java b/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
index 1b88147..eea6b87 100644
--- a/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
+++ b/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java
@@ -781,6 +781,12 @@ public class TypeUtilsTest<B> {
         Assert.assertTrue(TypeUtils.isAssignable(fromType, failingToType));
     }
 
+    @Test
+    public void testLANG1348() throws Exception {
+        final Method method = Enum.class.getMethod("valueOf", Class.class, String.class);
+        Assert.assertEquals("T extends java.lang.Enum<T>", TypeUtils.toString(method.getGenericReturnType()));
+    }
+
     public Iterable<? extends Map<Integer, ? extends Collection<?>>> iterable;
 
     public static <G extends Comparable<G>> G stub() {


[2/2] [lang] LANG-1348: StackOverflowError on TypeUtils.toString(...) for a generic return type of Enum.valueOf

Posted by pa...@apache.org.
LANG-1348: StackOverflowError on TypeUtils.toString(...) for a generic return type of Enum.valueOf

add changes.xml entry


Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo
Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/00feb98f
Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/00feb98f
Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/00feb98f

Branch: refs/heads/master
Commit: 00feb98f807cf44c993296052726043a90d70b7e
Parents: cc6beb2
Author: pascalschumacher <pa...@gmx.net>
Authored: Sat Oct 7 11:54:38 2017 +0200
Committer: pascalschumacher <pa...@gmx.net>
Committed: Sat Oct 7 11:54:38 2017 +0200

----------------------------------------------------------------------
 src/changes/changes.xml | 1 +
 1 file changed, 1 insertion(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/commons-lang/blob/00feb98f/src/changes/changes.xml
----------------------------------------------------------------------
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ec74e49..187b5f0 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -46,6 +46,7 @@ The <action> type attribute can be add,update,fix,remove.
   <body>
 
   <release version="3.7" date="tba" description="tba">
+    <action issue="LANG-1348" type="fix" dev="pschumacher" due-to="mbusso">StackOverflowError on TypeUtils.toString(...) for a generic return type of Enum.valueOf</action>
     <action issue="LANG-1346" type="update" dev="pschumacher">Remove deprecation from RandomStringUtils</action>
     <action issue="LANG-1350" type="fix" dev="ggregory" due-to="Brett Kail">ConstructorUtils.invokeConstructor(Class, Object...) regression</action>
     <action issue="LANG-1349" type="fix" dev="pschumacher" due-to="Naman Nigam">EqualsBuilder#isRegistered: swappedPair construction bug</action>