
com.ardikars.common.util.Reflections Maven / Gradle / Ivy
The newest version!
package com.ardikars.common.util;
import com.ardikars.common.annotation.Helper;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@Helper
public class Reflections {
private static final boolean ACCESS_CONTROL;
/**
* Try to call {@link AccessibleObject#setAccessible(boolean)} but will catch any {@link SecurityException}
* and return it.
* The caller must check if it returns {@code null} and if not handle the returned exception.
* @param object accessible object.
* @param checkAccessible accessible.
* @return returns null on success, throwable otherwise.
*/
public static Throwable trySetAccessible(final AccessibleObject object, final boolean checkAccessible) throws RuntimeException {
if (checkAccessible && !ACCESS_CONTROL) {
return new UnsupportedOperationException("Reflective setAccessible(true) disabled");
}
return setAccessible(object, checkAccessible);
}
/**
* Try to force call {@link AccessibleObject#setAccessible(boolean)} but will catch any {@link SecurityException}
* and return it.
* The caller must check if it returns {@code null} and if not handle the returned exception.
* @param object accessible object.
* @param checkAccessible accessible.
* @return returns null on success, throwable otherwise.
* @deprecated please use {@link Reflections}.{@link #trySetAccessible(AccessibleObject, boolean)}
*/
public static Throwable forceSetAccessible(final AccessibleObject object, final boolean checkAccessible) throws RuntimeException {
return setAccessible(object, checkAccessible);
}
/**
* Gets a {@code List} of superclasses for the given class.
*
* @param cls the class to look up.
* @return returns {@code List} of superclasses.
*/
public static List> getAllSuperClasses(final Class> cls) {
Validate.notIllegalArgument(cls != null, new IllegalArgumentException("Class should be not null"));
final List> classes = new ArrayList>();
Class> superclass = cls.getSuperclass();
while (superclass != null) {
classes.add(superclass);
superclass = superclass.getSuperclass();
}
return Collections.unmodifiableList(classes);
}
/**
* Gets a {@code List} of superclasses and class it self for the given class.
*
* @param cls the class to look up.
* @return returns {@code List} of superclasses and class it self.
*/
public static List> getAllClasses(final Class> cls) {
Validate.notIllegalArgument(cls != null, new IllegalArgumentException("Class should be not null"));
final List> classes = new ArrayList>();
classes.add(cls);
classes.addAll(getAllSuperClasses(cls));
return Collections.unmodifiableList(classes);
}
/**
* Gets a {@code List} of all interfaces implemented by the given
* class and its superclasses.
*
* @param cls the class to look up.
* @return returns {@code List} of interfaces.
*/
public static List> getAllInterfaces(final Class> cls) {
Validate.notIllegalArgument(cls != null, new IllegalArgumentException("Class should be not null"));
List> classes = getAllClasses(cls);
Iterator> iterator = classes.iterator();
List> interfaces = new ArrayList>();
while (iterator.hasNext()) {
Class> clazz = iterator.next();
for (Class> i : clazz.getInterfaces()) {
interfaces.add(i);
}
}
return Collections.unmodifiableList(interfaces);
}
/**
* Get a {@code List} of all classes and interfaces.
* @param cls the class to look up.
* @return returns {@code List} of all classes and interfaces.
*/
public static List> getAllClassesAndInterfaces(final Class> cls) {
Validate.notIllegalArgument(cls != null, new IllegalArgumentException("Class should be not null"));
List> classes = new ArrayList>();
classes.addAll(getAllClasses(cls));
classes.addAll(getAllInterfaces(cls));
return Collections.unmodifiableList(classes);
}
/**
* Get a {@code List} of all super classes and interfaces.
* @param cls the class to look up.
* @return returns {@code List} of all super classes and interfaces.
*/
public static List> getAllSuperClassesAndInterfaces(final Class> cls) {
Validate.notIllegalArgument(cls != null, new IllegalArgumentException("Class should be not null"));
final List> allSuperClassesAndInterfaces = new ArrayList>();
final List> allSuperclasses = getAllSuperClasses(cls);
int superClassIndex = 0;
final List> allInterfaces = getAllInterfaces(cls);
int interfaceIndex = 0;
while (interfaceIndex < allInterfaces.size()
|| superClassIndex < allSuperclasses.size()) {
Class> acls;
if (interfaceIndex >= allInterfaces.size()) {
acls = allSuperclasses.get(superClassIndex++);
} else if (superClassIndex >= allSuperclasses.size()) {
acls = allInterfaces.get(interfaceIndex++);
} else if (interfaceIndex < superClassIndex) {
acls = allInterfaces.get(interfaceIndex++);
} else if (superClassIndex < interfaceIndex) {
acls = allSuperclasses.get(superClassIndex++);
} else {
acls = allInterfaces.get(interfaceIndex++);
}
allSuperClassesAndInterfaces.add(acls);
}
return Collections.unmodifiableList(allSuperClassesAndInterfaces);
}
/**
* Get public field from current or super class/interface.
* @param cls the class to look up.
* @param fieldName field name.
* @return returns {@link Field}.
* @throws NoSuchFieldException field not found.
*/
public static Field getPublicFiled(final Class> cls, String fieldName) throws NoSuchFieldException {
final Field declaredField = cls.getField(fieldName);
if (Modifier.isPublic(declaredField.getDeclaringClass().getModifiers())) {
return declaredField;
}
final List> candidateClasses = getAllSuperClassesAndInterfaces(cls);
for (final Class> candidateClass : candidateClasses) {
if (!Modifier.isPublic(candidateClass.getModifiers())) {
continue;
}
Field candidateField;
try {
candidateField = candidateClass.getField(fieldName);
} catch (final NoSuchFieldException ex) {
continue;
}
if (Modifier.isPublic(candidateField.getDeclaringClass().getModifiers())) {
return candidateField;
}
}
throw new NoSuchFieldException("Can't find a public field for " + fieldName);
}
/**
* Get public method from current or super class/interface.
* @param cls the class to look up.
* @param methodName method name.
* @param parameterTypes parameter types.
* @return returns {@link Method}.
* @throws NoSuchMethodException method not found.
*/
public static Method getPublicMethod(final Class> cls, final String methodName, final Class>... parameterTypes)
throws NoSuchMethodException {
final Method declaredMethod = cls.getMethod(methodName, parameterTypes);
if (Modifier.isPublic(declaredMethod.getDeclaringClass().getModifiers())) {
return declaredMethod;
}
final List> candidateClasses = getAllSuperClassesAndInterfaces(cls);
for (final Class> candidateClass : candidateClasses) {
if (!Modifier.isPublic(candidateClass.getModifiers())) {
continue;
}
Method candidateMethod;
try {
candidateMethod = candidateClass.getMethod(methodName, parameterTypes);
} catch (final NoSuchMethodException ex) {
continue;
}
if (Modifier.isPublic(candidateMethod.getDeclaringClass().getModifiers())) {
return candidateMethod;
}
}
throw new NoSuchMethodException("Can't find a public method for "
+ methodName + " " + Arrays.toString(parameterTypes));
}
private static Throwable setAccessible(final AccessibleObject object, final boolean checkAccessible) throws RuntimeException {
Object obj = AccessController.doPrivileged(new PrivilegedAction
© 2015 - 2025 Weber Informatics LLC | Privacy Policy