diff options
-rw-r--r-- | src/changes/changes.xml | 1 | ||||
-rw-r--r-- | src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java | 25 | ||||
-rw-r--r-- | src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java | 17 |
3 files changed, 40 insertions, 3 deletions
diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 7eba1df85..f56258941 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -119,6 +119,7 @@ The <action> type attribute can be add,update,fix,remove. <action type="fix" dev="ggregory" due-to="Gary Gregory">Make ArrayUtils.removeAll() null-safe.</action> <action type="fix" dev="ggregory" due-to="Philipp Trulson, Gary Gregory">Fix Java version in README.md #1170.</action> <action type="fix" dev="ggregory" due-to="Stephan Peters, Gary Gregory, Bernd">StringUtils.stripAccents() should handle ligatures, UTF32 math blocks, etc. #1201.</action> + <action issue="LANG-1524" type="fix" dev="ggregory" due-to="kijong.youn, Aakash Gupta, Gary Gregory">TypeUtils.toString(Type) StackOverflowError for an inner class in the inner class parameterized enclosing class #657.</action> <!-- UPDATE --> <action type="update" dev="sebb" due-to="Dependabot">Bump commons-parent from 64 to 69 #1194.</action> <action type="update" dev="ggregory" due-to="Dependabot">Bump org.codehaus.mojo:exec-maven-plugin from 3.1.1 to 3.2.0 #1175.</action> 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 8533ea3be..cd0f437ae 100644 --- a/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java +++ b/src/main/java/org/apache/commons/lang3/reflect/TypeUtils.java @@ -16,6 +16,7 @@ */ package org.apache.commons.lang3.reflect; +import java.lang.reflect.AnnotatedType; import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.GenericDeclaration; @@ -325,15 +326,15 @@ public class TypeUtils { * * @param cls {@link Class} to format * @return String - * @since 3.2 */ private static String classToString(final Class<?> cls) { if (cls.isArray()) { return toString(cls.getComponentType()) + "[]"; } - + if (isCyclical(cls)) { + return cls.getSimpleName() + "(cycle)"; + } final StringBuilder buf = new StringBuilder(); - if (cls.getEnclosingClass() != null) { buf.append(classToString(cls.getEnclosingClass())).append('.').append(cls.getSimpleName()); } else { @@ -1427,6 +1428,24 @@ public class TypeUtils { } /** + * Tests whether the class contains a cyclical reference in the qualified name of a class. If any of the type parameters of A class is extending X class + * which is in scope of A class, then it forms cycle. + * + * @param cls the class to test. + * @return whether the class contains a cyclical reference. + */ + private static boolean isCyclical(final Class<?> cls) { + for (final TypeVariable<?> typeParameter : cls.getTypeParameters()) { + for (final AnnotatedType annotatedBound : typeParameter.getAnnotatedBounds()) { + if (annotatedBound.getType().getTypeName().contains(cls.getName())) { + return true; + } + } + } + return false; + } + + /** * Tests if the given value can be assigned to the target type * following the Java generics rules. * 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 ce5051413..dca2096b5 100644 --- a/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/reflect/TypeUtilsTest.java @@ -56,6 +56,16 @@ import org.apache.commons.lang3.reflect.testbed.StringParameterizedChild; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +/** + * Test fixture for https://issues.apache.org/jira/browse/LANG-1524 + */ +class AAAAClass<T extends AAAAClass.BBBBClass.CCCClass> { + public static class BBBBClass { + public static class CCCClass { + } + } +} + final class AAAClass extends AAClass<String> { public class BBBClass extends BBClass<String> { // empty @@ -261,6 +271,13 @@ public class TypeUtilsTest<B> extends AbstractLangTest { assertEquals("T extends java.lang.Enum<T>", TypeUtils.toString(method.getGenericReturnType())); } + @Test + public void test_LANG_1524() { + assertEquals("AAAAClass(cycle).BBBBClass.CCCClass", TypeUtils.toString(AAAAClass.BBBBClass.CCCClass.class)); + assertEquals("AAAAClass(cycle).BBBBClass", TypeUtils.toString(AAAAClass.BBBBClass.class)); + assertEquals("AAAAClass(cycle)", TypeUtils.toString(AAAAClass.class)); + } + /** * <pre>{@code * java.lang.StackOverflowError |