de.invation.code.toval.reflect.ReflectionUtils Maven / Gradle / Ivy
package de.invation.code.toval.reflect;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import de.invation.code.toval.validate.ParameterException;
import de.invation.code.toval.validate.Validate;
/**
* A collection of helpful methods for finding subclasses, superclasses, and
* implemented interfaces for given classes and interfaces.
*
* @version 1.0
* @author Adrian Lange
*/
public class ReflectionUtils {
/** Suffix for array class names: "[]" */
public static final String ARRAY_SUFFIX = "[]";
/** Separator for the class name suffix: "." */
public static final String CLASS_SUFFIX_SEPARATOR = ".";
/** The ".class" file suffix */
public static final String CLASS_FILE_SUFFIX = CLASS_SUFFIX_SEPARATOR + "class";
/** Name pattern for package name elements: "[a-z0-9]*" */
public static final String PACKAGE_NAME_PATTERN = "[a-z0-9]*";
/** Separator for package name elements: "." */
public static final String PACKAGE_SEPARATOR = ".";
/** Separator for package name elements in path form: "/" */
public static final String PACKAGE_PATH_SEPARATOR = "/";
public static Set> getClassesInPackage(String packageName, boolean recursive) throws ReflectionException{
Validate.notNull(packageName);
Validate.notEmpty(packageName);
try {
String packagePath = packageName.replace(PACKAGE_SEPARATOR, PACKAGE_PATH_SEPARATOR);
URL packageURL = Thread.currentThread().getContextClassLoader().getResource(packagePath);
Set> classes = new HashSet>();
try {
BufferedReader in = new BufferedReader(new InputStreamReader(packageURL.openStream()));
String line = null;
while ((line = in.readLine()) != null) {
if (line.endsWith(CLASS_FILE_SUFFIX)) { // class, enum, or
// interface
String className = line.substring(0, line.lastIndexOf(CLASS_SUFFIX_SEPARATOR));
try {
Class> currentClass = Class.forName(packageName + PACKAGE_SEPARATOR + className);
classes.add(currentClass);
} catch (ClassNotFoundException e) {
throw new ReflectionException("Cannot locate class \"" + className + "\"", e);
}
} else if (line.matches(PACKAGE_NAME_PATTERN) && recursive) { // package
// recursive call to add classes in the package
classes.addAll(getClassesInPackage(packageName + PACKAGE_SEPARATOR + line, recursive));
}
}
} catch (IOException e) {
throw new ReflectionException("Cannot access package directory", e);
}
return classes;
} catch (Exception e) {
throw new ReflectionException(e);
}
}
/**
* The same method as {@link #getSubclassesInPackage(Class, String, boolean)},
* but with the possibility to search in multiple packages. Since the result
* is returned as a {@link Set}, there won't be any duplicates.
* @throws ReflectionException
*/
public static Set> getClassesInPackages(List packageNames, boolean recursive) throws ReflectionException {
Validate.notNull(packageNames);
Set> classes = new HashSet>();
for (String packageName : packageNames) {
classes.addAll(getClassesInPackage(packageName, recursive));
}
return classes;
}
/**
*
* Returns a {@link List} of {@link Class} objects containing all classes of
* a specified package (including subpackages) which extend the given class.
*
*
* Example:
*
*
*
* String pack = "de.uni.freiburg.iig.telematik.sepia";
* Class<?> superclass = AbstractPlace.class;
* List<Class<?>> classes = ReflectionUtils.getSubclasses(superclass, pack);
* for (Class<?> c : classes) {
* System.out.println(c);
* }
*
* // class de.uni.freiburg.iig.telematik.sepia.petrinet.cpn.abstr.AbstractCPNPlace
* // class de.uni.freiburg.iig.telematik.sepia.petrinet.cpn.CPNPlace
* // class
* // de.uni.freiburg.iig.telematik.sepia.petrinet.ifnet.abstr.AbstractIFNetPlace
* // class de.uni.freiburg.iig.telematik.sepia.petrinet.ifnet.IFNetPlace
* // class de.uni.freiburg.iig.telematik.sepia.petrinet.pt.abstr.AbstractPTPlace
* // class de.uni.freiburg.iig.telematik.sepia.petrinet.pt.PTPlace
*
*
* @param clazz
* Class which should be extended.
* @param packageName
* Package to search for subclasses.
* @return {@link List} of {@link Class} objects extending the given class
* in the specified package.
* @throws ReflectionException
*/
public static Set> getSubclassesInPackage(Class> clazz, String packageName, boolean recursive) throws ReflectionException {
Validate.notNull(clazz);
if (clazz.isInterface() || clazz.isEnum()) {
throw new ParameterException("Parameter is not a class");
}
Set> classesInPackage = getClassesInPackage(packageName, recursive);
try{
Set> subClassesInPackage = new HashSet>();
for (Class> classInPackage : classesInPackage) {
if (getSuperclasses(classInPackage).contains(clazz) && clazz != classInPackage) {
subClassesInPackage.add(classInPackage);
}
}
return subClassesInPackage;
} catch(Exception e){
throw new ReflectionException(e);
}
}
/**
*
* Returns a {@link Set} of {@link Class} objects containing all classes of
* a specified package (including subpackages) which implement the given
* interface.
*
*
* Example:
*
*
*
* String pack = "de.uni.freiburg.iig.telematik.sepia";
* Class<?> interf = PNParserInterface.class;
* Set<Class<?>> classes = ReflectionUtils.getInterfaceImplementations(interf, pack);
* for (Class<?> c : classes) {
* System.out.println(c);
* }
*
* // class de.uni.freiburg.iig.telematik.sepia.parser.petrify.PetrifyParser
* // class de.uni.freiburg.iig.telematik.sepia.parser.pnml.PNMLParser
*
*
* @param interfaze
* Interface which should be implemented.
* @param packageName
* Package to search for classes.
* @return {@link Set} of {@link Class} objects implementing the given
* interface in the specified package.
* @throws ReflectionException
*/
public static Set> getInterfaceImplementationsInPackage(Class> interfaze, String packageName, boolean recursive) throws ReflectionException {
Validate.notNull(interfaze);
if (!interfaze.isInterface()) {
throw new ParameterException("Parameter is not an interface");
}
Set> classesInPackage = getClassesInPackage(packageName, recursive);
try{
Set> interfaceImplamantationsInPackage = new HashSet>();
for (Class> classInPackage : classesInPackage) {
if (getInterfaces(classInPackage).contains(interfaze)) {
interfaceImplamantationsInPackage.add(classInPackage);
}
}
return interfaceImplamantationsInPackage;
} catch(Exception e){
throw new ReflectionException(e);
}
}
/**
* The same method as
* {@link ReflectionUtils#getInterfaceImplementationsInPackage(Class, String, boolean)}, but
* with the possibility to search in multiple packages. Since the result is
* returned as a {@link Set}, there won't be any duplicates.
* @throws ReflectionException
*/
public static Set> getInterfaceImplementationsInPackages(Class> interfaze, List packageNames, boolean recursive) throws ReflectionException {
Validate.notNull(interfaze);
Validate.notNull(packageNames);
if (!interfaze.isInterface()) {
throw new ParameterException("Parameter is not an interface");
}
Set> classes = new HashSet>();
for (String packageName : packageNames) {
classes.addAll(getInterfaceImplementationsInPackage(interfaze, packageName, recursive));
}
return classes;
}
/**
* Returns all superclasses of the given class ordered top down. The last
* element is always {@link java.lang.Object}.
*/
public static List> getSuperclasses(Class> clazz) throws ReflectionException {
Validate.notNull(clazz);
try {
List> clazzes = new ArrayList>();
if (clazz.getSuperclass() != null) {
clazzes.add(clazz.getSuperclass());
clazzes.addAll(getSuperclasses(clazz.getSuperclass()));
}
return clazzes;
} catch (Exception e) {
throw new ReflectionException(e);
}
}
/**
* Returns all implemented interfaces of the given class.
*/
public static Set> getInterfaces(Class> clazz) throws ReflectionException {
Validate.notNull(clazz);
try{
Set> interfaces = new HashSet>();
interfaces.addAll(Arrays.asList(clazz.getInterfaces()));
List> superclasses = getSuperclasses(clazz);
for (Class> superclass : superclasses) {
interfaces.addAll(Arrays.asList(superclass.getInterfaces()));
}
return interfaces;
} catch(Exception e){
throw new ReflectionException(e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy