Skip to content

Commit fa3c9db

Browse files
committed
Migrate ClassUtils.loadClass methods to Types.load
The Types utility class is the central place for type-related utility methods going forward.
1 parent 37302c4 commit fa3c9db

4 files changed

Lines changed: 246 additions & 220 deletions

File tree

src/main/java/org/scijava/util/ClassUtils.java

Lines changed: 32 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -89,135 +89,6 @@ private ClassUtils() {
8989

9090
// -- Class loading, querying and reflection --
9191

92-
/**
93-
* Loads the class with the given name, using the current thread's context
94-
* class loader, or null if it cannot be loaded.
95-
*
96-
* @param name The name of the class to load.
97-
* @return The loaded class, or null if the class could not be loaded.
98-
* @see #loadClass(String, ClassLoader, boolean)
99-
*/
100-
public static Class<?> loadClass(final String name) {
101-
return loadClass(name, null, true);
102-
}
103-
104-
/**
105-
* Loads the class with the given name, using the specified
106-
* {@link ClassLoader}, or null if it cannot be loaded.
107-
*
108-
* @param name The name of the class to load.
109-
* @param classLoader The class loader with which to load the class; if null,
110-
* the current thread's context class loader will be used.
111-
* @return The loaded class, or null if the class could not be loaded.
112-
* @see #loadClass(String, ClassLoader, boolean)
113-
*/
114-
public static Class<?> loadClass(final String name,
115-
final ClassLoader classLoader)
116-
{
117-
return loadClass(name, classLoader, true);
118-
}
119-
120-
/**
121-
* Loads the class with the given name, using the current thread's context
122-
* class loader.
123-
*
124-
* @param className the name of the class to load
125-
* @param quietly Whether to return {@code null} (rather than throwing
126-
* {@link IllegalArgumentException}) if something goes wrong loading
127-
* the class
128-
* @return The loaded class, or {@code null} if the class could not be loaded
129-
* and the {@code quietly} flag is set.
130-
* @see #loadClass(String, ClassLoader, boolean)
131-
* @throws IllegalArgumentException If the class cannot be loaded and the
132-
* {@code quietly} flag is not set.
133-
*/
134-
public static Class<?> loadClass(final String className,
135-
final boolean quietly)
136-
{
137-
return loadClass(className, null, quietly);
138-
}
139-
140-
/**
141-
* Loads the class with the given name, using the specified
142-
* {@link ClassLoader}, or null if it cannot be loaded.
143-
* <p>
144-
* This method is capable of parsing several different class name syntaxes. In
145-
* particular, array classes (including primitives) represented using either
146-
* square brackets or internal Java array name syntax are supported. Examples:
147-
* </p>
148-
* <ul>
149-
* <li>{@code boolean} is loaded as {@code boolean.class}</li>
150-
* <li>{@code Z} is loaded as {@code boolean.class}</li>
151-
* <li>{@code double[]} is loaded as {@code double[].class}</li>
152-
* <li>{@code string[]} is loaded as {@code java.lang.String.class}</li>
153-
* <li>{@code [F} is loaded as {@code float[].class}</li>
154-
* </ul>
155-
*
156-
* @param name The name of the class to load.
157-
* @param classLoader The class loader with which to load the class; if null,
158-
* the current thread's context class loader will be used.
159-
* @param quietly Whether to return {@code null} (rather than throwing
160-
* {@link IllegalArgumentException}) if something goes wrong loading
161-
* the class
162-
* @return The loaded class, or {@code null} if the class could not be loaded
163-
* and the {@code quietly} flag is set.
164-
* @throws IllegalArgumentException If the class cannot be loaded and the
165-
* {@code quietly} flag is not set.
166-
*/
167-
public static Class<?> loadClass(final String name,
168-
final ClassLoader classLoader, final boolean quietly)
169-
{
170-
// handle primitive types
171-
if (name.equals("Z") || name.equals("boolean")) return boolean.class;
172-
if (name.equals("B") || name.equals("byte")) return byte.class;
173-
if (name.equals("C") || name.equals("char")) return char.class;
174-
if (name.equals("D") || name.equals("double")) return double.class;
175-
if (name.equals("F") || name.equals("float")) return float.class;
176-
if (name.equals("I") || name.equals("int")) return int.class;
177-
if (name.equals("J") || name.equals("long")) return long.class;
178-
if (name.equals("S") || name.equals("short")) return short.class;
179-
if (name.equals("V") || name.equals("void")) return void.class;
180-
181-
// handle built-in class shortcuts
182-
final String className;
183-
if (name.equals("string")) className = "java.lang.String";
184-
else className = name;
185-
186-
// handle source style arrays (e.g.: "java.lang.String[]")
187-
if (name.endsWith("[]")) {
188-
final String elementClassName = name.substring(0, name.length() - 2);
189-
return Types.array(loadClass(elementClassName, classLoader));
190-
}
191-
192-
// handle non-primitive internal arrays (e.g.: "[Ljava.lang.String;")
193-
if (name.startsWith("[L") && name.endsWith(";")) {
194-
final String elementClassName = name.substring(2, name.length() - 1);
195-
return Types.array(loadClass(elementClassName, classLoader));
196-
}
197-
198-
// handle other internal arrays (e.g.: "[I", "[[I", "[[Ljava.lang.String;")
199-
if (name.startsWith("[")) {
200-
final String elementClassName = name.substring(1);
201-
return Types.array(loadClass(elementClassName, classLoader));
202-
}
203-
204-
// load the class!
205-
try {
206-
final ClassLoader cl =
207-
classLoader == null ? Thread.currentThread().getContextClassLoader()
208-
: classLoader;
209-
return cl.loadClass(className);
210-
}
211-
catch (final Throwable t) {
212-
// NB: Do not allow any failure to load the class to crash us.
213-
// Not ClassNotFoundException.
214-
// Not NoClassDefFoundError.
215-
// Not UnsupportedClassVersionError!
216-
if (quietly) return null;
217-
throw new IllegalArgumentException("Cannot load class: " + className, t);
218-
}
219-
}
220-
22192
/** Checks whether a class with the given name exists. */
22293
public static boolean hasClass(final String className) {
22394
return hasClass(className, null);
@@ -724,6 +595,38 @@ private static <T extends AnnotatedElement> void populateCache(
724595

725596
// -- Deprecated methods --
726597

598+
/** @deprecated Use {@link Types#load(String)} instead. */
599+
@Deprecated
600+
public static Class<?> loadClass(final String name) {
601+
return Types.load(name);
602+
}
603+
604+
/** @deprecated Use {@link Types#load(String, ClassLoader)} instead. */
605+
@Deprecated
606+
public static Class<?> loadClass(final String name,
607+
final ClassLoader classLoader)
608+
{
609+
return Types.load(name, classLoader);
610+
}
611+
612+
/** @deprecated Use {@link Types#load(String, boolean)} instead. */
613+
@Deprecated
614+
public static Class<?> loadClass(final String className,
615+
final boolean quietly)
616+
{
617+
return Types.load(className, quietly);
618+
}
619+
620+
/**
621+
* @deprecated Use {@link Types#load(String, ClassLoader, boolean)} instead.
622+
*/
623+
@Deprecated
624+
public static Class<?> loadClass(final String name,
625+
final ClassLoader classLoader, final boolean quietly)
626+
{
627+
return Types.load(name, classLoader, quietly);
628+
}
629+
727630
/** @deprecated use {@link ConversionUtils#convert(Object, Class)} */
728631
@Deprecated
729632
public static <T> T convert(final Object value, final Class<T> type) {

src/main/java/org/scijava/util/Types.java

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,132 @@ private Types() {
8282
// NB: Prevent instantiation of utility class.
8383
}
8484

85+
/**
86+
* Loads the class with the given name, using the current thread's context
87+
* class loader, or null if it cannot be loaded.
88+
*
89+
* @param name The name of the class to load.
90+
* @return The loaded class, or null if the class could not be loaded.
91+
* @see #load(String, ClassLoader, boolean)
92+
*/
93+
public static Class<?> load(final String name) {
94+
return load(name, null, true);
95+
}
96+
97+
/**
98+
* Loads the class with the given name, using the specified
99+
* {@link ClassLoader}, or null if it cannot be loaded.
100+
*
101+
* @param name The name of the class to load.
102+
* @param classLoader The class loader with which to load the class; if null,
103+
* the current thread's context class loader will be used.
104+
* @return The loaded class, or null if the class could not be loaded.
105+
* @see #load(String, ClassLoader, boolean)
106+
*/
107+
public static Class<?> load(final String name,
108+
final ClassLoader classLoader)
109+
{
110+
return load(name, classLoader, true);
111+
}
112+
113+
/**
114+
* Loads the class with the given name, using the current thread's context
115+
* class loader.
116+
*
117+
* @param className the name of the class to load.
118+
* @param quietly Whether to return {@code null} (rather than throwing
119+
* {@link IllegalArgumentException}) if something goes wrong loading
120+
* the class.
121+
* @return The loaded class, or {@code null} if the class could not be loaded
122+
* and the {@code quietly} flag is set.
123+
* @see #load(String, ClassLoader, boolean)
124+
* @throws IllegalArgumentException If the class cannot be loaded and the
125+
* {@code quietly} flag is not set.
126+
*/
127+
public static Class<?> load(final String className, final boolean quietly) {
128+
return load(className, null, quietly);
129+
}
130+
131+
/**
132+
* Loads the class with the given name, using the specified
133+
* {@link ClassLoader}, or null if it cannot be loaded.
134+
* <p>
135+
* This method is capable of parsing several different class name syntaxes. In
136+
* particular, array classes (including primitives) represented using either
137+
* square brackets or internal Java array name syntax are supported. Examples:
138+
* </p>
139+
* <ul>
140+
* <li>{@code boolean} is loaded as {@code boolean.class}</li>
141+
* <li>{@code Z} is loaded as {@code boolean.class}</li>
142+
* <li>{@code double[]} is loaded as {@code double[].class}</li>
143+
* <li>{@code string[]} is loaded as {@code java.lang.String.class}</li>
144+
* <li>{@code [F} is loaded as {@code float[].class}</li>
145+
* </ul>
146+
*
147+
* @param name The name of the class to load.
148+
* @param classLoader The class loader with which to load the class; if null,
149+
* the current thread's context class loader will be used.
150+
* @param quietly Whether to return {@code null} (rather than throwing
151+
* {@link IllegalArgumentException}) if something goes wrong loading
152+
* the class
153+
* @return The loaded class, or {@code null} if the class could not be loaded
154+
* and the {@code quietly} flag is set.
155+
* @throws IllegalArgumentException If the class cannot be loaded and the
156+
* {@code quietly} flag is not set.
157+
*/
158+
public static Class<?> load(final String name, final ClassLoader classLoader,
159+
final boolean quietly)
160+
{
161+
// handle primitive types
162+
if (name.equals("Z") || name.equals("boolean")) return boolean.class;
163+
if (name.equals("B") || name.equals("byte")) return byte.class;
164+
if (name.equals("C") || name.equals("char")) return char.class;
165+
if (name.equals("D") || name.equals("double")) return double.class;
166+
if (name.equals("F") || name.equals("float")) return float.class;
167+
if (name.equals("I") || name.equals("int")) return int.class;
168+
if (name.equals("J") || name.equals("long")) return long.class;
169+
if (name.equals("S") || name.equals("short")) return short.class;
170+
if (name.equals("V") || name.equals("void")) return void.class;
171+
172+
// handle built-in class shortcuts
173+
final String className;
174+
if (name.equals("string")) className = "java.lang.String";
175+
else className = name;
176+
177+
// handle source style arrays (e.g.: "java.lang.String[]")
178+
if (name.endsWith("[]")) {
179+
final String elementClassName = name.substring(0, name.length() - 2);
180+
return arrayOrNull(load(elementClassName, classLoader));
181+
}
182+
183+
// handle non-primitive internal arrays (e.g.: "[Ljava.lang.String;")
184+
if (name.startsWith("[L") && name.endsWith(";")) {
185+
final String elementClassName = name.substring(2, name.length() - 1);
186+
return arrayOrNull(load(elementClassName, classLoader));
187+
}
188+
189+
// handle other internal arrays (e.g.: "[I", "[[I", "[[Ljava.lang.String;")
190+
if (name.startsWith("[")) {
191+
final String elementClassName = name.substring(1);
192+
return arrayOrNull(load(elementClassName, classLoader));
193+
}
194+
195+
// load the class!
196+
try {
197+
final ClassLoader cl = classLoader == null ? Thread.currentThread()
198+
.getContextClassLoader() : classLoader;
199+
return cl.loadClass(className);
200+
}
201+
catch (final Throwable t) {
202+
// NB: Do not allow any failure to load the class to crash us.
203+
// Not ClassNotFoundException.
204+
// Not NoClassDefFoundError.
205+
// Not UnsupportedClassVersionError!
206+
if (quietly) return null;
207+
throw new IllegalArgumentException("Cannot load class: " + className, t);
208+
}
209+
}
210+
85211
/**
86212
* Gets a string representation of the given type.
87213
*
@@ -435,6 +561,17 @@ public static final ParameterizedType parameterize(final Class<?> raw,
435561
return TypeUtils.parameterize(raw, typeArgMappings);
436562
}
437563

564+
// -- Helper methods --
565+
566+
private static Class<?> arrayOrNull(final Class<?> componentType) {
567+
try {
568+
return Types.array(componentType);
569+
}
570+
catch (final IllegalArgumentException exc) {
571+
return null;
572+
}
573+
}
574+
438575
// -- BEGIN FORK OF APACHE COMMONS LANG 3.4 CODE --
439576

440577
/*

0 commit comments

Comments
 (0)