org.jboss.dashboard.commons.misc.ReflectionUtils.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.dashboard.commons.misc.ReflectionUtils.java

Source

/**
 * Copyright (C) 2012 JBoss Inc
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.jboss.dashboard.commons.misc;

import org.apache.commons.jxpath.JXPathContext;
import org.apache.commons.lang3.StringUtils;
import org.jboss.dashboard.Application;
import org.jboss.dashboard.commons.text.StringUtil;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;

public class ReflectionUtils {

    private static final String PREFIX_GET = "get";
    private static final String PREFIX_SET = "set";
    private static final String PREFIX_IS = "is";
    public static final String ARRAYS_DELIMITER = ",";

    public static Object getPrivateField(Object o, String fieldName) {
        Field fields[] = o.getClass().getDeclaredFields();
        for (int i = 0; i < fields.length; ++i) {
            if (fieldName.equals(fields[i].getName())) {
                try {
                    fields[i].setAccessible(true);
                    return fields[i].get(o);
                } catch (IllegalAccessException ex) {
                    return null;
                }
            }
        }
        return null;
    }

    public static Object invokeMethod(Object o, String methodName, Object[] params) {
        Method methods[] = o.getClass().getMethods();
        for (int i = 0; i < methods.length; ++i) {
            if (methodName.equals(methods[i].getName())) {
                try {
                    methods[i].setAccessible(true);
                    return methods[i].invoke(o, params);
                } catch (IllegalAccessException ex) {
                    return null;
                } catch (InvocationTargetException ite) {
                    return null;
                }
            }
        }
        return null;
    }

    public static List<Field> getClassHierarchyFields(Class clazz, Class fieldType, boolean isStatic,
            String[] fieldsToIgnore) {
        List<Field> results = new ArrayList<Field>();
        if (clazz == null)
            return results;
        if (clazz.equals(java.lang.Object.class))
            return results;

        List<Field> superClassFields = getClassHierarchyFields(clazz.getSuperclass(), fieldType, isStatic,
                fieldsToIgnore);
        results.addAll(superClassFields);

        List<Field> classFields = getClassFields(clazz, fieldType, isStatic, fieldsToIgnore);
        results.addAll(classFields);
        return results;
    }

    public static List<Field> getClassFields(Class clazz, Class type, boolean isStatic, String[] fieldsToIgnore) {
        List<Field> results = new ArrayList<Field>();
        if (clazz == null)
            return results;
        if (clazz.isPrimitive())
            return results;
        if (clazz.isAnnotation())
            return results;
        if (clazz.isInterface())
            return results;
        if (clazz.isEnum())
            return results;

        Collection<String> toIgnore = fieldsToIgnore != null ? Arrays.asList(fieldsToIgnore)
                : Collections.EMPTY_SET;
        Field[] fields = clazz.getDeclaredFields();

        for (int i = 0; i < fields.length; i++) {
            Field field = fields[i];
            if (toIgnore.contains(field.getName()))
                continue;
            if (isStatic && !Modifier.isStatic(field.getModifiers()))
                continue;
            if (!isStatic && Modifier.isStatic(field.getModifiers()))
                continue;
            if (type != null && !field.getType().equals(type))
                continue;
            results.add(field);
        }
        return results;
    }

    public static Class[] getClassHierarchyInterfaces(Class clazz) {
        if (clazz == null)
            return new Class[] {};
        if (clazz.equals(java.lang.Object.class))
            return new Class[] {};

        List<Class> results = new ArrayList<Class>();
        Class[] ifaces = clazz.getInterfaces();
        for (int i = 0; i < ifaces.length; i++) {
            if (!results.contains(ifaces[i]))
                results.add(ifaces[i]);
        }

        ifaces = getClassHierarchyInterfaces(clazz.getSuperclass());
        for (int i = 0; i < ifaces.length; i++) {
            if (!results.contains(ifaces[i]))
                results.add(ifaces[i]);
        }

        int index = 0;
        Class[] array = new Class[results.size()];
        for (Class result : results)
            array[index++] = result;
        return array;
    }

    /**
     * Generates the name of a get method for the given field name.
     *
     * @param fieldName the field name to generate a method name for
     * @return the generated get method name
     */
    public static final String getGetMethodName(String fieldName) {
        return PREFIX_GET + getValidAccessorName(fieldName);
    }

    /**
     * Generates the name of a create method for the given field name.
     *
     * @param fieldName the field name to generate a method name for
     * @return the generated create method name
     */
    public static final String getSetMethodName(String fieldName) {
        return PREFIX_SET + getValidAccessorName(fieldName);
    }

    /**
     * Convert the fieldName to a valid name to be append to METHOD_PREFIX_GET/SET
     *
     * @param fieldName name of the accessor property
     * @return valid name for accessor
     */
    private static String getValidAccessorName(String fieldName) {
        char firstChar = fieldName.charAt(0);
        String field = StringUtil.toJavaClassName(fieldName);
        if (fieldName.length() > 1) {
            //fix if firstCharacter is lowercase and second is uppercase, then create correct accessor (i.e. getter for field xXX is getxXX)
            char secondChar = fieldName.charAt(1);
            if (Character.isLowerCase(firstChar) && Character.isUpperCase(secondChar)) {
                field = field.replaceFirst(Character.toString(field.charAt(0)), Character.toString(firstChar));
            }
        }
        return field;
    }

    /**
     * Checks if the given method is a set method.
     *
     * @param method the Method to check
     * @return true if it is a set method
     */
    public static final boolean isSetMethod(final Method method) {
        if (method == null) {
            return false;
        }
        if (!method.getName().startsWith(PREFIX_SET)) {
            return false;
        }
        if (method.getParameterTypes().length != 1) {
            return false;
        }
        if ((method.getReturnType() != void.class) && (method.getReturnType() != Void.class)) {
            return false;
        }
        return true;
    }

    /**
     * Checks if the given method is a get method.
     *
     * @param method the Method to check
     * @return true if it is a get method
     */
    public static final boolean isGetMethod(final Method method) {
        if (method == null) {
            return false;
        }
        if (!method.getName().startsWith(PREFIX_GET)) {
            return false;
        }
        if (method.getParameterTypes().length != 0) {
            return false;
        }
        if (method.getReturnType() == null) {
            return false;
        }
        return true;
    }

    /**
     * Checks if the given method is a 'is' method.
     *
     * @param method the Method to check
     * @return true if it is a 'is' method
     */
    public static final boolean isIsMethod(final Method method) {
        if (method == null) {
            return false;
        }
        if (!method.getName().startsWith(PREFIX_IS)) {
            return false;
        }
        if (method.getParameterTypes().length != 0) {
            return false;
        }
        if ((method.getReturnType().isPrimitive()) && (method.getReturnType() != Boolean.TYPE)) {
            return false;
        }
        if ((!method.getReturnType().isPrimitive()) && (method.getReturnType() != Boolean.class)) {
            return false;
        }
        return true;
    }

    public static Object parseAndSetFieldValues(Object obj, String fieldName, String[] fieldValues)
            throws Exception {
        StringBuffer propertyValue = new StringBuffer();
        for (int i = 0; i < fieldValues.length; i++) {
            String value = fieldValues[i];
            if (i != 0)
                propertyValue.append(ARRAYS_DELIMITER);
            if (fieldValues.length > 1)
                propertyValue.append(StringUtils.replace(value, ",", ",,"));
            else
                propertyValue.append(value);
        }
        return parseAndSetFieldValue(obj, fieldName, propertyValue.toString());
    }

    public static Object parseAndSetFieldValue(Object obj, String fieldName, String fieldValue) throws Exception {
        if (obj instanceof Map) {
            ((Map) obj).put(fieldName, parseValue(fieldValue, String.class)); //Map of Strings
        } else if (obj instanceof List) {
            int index = Integer.parseInt(fieldName);
            while (((List) obj).size() <= index)
                ((List) obj).add(null);
            ((List) obj).set(index, parseValue(fieldValue, String.class)); //List of Strings
        } else if (fieldName.indexOf('.') != -1) { //Set it by JXPath, valid only for strings
            JXPathContext ctx = JXPathContext.newContext(obj);
            ctx.setValue(fieldName.replace('.', '/'), parseValue(fieldValue, String.class));
        } else {
            // Find a Field
            Field field = getField(obj, fieldName);
            if (field != null) {
                Class fieldClass = field.getType();
                Object value = parseValue(fieldValue, fieldClass);
                field.set(obj, value);
                return obj;
            }
            // Find a getter and setter
            Method getter = getGetter(obj, fieldName);
            Method setter = getSetter(obj, getter, fieldName);
            if (setter != null && getter != null) {
                Object value = parseValue(fieldValue, getter.getReturnType());
                setter.invoke(obj, value);
            }
        }
        return obj;
    }

    public static Object setFieldValue(Object obj, String fieldName, Object fieldValue) throws Exception {
        if (obj instanceof Map) {
            ((Map) obj).put(fieldName, fieldValue); //Map of Strings
        } else if (obj instanceof List) {
            int index = Integer.parseInt(fieldName);
            while (((List) obj).size() <= index)
                ((List) obj).add(null);
            ((List) obj).set(index, fieldValue); //List of Strings
        } else if (fieldName.indexOf('.') != -1) { //Set it by JXPath, valid only for strings
            JXPathContext ctx = JXPathContext.newContext(obj);
            ctx.setValue(fieldName.replace('.', '/'), fieldValue);
        } else {
            // Find a Field
            Field field = getField(obj, fieldName);
            if (field != null) {
                field.set(obj, fieldValue);
                return obj;
            }
            // Find a getter and setter.
            Method getter = getGetter(obj, fieldName);
            Method setter = getSetter(obj, getter, fieldName);
            if (setter != null && getter != null) {
                setter.invoke(obj, fieldValue);
            }
        }
        return obj;
    }

    public static Object setFieldFile(Object obj, String fieldName, File fieldValue) throws Exception {
        // Find a Field
        Field field = getField(obj, fieldName);
        if (field != null) {
            Class fieldClass = field.getType();
            if (File.class.equals(fieldClass)) {
                field.set(obj, fieldValue);
            } else if (byte[].class.equals(fieldClass)) {
                field.set(obj, toByteArray(fieldValue));
            } else {
                throw new IllegalArgumentException("Field specified is not a File/byte[]: " + fieldName);
            }
        }
        // Find a getter and setter.
        Method getter = getGetter(obj, fieldName);
        Method setter = getSetter(obj, getter, fieldName);
        if (setter != null && getter != null) {
            Class returnType = getter.getReturnType();
            if (File.class.equals(returnType)) {
                setter.invoke(obj, fieldValue);
            } else if (byte[].class.equals(returnType)) {
                setter.invoke(obj, new Object[] { toByteArray(fieldValue) });
            } else {
                throw new IllegalArgumentException("Field specified is not a File/byte[]: " + fieldName);
            }
        }
        return obj;
    }

    public static Field getField(Object obj, String propertyName) {
        try {
            Field field = obj.getClass().getField(propertyName);
            int modifiers = field.getModifiers();
            if (Modifier.isPublic(modifiers) && !Modifier.isFinal(field.getModifiers())) {
                return field;
            }
        } catch (NoSuchFieldException e) {
        }
        return null;
    }

    public static Method getGetter(Object obj, String propertyName) {
        Method getter = null;
        String propertyAccessorSuffix = StringUtils.capitalize(propertyName);
        String getterName = "get" + propertyAccessorSuffix;
        try {
            getter = obj.getClass().getMethod(getterName, new Class[0]);
        } catch (NoSuchMethodException e) {
            String booleanGetterName = "is" + propertyAccessorSuffix;
            try {
                getter = obj.getClass().getMethod(booleanGetterName, new Class[0]);
            } catch (NoSuchMethodException e1) {
            }
        }
        return getter;
    }

    public static Method getSetter(Object obj, Method getter, String propertyName) {
        Method setter = null;
        String propertyAccessorSuffix = StringUtils.capitalize(propertyName);
        String setterName = "set" + propertyAccessorSuffix;
        Class returnType = getter.getReturnType();
        try {
            setter = obj.getClass().getMethod(setterName, new Class[] { returnType });
        } catch (NoSuchMethodException e) {
        }
        return setter;
    }

    public static <T> T newInstanceForClass(Class<T> type) {
        Object object = null;
        if (type.isArray()) {
            Class componentClass = type.getComponentType();
            if (componentClass.isPrimitive()) {
                if (componentClass.equals(int.class))
                    object = new int[0];
                else if (componentClass.equals(boolean.class))
                    object = new boolean[0];
                else if (componentClass.equals(long.class))
                    object = new long[0];
                else if (componentClass.equals(char.class))
                    object = new char[0];
                else if (componentClass.equals(double.class))
                    object = new double[0];
                else if (componentClass.equals(float.class))
                    object = new float[0];
                else if (componentClass.equals(byte.class))
                    object = new byte[0];
                else if (componentClass.equals(short.class))
                    object = new short[0];
            } else if (String.class.equals(componentClass))
                object = new String[0];
            else if (componentClass.equals(Integer.class))
                object = new Integer[0];
            else if (componentClass.equals(Boolean.class))
                object = new Boolean[0];
            else if (componentClass.equals(Long.class))
                object = new Long[0];
            else if (componentClass.equals(Character.class))
                object = new Character[0];
            else if (componentClass.equals(Double.class))
                object = new Double[0];
            else if (componentClass.equals(Float.class))
                object = new Float[0];
            else if (componentClass.equals(Byte.class))
                object = new Byte[0];
            else if (componentClass.equals(Short.class))
                object = new Short[0];
            else
                object = Array.newInstance(componentClass, 0);
        } else {
            if (String.class.equals(type))
                object = "";
            else if (type.equals(int.class))
                object = new Integer(0);
            else if (type.equals(boolean.class))
                object = Boolean.FALSE;
            else if (type.equals(long.class))
                object = new Long(0);
            else if (type.equals(char.class))
                object = new Character((char) 0);
            else if (type.equals(double.class))
                object = new Double(0);
            else if (type.equals(float.class))
                object = new Float(0);
            else if (type.equals(byte.class))
                object = new Byte((byte) 0);
            else if (type.equals(short.class))
                object = new Short((short) 0);
            else if (type.equals(Integer.class))
                object = new Integer(0);
            else if (type.equals(Boolean.class))
                object = Boolean.FALSE;
            else if (type.equals(Long.class))
                object = new Long(0);
            else if (type.equals(Character.class))
                object = new Character((char) 0);
            else if (type.equals(Double.class))
                object = new Double(0);
            else if (type.equals(Float.class))
                object = new Float(0);
            else if (type.equals(Byte.class))
                object = new Byte((byte) 0);
            else if (type.equals(Short.class))
                object = new Short((short) 0);
            else
                object = null;
        }
        return type.cast(object);
    }

    public static <T> T parseValue(String value, Class<T> type) throws Exception {
        if (type.isArray()) {
            return type.cast(toArray(value, type.getComponentType()));
        } else {
            Object object = null;
            if (String.class.equals(type))
                object = value;
            else if (type.equals(int.class))
                object = toInt(value);
            else if (type.equals(boolean.class))
                object = (toBoolean(value)) ? Boolean.TRUE : Boolean.FALSE;
            else if (type.equals(long.class))
                object = toLong(value);
            else if (type.equals(char.class))
                object = toChar(value);
            else if (type.equals(double.class))
                object = toDouble(value);
            else if (type.equals(float.class))
                object = toFloat(value);
            else if (type.equals(byte.class))
                object = toByte(value);
            else if (type.equals(short.class))
                object = toShort(value);
            else if (type.equals(File.class))
                object = toFile(value);
            else if (type.equals(Integer.class))
                object = toInt(value);
            else if (type.equals(Boolean.class))
                object = (toBoolean(value)) ? Boolean.TRUE : Boolean.FALSE;
            else if (type.equals(Long.class))
                object = toLong(value);
            else if (type.equals(Character.class))
                object = toChar(value);
            else if (type.equals(Double.class))
                object = toDouble(value);
            else if (type.equals(Float.class))
                object = toFloat(value);
            else if (type.equals(Byte.class))
                object = toByte(value);
            else if (type.equals(Short.class))
                object = toShort(value);

            return (T) object;
        }
    }

    public static Object[] toArray(String value, Class type) throws Exception {
        if (type.isArray())
            throw new Exception("Nested array is not supported.");

        List objectValue = new ArrayList();
        StringTokenizer stk = new StringTokenizer(value, ARRAYS_DELIMITER, true);
        while (stk.hasMoreTokens()) {
            String token = stk.nextToken();
            int delimiterCount = 0;
            boolean addTrailingToken = true;
            while (ARRAYS_DELIMITER.equals(token)) {
                addTrailingToken = false;
                delimiterCount++;
                if (delimiterCount % 2 == 0) {
                    String lastToken = (String) objectValue.get(objectValue.size() - 1);
                    objectValue.set(objectValue.size() - 1, lastToken + ARRAYS_DELIMITER);
                    if (stk.hasMoreTokens()) {
                        token = stk.nextToken();
                        if (!ARRAYS_DELIMITER.equals(token)) {
                            lastToken = (String) objectValue.get(objectValue.size() - 1);
                            objectValue.remove(objectValue.size() - 1);
                            objectValue.add(lastToken + token);
                        }
                    } else {
                        addTrailingToken = false;
                        break;
                    }
                } else if (delimiterCount % 2 == 1 && !stk.hasMoreTokens()) {
                    objectValue.add("");
                } else if (stk.hasMoreTokens()) {
                    token = stk.nextToken();
                    addTrailingToken = true;
                }
            }
            if (addTrailingToken) {
                objectValue.add(token);
            }
        }
        for (int i = 0; i < objectValue.size(); i++) {
            String s = (String) objectValue.get(i);
            objectValue.set(i, parseValue(s, type));
        }

        Object baseObjectArray = getBaseArray(type, objectValue.size());
        return objectValue.toArray((Object[]) baseObjectArray);
    }

    private static Object getBaseArray(Class type, int length) {
        if (type.isPrimitive()) {
            if (type.equals(int.class))
                return new Integer[length];
            else if (type.equals(boolean.class))
                return new Boolean[length];
            else if (type.equals(long.class))
                return new Long[length];
            else if (type.equals(char.class))
                return new Character[length];
            else if (type.equals(double.class))
                return new Double[length];
            else if (type.equals(float.class))
                return new Float[length];
            else if (type.equals(byte.class))
                return new Byte[length];
            else if (type.equals(short.class))
                return new Short[length];
        }
        return Array.newInstance(type, length);

    }

    public static int toInt(String parameter) throws Exception {
        return Integer.parseInt(parameter);
    }

    public static boolean toBoolean(String parameter) throws Exception {
        return Boolean.valueOf(parameter);
    }

    public static long toLong(String parameter) throws Exception {
        return Long.parseLong(parameter);
    }

    public static char toChar(String parameter) throws Exception {
        if (parameter.length() != 1)
            throw new Exception("Invalid value for a char " + parameter);
        return parameter.charAt(0);
    }

    public static double toDouble(String parameter) throws Exception {
        return Double.parseDouble(parameter);
    }

    public static float toFloat(String parameter) throws Exception {
        return Float.parseFloat(parameter);
    }

    public static byte toByte(String parameter) throws Exception {
        return Byte.parseByte(parameter);
    }

    public static short toShort(String parameter) throws Exception {
        return Short.parseShort(parameter);
    }

    public static Object toFile(String paramValue) {
        if (paramValue == null || "".equals(paramValue.trim())) {
            return null;
        }
        if (paramValue.startsWith("/") || paramValue.contains(":")) {
            return new File(paramValue);
        } else {
            return new File(Application.lookup().getBaseAppDirectory() + "/" + paramValue);
        }
    }

    public static byte[] toByteArray(File f) throws IOException {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(f));
            int byteRead;
            while ((byteRead = bis.read()) != -1) {
                bos.write(byteRead);
            }
        } finally {
            if (bis != null)
                bis.close();
            bos.close();
        }
        return bos.toByteArray();
    }

    public static void main(String[] args) {
        String s = "pepe";
        Object v1 = getPrivateField(s, "cunt");
        Object v2 = invokeMethod(s, "sustring", new Object[] { new Integer(1) });
        System.out.println(v1);
        System.out.println(v2);
    }
}