
net.java.btrace.ext.Reflective Maven / Gradle / Ivy
/*
* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package net.java.btrace.ext;
import net.java.btrace.api.extensions.BTraceExtension;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.annotation.Resource;
import net.java.btrace.api.extensions.runtime.Exceptions;
import sun.reflect.Reflection;
import static net.java.btrace.ext.Printer.*;
/*
* Wraps the reflection related BTrace utility methods
* @since 1.3
* @author Jaroslav Bachorik
*/
@BTraceExtension
public class Reflective {
@Resource
private static Exceptions exc;
// standard stack depth decrement for Reflection.getCallerClass() calls
private static final int STACK_DEC = 4;
/**
* Returns the runtime class of the given Object.
*
* @param obj the Object whose Class is returned
* @return the Class object of given object
*/
public static Class classOf(Object obj) {
return obj.getClass();
}
/**
* Returns the Class object representing the class or interface
* that declares the field represented by the given Field object.
* @param field whose declaring Class is returned
*/
public static Class declaringClass(Field field) {
return field.getDeclaringClass();
}
/**
* Returns the name of the given Class object.
*/
public static String name(Class clazz) {
return clazz.getName();
}
/**
* Returns the name of the Field object.
*
* @param field Field for which name is returned
* @return name of the given field
*/
public static String name(Field field) {
return field.getName();
}
/**
* Returns the type of the Field object.
*
* @param field Field for which type is returned
* @return type of the given field
*/
public static Class type(Field field) {
return field.getType();
}
/**
* Returns the access flags of the given Class.
*/
public static int accessFlags(Class clazz) {
return clazz.getModifiers();
}
/**
* Returns the access flags of the given Field.
*/
public static int accessFlags(Field field) {
return field.getModifiers();
}
/**
* Returns the current context class loader
*/
public static ClassLoader contextClassLoader() {
return Thread.currentThread().getContextClassLoader();
}
// get Class of the given name
/**
* Returns Class object for given class name.
*/
public static Class classForName(String name) {
return classForName(name, getCallerLoader());
}
/**
* Returns the Class for the given class name
* using the given class loader.
*/
public static Class classForName(String name, ClassLoader cl) {
try {
return Class.forName(name, false, cl);
} catch (ClassNotFoundException exp) {
throw exc.translate(exp);
}
}
/**
* Determines if the class or interface represented by the first
* Class
object is either the same as, or is a superclass or
* superinterface of, the class or interface represented by the second
* Class
parameter. It returns true
if so;
* otherwise it returns false
.
*/
public static boolean isAssignableFrom(Class> a, Class> b) {
return a.isAssignableFrom(b);
}
/**
* Determines if the specified Object
is assignment-compatible
* with the object represented by the specified Class
. This method is
* the dynamic equivalent of the Java language instanceof
* operator. The method returns true
if the specified
* Object
argument is non-null and can be cast to the
* reference type represented by this Class
object without
* raising a ClassCastException.
It returns false
* otherwise.
*
* @param clazz the class that is checked.
* @param obj the object to check.
* @return true if obj
is an instance of the given class.
*/
public static boolean isInstance(Class clazz, Object obj) {
return clazz.isInstance(obj);
}
/**
* Returns the Class
representing the superclass of the entity
* (class, interface, primitive type or void) represented by the given
* Class
. If the given Class
represents either the
* Object
class, an interface, a primitive type, or void, then
* null is returned. If the given object represents an array class then the
* Class
object representing the Object
class is
* returned.
*
* @param clazz the Class whose super class is returned.
* @return the superclass of the class represented by the given object.
*/
public static Class getSuperclass(Class clazz) {
return clazz.getSuperclass();
}
/**
* Determines if the specified Class
object represents an
* interface type.
*
* @param clazz the Class object to check.
* @return true
if the Class represents an interface;
* false
otherwise.
*/
public static boolean isInterface(Class clazz) {
return clazz.isInterface();
}
/**
* Determines if the given Class
object represents an array class.
*
* @param clazz Class object to check.
* @return true
if the given object represents an array class;
* false
otherwise.
*/
public static boolean isArray(Class clazz) {
return clazz.isArray();
}
/**
* Returns whether the given Class represent primitive type or not.
*/
public static boolean isPrimitive(Class clazz) {
return clazz.isPrimitive();
}
/**
* returns component type of an array Class.
*/
public static Class getComponentType(Class clazz) {
return clazz.getComponentType();
}
// Accessing fields by reflection
/**
* Returns a Field
object that reflects the specified declared
* field of the class or interface represented by the given Class
* object. The name
parameter is a String
that
* specifies the simple name of the desired field. Returns null
on not finding
* field if throwException parameter is false
. Else throws a RuntimeException
* when field is not found.
*
* @param clazz Class whose field is returned
* @param name the name of the field
* @param throwException whether to throw exception on failing to find field or not
* @return the Field
object for the specified field in this
* class
*/
public static Field field(Class clazz, String name, boolean throwException) {
return getField(clazz, name, throwException);
}
/**
* Returns a Field
object that reflects the specified declared
* field of the class or interface represented by the given Class
* object. The name
parameter is a String
that
* specifies the simple name of the desired field. Throws a RuntimeException
* when field is not found.
*
* @param clazz Class whose field is returned
* @param name the name of the field
* @return the Field
object for the specified field in this
* class
*/
public static Field field(Class clazz, String name) {
return field(clazz, name, true);
}
/**
* Returns a Field
object that reflects the specified declared
* field of the class or interface represented by the given Class
* object. The name
parameter is a String
that
* specifies the simple name of the desired field. Returns null
on not finding
* field if throwException parameter is false
. Else throws a RuntimeException
* when field is not found.
*
* @param clazz Class whose field is returned
* @param name the name of the field
* @param throwException whether to throw exception on failing to find field or not
* @return the Field
object for the specified field in this
* class
*/
public static Field field(String clazz, String name, boolean throwException) {
return field(classForName(clazz, getCallerLoader()), name, throwException);
}
/**
* Returns a Field
object that reflects the specified declared
* field of the class or interface represented by the given Class
* object. The name
parameter is a String
that
* specifies the simple name of the desired field. Throws a RuntimeException
* when field is not found.
*
* @param clazz Class whose field is returned
* @param name the name of the field
* @return the Field
object for the specified field in this
* class
*/
public static Field field(String clazz, String name) {
return field(classForName(clazz, getCallerLoader()), name);
}
// field value get methods
/**
* Gets the value of a static byte
field.
*
* @param field Field object whose value is returned.
* @return the value of the byte
field
*/
public static byte getByte(Field field) {
checkStatic(field);
try {
return field.getByte(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance byte
field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the byte
value
* from
* @return the value of the byte
field
*/
public static byte getByte(Field field, Object obj) {
try {
return field.getByte(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of a static short
field.
*
* @param field Field object whose value is returned.
* @return the value of the short
field
*/
public static short getShort(Field field) {
checkStatic(field);
try {
return field.getShort(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance short
field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the short
value
* from
* @return the value of the short
field
*/
public static short getShort(Field field, Object obj) {
try {
return field.getShort(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of a static int
field.
*
* @param field Field object whose value is returned.
* @return the value of the int
field
*/
public static int getInt(Field field) {
checkStatic(field);
try {
return field.getInt(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance int
field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the int
value
* from
* @return the value of the int
field
*/
public static int getInt(Field field, Object obj) {
try {
return field.getInt(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of a static long
field.
*
* @param field Field object whose value is returned.
* @return the value of the long
field
*/
public static long getLong(Field field) {
checkStatic(field);
try {
return field.getLong(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance long
field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the long
value
* from
* @return the value of the long
field
*/
public static long getLong(Field field, Object obj) {
try {
return field.getLong(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of a static float
field.
*
* @param field Field object whose value is returned.
* @return the value of the float
field
*/
public static float getFloat(Field field) {
checkStatic(field);
try {
return field.getFloat(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance float
field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the float
value
* from
* @return the value of the float
field
*/
public static float getFloat(Field field, Object obj) {
try {
return field.getFloat(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of a static double
field.
*
* @param field Field object whose value is returned.
* @return the value of the double
field
*/
public static double getDouble(Field field) {
checkStatic(field);
try {
return field.getDouble(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance double
field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the double
value
* from
* @return the value of the double
field
*/
public static double getDouble(Field field, Object obj) {
try {
return field.getDouble(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of a static boolean
field.
*
* @param field Field object whose value is returned.
* @return the value of the boolean
field
*/
public static boolean getBoolean(Field field) {
checkStatic(field);
try {
return field.getBoolean(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance boolean
field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the boolean
value
* from
* @return the value of the boolean
field
*/
public static boolean getBoolean(Field field, Object obj) {
try {
return field.getBoolean(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of a static char
field.
*
* @param field Field object whose value is returned.
* @return the value of the char
field
*/
public static char getChar(Field field) {
checkStatic(field);
try {
return field.getChar(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance char
field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the char
value
* from
* @return the value of the char
field
*/
public static char getChar(Field field, Object obj) {
try {
return field.getChar(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of a static reference field.
*
* @param field Field object whose value is returned.
* @return the value of the reference field
*/
public static Object get(Field field) {
checkStatic(field);
try {
return field.get(null);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Gets the value of an instance reference field.
*
* @param field Field object whose value is returned.
* @param obj the object to extract the reference value
* from
* @return the value of the reference field
*/
public static Object get(Field field, Object obj) {
try {
return field.get(obj);
} catch (Exception exp) {
throw exc.translate(exp);
}
}
/**
* Print all instance fields of an object as name-value
* pairs. Includes the inherited fields as well.
*
* @param obj Object whose fields are printed.
*/
public static void printFields(Object obj) {
printFields(obj, false);
}
/**
* Print all instance fields of an object as name-value
* pairs. Includes the inherited fields as well. Optionally,
* prints name of the declaring class before each field - so that
* if same named field in super class chain may be disambiguated.
*
* @param obj Object whose fields are printed.
* @param classNamePrefix flag to tell whether to prefix field names
* names by class name or not.
*/
public static void printFields(Object obj, boolean classNamePrefix) {
StringBuilder buf = new StringBuilder();
buf.append('{');
addFieldValues(buf, obj, obj.getClass(), classNamePrefix);
buf.append('}');
println(buf.toString());
}
/**
* Print all static fields of the class as name-value
* pairs. Includes the inherited fields as well.
*
* @param clazz Class whose static fields are printed.
*/
public static void printStaticFields(Class clazz) {
printStaticFields(clazz, false);
}
/**
* Print all static fields of the class as name-value
* pairs. Includes the inherited fields as well. Optionally,
* prints name of the declaring class before each field - so that
* if same named field in super class chain may be disambigated.
*
* @param clazz Class whose static fields are printed.
* @param classNamePrefix flag to tell whether to prefix field names
* names by class name or not.
*/
public static void printStaticFields(Class clazz, boolean classNamePrefix) {
StringBuilder buf = new StringBuilder();
buf.append('{');
addStaticFieldValues(buf, clazz, classNamePrefix);
buf.append('}');
println(buf.toString());
}
private static void addStaticFieldValues(StringBuilder buf,
Class clazz, boolean classNamePrefix) {
Field[] fields = getAllFields(clazz);
for (Field f : fields) {
int modifiers = f.getModifiers();
if (Modifier.isStatic(modifiers)) {
if (classNamePrefix) {
buf.append(f.getDeclaringClass().getName());
buf.append('.');
}
buf.append(f.getName());
buf.append('=');
try {
Object val = f.get(null);
buf.append(val != null ? val.toString() : val);
} catch (Exception exp) {
throw exc.translate(exp);
}
buf.append(", ");
}
}
Class sc = clazz.getSuperclass();
if (sc != null) {
addStaticFieldValues(buf, sc, classNamePrefix);
}
}
private static Field getField(final Class clazz, final String name,
final boolean throwError) {
return AccessController.doPrivileged(new PrivilegedAction() {
public Field run() {
try {
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field;
} catch (Exception exp) {
if (throwError) {
throw exc.translate(exp);
} else {
return null;
}
}
}
});
}
private static Field[] getAllFields(final Class clazz) {
return AccessController.doPrivileged(new PrivilegedAction() {
public Field[] run() {
try {
Field[] fields = clazz.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
}
return fields;
} catch (Exception exp) {
throw exc.translate(exp);
}
}
});
}
private static void addFieldValues(StringBuilder buf, Object obj,
Class clazz, boolean classNamePrefix) {
Field[] fields = getAllFields(clazz);
for (Field f : fields) {
int modifiers = f.getModifiers();
if (! Modifier.isStatic(modifiers)) {
if (classNamePrefix) {
buf.append(f.getDeclaringClass().getName());
buf.append('.');
}
buf.append(f.getName());
buf.append('=');
try {
Object val = f.get(obj);
buf.append(val != null ? val.toString() : val);
} catch (Exception exp) {
throw exc.translate(exp);
}
buf.append(", ");
}
}
Class sc = clazz.getSuperclass();
if (sc != null) {
addFieldValues(buf, obj, sc, classNamePrefix);
}
}
private static void checkStatic(Field field) {
if (! Modifier.isStatic(field.getModifiers())) {
throw new IllegalArgumentException(field.getName() +
" is not a static field");
}
}
private static Class getCallerClass(int dec) {
Class cClass = null;
do {
cClass = Reflection.getCallerClass(dec++);
if (!cClass.getName().startsWith("net.java.btrace")) {
return cClass;
}
} while (cClass != null);
return null;
}
private static Class getCallerClass() {
return getCallerClass(STACK_DEC);
}
private static ClassLoader getCallerLoader() {
Class cClass = getCallerClass(STACK_DEC);
if (cClass != null) {
return cClass.getClassLoader();
} else {
return ClassLoader.getSystemClassLoader();
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy