All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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