/** * Copyright (c) 2000-present Liferay, Inc. All rights reserved. * * This library is free software; you can redistribute it and/or modify it under * the terms of the GNU Lesser General Public License as published by the Free * Software Foundation; either version 2.1 of the License, or (at your option) * any later version. * * This library 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 Lesser General Public License for more * details. */ package com.liferay.portal.kernel.util; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; /** * @author Brian Wing Shun Chan * @author Miguel Pastor * @author Shuyang Zhou */ public class ReflectionUtil { public static Object arrayClone(Object array) { Class<?> clazz = array.getClass(); if (!clazz.isArray()) { throw new IllegalArgumentException( "Input object is not an array: " + array); } try { return _CLONE_METHOD.invoke(array); } catch (Exception e) { return throwException(e); } } public static Field getDeclaredField(Class<?> clazz, String name) throws Exception { Field field = clazz.getDeclaredField(name); if (!field.isAccessible()) { field.setAccessible(true); } return unfinalField(field); } public static Field[] getDeclaredFields(Class<?> clazz) throws Exception { Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (!field.isAccessible()) { field.setAccessible(true); } unfinalField(field); } return fields; } public static Method getDeclaredMethod( Class<?> clazz, String name, Class<?>... parameterTypes) throws Exception { Method method = clazz.getDeclaredMethod(name, parameterTypes); if (!method.isAccessible()) { method.setAccessible(true); } return method; } public static Type getGenericInterface( Object object, Class<?> interfaceClass) { Class<?> clazz = object.getClass(); Type genericInterface = _getGenericInterface(clazz, interfaceClass); if (genericInterface != null) { return genericInterface; } Class<?> superClass = clazz.getSuperclass(); while (superClass != null) { genericInterface = _getGenericInterface(superClass, interfaceClass); if (genericInterface != null) { return genericInterface; } superClass = superClass.getSuperclass(); } return null; } public static Class<?> getGenericSuperType(Class<?> clazz) { try { ParameterizedType parameterizedType = (ParameterizedType)clazz.getGenericSuperclass(); Type[] types = parameterizedType.getActualTypeArguments(); if (types.length > 0) { return (Class<?>)types[0]; } } catch (Throwable t) { } return null; } public static Class<?>[] getInterfaces(Object object) { return getInterfaces(object, null); } public static Class<?>[] getInterfaces( Object object, ClassLoader classLoader) { Set<Class<?>> interfaceClasses = new LinkedHashSet<>(); Class<?> clazz = object.getClass(); _getInterfaces(interfaceClasses, clazz, classLoader); Class<?> superClass = clazz.getSuperclass(); while (superClass != null) { _getInterfaces(interfaceClasses, superClass, classLoader); superClass = superClass.getSuperclass(); } return interfaceClasses.toArray(new Class<?>[interfaceClasses.size()]); } public static Class<?>[] getParameterTypes(Object[] arguments) { if (arguments == null) { return null; } Class<?>[] parameterTypes = new Class<?>[arguments.length]; for (int i = 0; i < arguments.length; i++) { if (arguments[i] == null) { parameterTypes[i] = null; } else if (arguments[i] instanceof Boolean) { parameterTypes[i] = Boolean.TYPE; } else if (arguments[i] instanceof Byte) { parameterTypes[i] = Byte.TYPE; } else if (arguments[i] instanceof Character) { parameterTypes[i] = Character.TYPE; } else if (arguments[i] instanceof Double) { parameterTypes[i] = Double.TYPE; } else if (arguments[i] instanceof Float) { parameterTypes[i] = Float.TYPE; } else if (arguments[i] instanceof Integer) { parameterTypes[i] = Integer.TYPE; } else if (arguments[i] instanceof Long) { parameterTypes[i] = Long.TYPE; } else if (arguments[i] instanceof Short) { parameterTypes[i] = Short.TYPE; } else { parameterTypes[i] = arguments[i].getClass(); } } return parameterTypes; } public static Set<Method> getVisibleMethods(Class<?> clazz) { Set<Method> visibleMethods = new HashSet<>( Arrays.asList(clazz.getMethods())); Collections.addAll(visibleMethods, clazz.getDeclaredMethods()); while ((clazz = clazz.getSuperclass()) != null) { for (Method method : clazz.getDeclaredMethods()) { int modifiers = method.getModifiers(); if (!Modifier.isPrivate(modifiers) & !Modifier.isPublic(modifiers)) { visibleMethods.add(method); } } } return visibleMethods; } public static <T> T throwException(Throwable throwable) { return ReflectionUtil.<T, RuntimeException>_throwException(throwable); } public static Field unfinalField(Field field) throws Exception { int modifiers = field.getModifiers(); if ((modifiers & Modifier.FINAL) == Modifier.FINAL) { Field modifiersField = getDeclaredField(Field.class, "modifiers"); modifiersField.setInt(field, modifiers & ~Modifier.FINAL); } return field; } private static Type _getGenericInterface( Class<?> clazz, Class<?> interfaceClass) { Type[] genericInterfaces = clazz.getGenericInterfaces(); for (Type genericInterface : genericInterfaces) { if (!(genericInterface instanceof ParameterizedType)) { continue; } ParameterizedType parameterizedType = (ParameterizedType)genericInterface; Type rawType = parameterizedType.getRawType(); if (rawType.equals(interfaceClass)) { return parameterizedType; } } return null; } private static void _getInterfaces( Set<Class<?>> interfaceClasses, Class<?> clazz, ClassLoader classLoader) { for (Class<?> interfaceClass : clazz.getInterfaces()) { try { if (classLoader != null) { interfaceClasses.add( classLoader.loadClass(interfaceClass.getName())); } else { interfaceClasses.add(interfaceClass); } } catch (ClassNotFoundException cnfe) { } } } @SuppressWarnings("unchecked") private static <T, E extends Throwable> T _throwException( Throwable throwable) throws E { throw (E)throwable; } private static final Method _CLONE_METHOD; static { try { _CLONE_METHOD = getDeclaredMethod(Object.class, "clone"); } catch (Exception e) { throw new ExceptionInInitializerError(e); } } }