
com.orientechnologies.common.reflection.OReflectionHelper Maven / Gradle / Ivy
The newest version!
package com.orientechnologies.common.reflection;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import com.orientechnologies.common.log.OLogManager;
/**
* Helper class to browse .class files. See also: http://forums.sun.com/thread.jspa?threadID=341935&start=15&tstart=0
*
* @author Antony Stubbs
*/
public class OReflectionHelper {
private static final String CLASS_EXTENSION = ".class";
public static List> getClassesForPackage(final String iPackageName, final ClassLoader iClassLoader)
throws ClassNotFoundException {
// This will hold a list of directories matching the pckgname.
// There may be more than one if a package is split over multiple jars/paths
List> classes = new ArrayList>();
ArrayList directories = new ArrayList();
try {
// Ask for all resources for the path
final String packageUrl = iPackageName.replace('.', '/');
Enumeration resources = iClassLoader.getResources(packageUrl);
if (!resources.hasMoreElements()) {
resources = iClassLoader.getResources(packageUrl + CLASS_EXTENSION);
if (resources.hasMoreElements()) {
throw new IllegalArgumentException(iPackageName + " does not appear to be a valid package but a class");
}
} else {
while (resources.hasMoreElements()) {
URL res = resources.nextElement();
if (res.getProtocol().equalsIgnoreCase("jar")) {
JarURLConnection conn = (JarURLConnection) res.openConnection();
JarFile jar = conn.getJarFile();
for (JarEntry e : Collections.list(jar.entries())) {
if (e.getName().startsWith(iPackageName.replace('.', '/')) && e.getName().endsWith(CLASS_EXTENSION)
&& !e.getName().contains("$")) {
String className = e.getName().replace("/", ".").substring(0, e.getName().length() - 6);
classes.add(Class.forName(className));
}
}
} else
directories.add(new File(URLDecoder.decode(res.getPath(), "UTF-8")));
}
}
} catch (NullPointerException x) {
throw new ClassNotFoundException(iPackageName + " does not appear to be " + "a valid package (Null pointer exception)");
} catch (UnsupportedEncodingException encex) {
throw new ClassNotFoundException(iPackageName + " does not appear to be " + "a valid package (Unsupported encoding)");
} catch (IOException ioex) {
throw new ClassNotFoundException("IOException was thrown when trying " + "to get all resources for " + iPackageName);
}
// For every directory identified capture all the .class files
for (File directory : directories) {
if (directory.exists()) {
// Get the list of the files contained in the package
File[] files = directory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
classes.addAll(findClasses(file, iPackageName));
} else {
String className;
if (file.getName().endsWith(CLASS_EXTENSION)) {
className = file.getName().substring(0, file.getName().length() - CLASS_EXTENSION.length());
classes.add(Class.forName(iPackageName + '.' + className));
}
}
}
} else {
throw new ClassNotFoundException(iPackageName + " (" + directory.getPath() + ") does not appear to be a valid package");
}
}
return classes;
}
/**
* Recursive method used to find all classes in a given directory and subdirs.
*
* @param iDirectory
* The base directory
* @param iPackageName
* The package name for classes found inside the base directory
* @return The classes
* @throws ClassNotFoundException
*/
private static List> findClasses(final File iDirectory, String iPackageName) throws ClassNotFoundException {
final List> classes = new ArrayList>();
if (!iDirectory.exists())
return classes;
iPackageName += "." + iDirectory.getName();
String className;
final File[] files = iDirectory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
if (file.getName().contains("."))
continue;
classes.addAll(findClasses(file, iPackageName));
} else if (file.getName().endsWith(CLASS_EXTENSION)) {
className = file.getName().substring(0, file.getName().length() - CLASS_EXTENSION.length());
classes.add(Class.forName(iPackageName + '.' + className));
}
}
return classes;
}
/**
* Filters discovered classes to see if they implement a given interface.
*
* @param thePackage
* @param theInterface
* @param iClassLoader
* @return The list of classes that implements the requested interface
*/
public static List> getClassessOfInterface(String thePackage, Class> theInterface, final ClassLoader iClassLoader) {
List> classList = new ArrayList>();
try {
for (Class> discovered : getClassesForPackage(thePackage, iClassLoader)) {
if (Arrays.asList(discovered.getInterfaces()).contains(theInterface)) {
classList.add(discovered);
}
}
} catch (ClassNotFoundException ex) {
OLogManager.instance().error(null, "Error finding classes", ex);
}
return classList;
}
/**
* Returns the declared generic types of a class.
*
* @param iClass
* Class to examine
* @return The array of Type if any, otherwise null
*/
public static Type[] getGenericTypes(final Class> iClass) {
final Type genericType = iClass.getGenericInterfaces()[0];
if (genericType != null && genericType instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) genericType;
if (pt.getActualTypeArguments() != null && pt.getActualTypeArguments().length > 1)
return pt.getActualTypeArguments();
}
return null;
}
/**
* Returns the generic class of multi-value objects.
*
* @param p
* Field to examine
* @return The Class> of generic type if any, otherwise null
*/
public static Class> getGenericMultivalueType(final Field p) {
if (p.getType() instanceof Class>) {
final Type genericType = p.getGenericType();
if (genericType != null && genericType instanceof ParameterizedType) {
final ParameterizedType pt = (ParameterizedType) genericType;
if (pt.getActualTypeArguments() != null && pt.getActualTypeArguments().length > 0) {
if (((Class>) pt.getRawType()).isAssignableFrom(Map.class)) {
if (pt.getActualTypeArguments()[1] instanceof Class>) {
return (Class>) pt.getActualTypeArguments()[1];
} else if (pt.getActualTypeArguments()[1] instanceof ParameterizedType)
return (Class>) ((ParameterizedType) pt.getActualTypeArguments()[1]).getRawType();
} else if (pt.getActualTypeArguments()[0] instanceof Class>) {
return (Class>) pt.getActualTypeArguments()[0];
} else if (pt.getActualTypeArguments()[0] instanceof ParameterizedType)
return (Class>) ((ParameterizedType) pt.getActualTypeArguments()[0]).getRawType();
}
} else if (p.getType().isArray())
return p.getType().getComponentType();
}
return null;
}
/**
* Checks if a class is a Java type: Map, Collection,arrays, Number (extensions and primitives), String, Boolean..
*
* @param clazz
* Class> to examine
* @return true if clazz is Java type, false otherwise
*/
public static boolean isJavaType(Class> clazz) {
if (clazz.isPrimitive())
return true;
else if (clazz.getName().startsWith("java.lang"))
return true;
else if (clazz.getName().startsWith("java.util"))
return true;
else if (clazz.isArray())
return true;
return false;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy