Utilities to use Java reflection without all of the checked exceptions
import java.lang.reflect.Array;
import java.lang.reflect.Method;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
/**
*
* ReflectUtils is a collection of utilities that allows you to leverage Java
* reflection without all of the checked exceptions (they are converted to
* runtime exceptions or return values). This class was created to get around
* the fact that the classes in java.lang.reflect.* turn every event into an
* exception, which is often cumbersome or inaccurate.
*
* @author Dan Jemiolo (danj)
*
*/
class ReflectUtils {
//
// The class loader used by this class
//
private static final ClassLoader _DEFAULT_CLASS_LOADER;
//
// The class loader used by this class
//
private static ReflectUtilHelper _helper = null;
static {
//
// load the default class loader (we need an instance to do so)
//
ReflectUtils instance = new ReflectUtils();
_DEFAULT_CLASS_LOADER = instance.getClass().getClassLoader();
_helper = null;
}
/**
*
* @param className
* The qualified name of the class to search for.
*
* @return True if the class is in the JVM's classpath.
*
*/
public static boolean exists(String className) {
if (_helper != null)
return _helper.exists(className);
try {
Class.forName(className);
return true;
}
catch (ClassNotFoundException error) {
return false;
}
}
/**
*
* @param className
* The qualified name of the class to search for.
*
* @param classLoader
* The class loader to use in the class lookup.
*
* @return True if the class is in the JVM's classpath.
*
*/
public static boolean exists(String className, ClassLoader classLoader) {
try {
classLoader.loadClass(className);
return true;
}
catch (ClassNotFoundException error) {
return false;
}
}
/**
*
* @param theClass
* A "normal", non-array type.
*
* @return The array version of the given type. For example, if you pass
* <em>String.class</em>, you get <em>String[].class</em>. If
* you pass <em>int.class</em>, you get <em>int[].class</em>. If
* the given class is already an array type, it is returned.
*
* @see #getClassFromArrayClass(Class)
*
*/
public static Class getArrayClassFromClass(Class theClass) {
if (theClass.isArray())
return theClass;
return Array.newInstance(theClass, 0).getClass();
}
/**
*
* This method calls getClass(Class, ClassLoader) with this class'
* ClassLoader.
*
* @param className
* The name of the class to load.
*
* @return The Class representing the given class name. A RuntimeException is
* thrown if the class is not found.
*
* @see #exists(String)
*
*/
public static Class getClass(String className) {
if (_helper != null) {
Class clazz = _helper.getClass(className);
if (clazz != null)
return clazz;
}
return getClass(className, _DEFAULT_CLASS_LOADER);
}
/**
*
* @param className
* The name of the class to load.
*
* @param classLoader
* The class loader to use for class lookup.
*
* @return The Class representing the given class name. A RuntimeException is
* thrown if the class is not found.
*
* @see #exists(String)
*
*/
public static Class getClass(String className, ClassLoader classLoader) {
try {
return classLoader.loadClass(className);
}
catch (Throwable error) {
//
// if it failed, try the default loader, if applicable
//
if (_helper != null) {
Class clzz = _helper.getClass(className);
if (clzz != null)
return clzz;
}
if (classLoader != _DEFAULT_CLASS_LOADER) {
try {
return _DEFAULT_CLASS_LOADER.loadClass(className);
}
catch (Throwable error2) {
//
// still failed - ignore this one and throw from the
// original error
//
}
}
Object[] filler = { className };
String message = "JavaClassNotFound";
throw new RuntimeException(message);
}
}
/**
*
* @param arrayClass
* The array version of a given type (<em>YourType[].class</em>)
*
* @return The non-array version of the given type. For example, if you pass
* <em>String[].class</em>, you get <em>String.class</em>. If
* you pass <em>int[].class</em>, you get <em>int.class</em>.
*
* @see #getArrayClassFromClass(Class)
*
*/
public static Class getClassFromArrayClass(Class arrayClass) {
if (arrayClass == null)
throw new NullPointerException("NullClass");
String name = arrayClass.getName();
//
// make sure it's an array type
//
if (name.charAt(0) != '[') {
Object[] filler = { name };
throw new RuntimeException("NotArrayClass");
}
if (name.charAt(1) == '[') {
Object[] filler = { name };
throw new RuntimeException("NoMultiArrays");
}
//
// the char after the [ signifies the type of the array. these
// values are documented with java.lang.Class.getName()
//
char type = name.charAt(1);
switch (type) {
case 'Z':
return boolean.class;
case 'B':
return byte.class;
case 'C':
return char.class;
case 'D':
return double.class;
case 'F':
return float.class;
case 'I':
return int.class;
case 'J':
return long.class;
case 'S':
return short.class;
case 'L':
return getClass(name.substring(2, name.length() - 1));
default:
Object[] filler = { name, new Character(type) };
String message = "UnsupportedType";
throw new RuntimeException(message);
}
}
public static Method getFirstMethod(Class theClass, String name) {
Method[] methods = theClass.getMethods();
for (int n = 0; n < methods.length; ++n)
if (name.equals(methods[n].getName()))
return methods[n];
return null;
}
/**
*
* @param theClass
*
* @return The full name of the Java package that contains the given class, or
* null if the class is not in a package.
*
*/
public static String getPackageName(Class theClass) {
//
// NOTE: Using the Package would be the easiest way to get this
// data, but the ClassLoader is not required to provide it. Thus,
// we use the more reliable method of parsing the class name.
//
//
// arrays will have the [ as part of their name - no good
//
if (theClass.isArray())
theClass = getClassFromArrayClass(theClass);
return getPackageName(theClass.getName());
}
/**
*
* @param qualifiedName
*
* @return The full name of the Java package that contains the given class, or
* null if the class is not in a package.
*
*/
public static String getPackageName(String qualifiedName) {
int dot = qualifiedName.lastIndexOf('.');
return dot >= 0 ? qualifiedName.substring(0, dot) : null;
}
/**
*
* @param type
*
* @return The unqualified (local) name of the class/interface. If the type is
* an array, the [] characters will be appended.
*
*/
public static String getShortName(Class type) {
if (type.isArray()) {
Class base = getClassFromArrayClass(type);
String name = getShortName(base);
return name + "[]";
}
return getShortName(type.getName());
}
/**
*
* @param qualifiedName
*
* @return The unqualified (local) name.
*
*/
public static String getShortName(String qualifiedName) {
int dot = qualifiedName.lastIndexOf('.');
return qualifiedName.substring(dot + 1);
}
/**
*
* Invokes the Class.newInstance() method on the given Class.
*
* @param theClass
* The type to instantiate.
*
* @return An object of the given type, created with the default constructor.
* A RuntimeException is thrown if the object could not be created.
*
*/
public static Object newInstance(Class theClass) {
try {
return theClass.newInstance();
}
catch (InstantiationException error) {
Object[] filler = { theClass };
String message = "ObjectCreationFailed";
throw new RuntimeException(message);
}
catch (IllegalAccessException error) {
Object[] filler = { theClass };
String message = "DefaultConstructorHidden";
throw new RuntimeException(message);
}
}
/**
*
* This is a convenience method that invokes newInstance(Class) with a Class
* object representing the given type.
*
* @see #getClass(String, ClassLoader)
* @see #newInstance(Class)
*
*/
public static Object newInstance(String className) {
return newInstance(getClass(className));
}
/**
*
* This is a convenience method that invokes newInstance(Class) with a Class
* object loaded by the given ClassLoader
*
* @see #getClass(String, ClassLoader)
* @see #newInstance(Class)
*
*/
public static Object newInstance(String className, ClassLoader classLoader) {
return newInstance(getClass(className, classLoader));
}
/**
*
* This is a setter for the helper object
*
*/
public static void setHelper(ReflectUtilHelper helper) {
_helper = helper;
}
}
/**
*
* @author Joel Hawkins
*
*/
interface ReflectUtilHelper {
boolean exists(String className);
Class getClass(String className);
}
Related examples in the same category