Skip to content

Commit 1a22007

Browse files
nakamura-toclaude
andcommitted
Add comprehensive tests for ClassUtil and improve ClassLoader support
- Add ClassUtilTest with full coverage of all ClassUtil methods - Add new error messages (DOMAGEN0033-0035) for ClassLoader-specific errors - Improve ClassUtil implementation to properly handle ClassLoader parameter validation - Ensure proper separation between default and ClassLoader-based class loading 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent c3a5611 commit 1a22007

File tree

3 files changed

+155
-12
lines changed

3 files changed

+155
-12
lines changed

codegen/src/main/java/org/seasar/doma/gradle/codegen/message/Message.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ public enum Message implements MessageResource {
2626
"Cannot infer the driver class name from the property \"url\", so this plugin cannot create a DataSource instance. Correct the url property or specify the property \"dataSource\" explicitly."),
2727
DOMAGEN0025(
2828
"Cannot infer the dialect name from the property \"url\", so this plugin cannot create a CodeGenDialect instance. Correct the url property or specify the property \"codeGenDialect\" explicitly."),
29+
DOMAGEN0033("The class \"{1}\" to which the parameter \"{0}\" refers is not found. {2}"),
30+
DOMAGEN0034(
31+
"The class \"{1}\" to which the parameter \"{0}\" refers must be a subtype of the class \"{2}\"."),
32+
DOMAGEN0035(
33+
"The class \"{1}\" to which the parameter \"{0}\" refers cannot be instantiated. The class \"{1}\" must have a public default constructor. {2}"),
2934

3035
DOMAGEN5001(
3136
"The JDBC driver may not be loaded. Check that the JDBC driver is in the classpath. If the JDBC driver is not loaded automatically, load it explicitly using Class.forName. ex) Class.forName(\"oracle.jdbc.driver.OracleDriver\")"),

codegen/src/main/java/org/seasar/doma/gradle/codegen/util/ClassUtil.java

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,38 +57,46 @@ public static Class<?> toBoxedPrimitiveTypeIfPossible(Class<?> clazz) {
5757

5858
public static <T> T newInstance(Class<T> supertype, String className, String propertyName) {
5959
AssertionUtil.assertNotNull(supertype, className, propertyName);
60-
return newInstance(supertype, className, propertyName, null);
60+
Class<?> clazz = forName(className, propertyName);
61+
if (!supertype.isAssignableFrom(clazz)) {
62+
throw new CodeGenException(Message.DOMAGEN0014, propertyName, className, supertype.getName());
63+
}
64+
try {
65+
return supertype.cast(clazz.getDeclaredConstructor().newInstance());
66+
} catch (ReflectiveOperationException e) {
67+
throw new CodeGenException(Message.DOMAGEN0015, propertyName, className, e);
68+
}
6169
}
6270

6371
public static <T> T newInstance(
6472
Class<T> supertype, String className, String propertyName, ClassLoader classLoader) {
65-
AssertionUtil.assertNotNull(supertype, className, propertyName);
73+
AssertionUtil.assertNotNull(supertype, className, propertyName, classLoader);
6674
Class<?> clazz = forName(className, propertyName, classLoader);
6775
if (!supertype.isAssignableFrom(clazz)) {
68-
throw new CodeGenException(Message.DOMAGEN0014, propertyName, className, supertype.getName());
76+
throw new CodeGenException(Message.DOMAGEN0034, propertyName, className, supertype.getName());
6977
}
7078
try {
7179
return supertype.cast(clazz.getDeclaredConstructor().newInstance());
7280
} catch (ReflectiveOperationException e) {
73-
throw new CodeGenException(Message.DOMAGEN0015, propertyName, className, e);
81+
throw new CodeGenException(Message.DOMAGEN0035, propertyName, className, e);
7482
}
7583
}
7684

7785
public static Class<?> forName(String className, String propertyName) {
7886
AssertionUtil.assertNotNull(className, propertyName);
79-
return forName(className, propertyName, null);
87+
try {
88+
return Class.forName(className);
89+
} catch (ClassNotFoundException e) {
90+
throw new CodeGenException(Message.DOMAGEN0013, propertyName, className, e);
91+
}
8092
}
8193

8294
public static Class<?> forName(String className, String propertyName, ClassLoader classLoader) {
83-
AssertionUtil.assertNotNull(className, propertyName);
95+
AssertionUtil.assertNotNull(className, propertyName, classLoader);
8496
try {
85-
if (classLoader != null) {
86-
return classLoader.loadClass(className);
87-
} else {
88-
return Class.forName(className);
89-
}
97+
return classLoader.loadClass(className);
9098
} catch (ClassNotFoundException e) {
91-
throw new CodeGenException(Message.DOMAGEN0013, propertyName, className, e);
99+
throw new CodeGenException(Message.DOMAGEN0033, propertyName, className, e);
92100
}
93101
}
94102
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
package org.seasar.doma.gradle.codegen.util;
2+
3+
import static org.junit.jupiter.api.Assertions.assertEquals;
4+
import static org.junit.jupiter.api.Assertions.assertInstanceOf;
5+
import static org.junit.jupiter.api.Assertions.assertSame;
6+
import static org.junit.jupiter.api.Assertions.assertThrows;
7+
8+
import java.net.URL;
9+
import java.net.URLClassLoader;
10+
import java.util.ArrayList;
11+
import java.util.List;
12+
import org.junit.jupiter.api.Test;
13+
import org.seasar.doma.gradle.codegen.exception.CodeGenException;
14+
15+
@SuppressWarnings("unchecked")
16+
public class ClassUtilTest {
17+
18+
@Test
19+
public void testGetPackageName() {
20+
assertEquals("java.lang", ClassUtil.getPackageName("java.lang.String"));
21+
assertEquals("", ClassUtil.getPackageName("String"));
22+
assertEquals("", ClassUtil.getPackageName(""));
23+
}
24+
25+
@Test
26+
public void testGetSimpleName() {
27+
assertEquals("String", ClassUtil.getSimpleName("java.lang.String"));
28+
assertEquals("String", ClassUtil.getSimpleName("String"));
29+
assertEquals("", ClassUtil.getSimpleName(""));
30+
}
31+
32+
@Test
33+
public void testToBoxedPrimitiveTypeIfPossible() {
34+
assertSame(Void.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(void.class));
35+
assertSame(Character.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(char.class));
36+
assertSame(Boolean.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(boolean.class));
37+
assertSame(Byte.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(byte.class));
38+
assertSame(Short.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(short.class));
39+
assertSame(Integer.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(int.class));
40+
assertSame(Long.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(long.class));
41+
assertSame(Float.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(float.class));
42+
assertSame(Double.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(double.class));
43+
assertSame(String.class, ClassUtil.toBoxedPrimitiveTypeIfPossible(String.class));
44+
}
45+
46+
@Test
47+
public void testNewInstance() {
48+
List<String> list = ClassUtil.newInstance(List.class, "java.util.ArrayList", "testProperty");
49+
assertInstanceOf(ArrayList.class, list);
50+
}
51+
52+
@Test
53+
public void testNewInstance_WithClassLoader() throws Exception {
54+
URLClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
55+
List<String> list =
56+
ClassUtil.newInstance(List.class, "java.util.ArrayList", "testProperty", classLoader);
57+
assertInstanceOf(ArrayList.class, list);
58+
}
59+
60+
@Test
61+
public void testNewInstance_ClassNotFound() {
62+
assertThrows(
63+
CodeGenException.class,
64+
() -> {
65+
ClassUtil.newInstance(List.class, "non.existent.Class", "testProperty");
66+
});
67+
}
68+
69+
@Test
70+
public void testNewInstance_NotAssignable() {
71+
assertThrows(
72+
CodeGenException.class,
73+
() -> {
74+
ClassUtil.newInstance(List.class, "java.lang.String", "testProperty");
75+
});
76+
}
77+
78+
@Test
79+
public void testNewInstance_WithClassLoader_ClassNotFound() throws Exception {
80+
URLClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
81+
assertThrows(
82+
CodeGenException.class,
83+
() -> {
84+
ClassUtil.newInstance(List.class, "non.existent.Class", "testProperty", classLoader);
85+
});
86+
}
87+
88+
@Test
89+
public void testNewInstance_WithClassLoader_NotAssignable() throws Exception {
90+
try (URLClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader())) {
91+
assertThrows(
92+
CodeGenException.class,
93+
() -> {
94+
ClassUtil.newInstance(List.class, "java.lang.String", "testProperty", classLoader);
95+
});
96+
}
97+
}
98+
99+
@Test
100+
public void testForName() {
101+
Class<?> clazz = ClassUtil.forName("java.lang.String", "testProperty");
102+
assertSame(String.class, clazz);
103+
}
104+
105+
@Test
106+
public void testForName_WithClassLoader() throws Exception {
107+
URLClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
108+
Class<?> clazz = ClassUtil.forName("java.lang.String", "testProperty", classLoader);
109+
assertSame(String.class, clazz);
110+
}
111+
112+
@Test
113+
public void testForName_ClassNotFound() {
114+
assertThrows(
115+
CodeGenException.class,
116+
() -> {
117+
ClassUtil.forName("non.existent.Class", "testProperty");
118+
});
119+
}
120+
121+
@Test
122+
public void testForName_WithClassLoader_ClassNotFound() throws Exception {
123+
URLClassLoader classLoader = new URLClassLoader(new URL[0], getClass().getClassLoader());
124+
assertThrows(
125+
CodeGenException.class,
126+
() -> {
127+
ClassUtil.forName("non.existent.Class", "testProperty", classLoader);
128+
});
129+
}
130+
}

0 commit comments

Comments
 (0)