1765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye/******************************************************************************* 2765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Copyright (c) 2011 Google, Inc. 3765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * All rights reserved. This program and the accompanying materials 4765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * are made available under the terms of the Eclipse Public License v1.0 5765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * which accompanies this distribution, and is available at 6765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * http://www.eclipse.org/legal/epl-v10.html 7765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 8765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Contributors: 9765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Google, Inc. - initial API and implementation 10765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye *******************************************************************************/ 11765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyepackage org.eclipse.wb.internal.core.utils.reflect; 12765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 13765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport com.google.common.collect.Maps; 14765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 15765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport org.eclipse.wb.internal.core.utils.check.Assert; 16765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 17765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.lang.reflect.Field; 18765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.lang.reflect.GenericArrayType; 19765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.lang.reflect.InvocationTargetException; 20765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.lang.reflect.Method; 21765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.lang.reflect.ParameterizedType; 22765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.lang.reflect.Type; 23765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.lang.reflect.TypeVariable; 24765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.lang.reflect.WildcardType; 25765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyeimport java.util.Map; 26765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 27765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye/** 28765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Contains different Java reflection utilities. 29765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 30765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @author scheglov_ke 31765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @coverage core.util 32765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 33765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbyepublic class ReflectionUtils { 34765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 35765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 36765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // Constructor 37765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 38765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 39765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye private ReflectionUtils() { 40765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 41765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 42765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 43765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 44765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // Signature 45765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 46765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 47765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 48765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param runtime 49765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * is <code>true</code> if we need name for class loading, <code>false</code> if we need 50765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * name for source generation. 51765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 52765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return the fully qualified name of given {@link Type}. 53765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 54765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static String getFullyQualifiedName(Type type, boolean runtime) { 55765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(type); 56765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // Class 57765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (type instanceof Class<?>) { 58765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Class<?> clazz = (Class<?>) type; 59765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // array 60765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (clazz.isArray()) { 61765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return getFullyQualifiedName(clazz.getComponentType(), runtime) + "[]"; 62765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 63765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // object 64765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye String name = clazz.getName(); 65765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (!runtime) { 66765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye name = name.replace('$', '.'); 67765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 68765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return name; 69765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 70765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // GenericArrayType 71765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (type instanceof GenericArrayType) { 72765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye GenericArrayType genericArrayType = (GenericArrayType) type; 73765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return getFullyQualifiedName(genericArrayType.getGenericComponentType(), runtime) + "[]"; 74765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 75765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // ParameterizedType 76765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (type instanceof ParameterizedType) { 77765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye ParameterizedType parameterizedType = (ParameterizedType) type; 78765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Type rawType = parameterizedType.getRawType(); 79765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // raw type 80765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye StringBuilder sb = new StringBuilder(); 81765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye sb.append(getFullyQualifiedName(rawType, runtime)); 82765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // type arguments 83765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye sb.append("<"); 84765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye boolean firstTypeArgument = true; 85765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye for (Type typeArgument : parameterizedType.getActualTypeArguments()) { 86765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (!firstTypeArgument) { 87765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye sb.append(","); 88765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 89765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye firstTypeArgument = false; 90765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye sb.append(getFullyQualifiedName(typeArgument, runtime)); 91765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 92765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye sb.append(">"); 93765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // done 94765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return sb.toString(); 95765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 96765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // WildcardType 97765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (type instanceof WildcardType) { 98765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye WildcardType wildcardType = (WildcardType) type; 99765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return "? extends " + getFullyQualifiedName(wildcardType.getUpperBounds()[0], runtime); 100765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 101765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // TypeVariable 102765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye TypeVariable<?> typeVariable = (TypeVariable<?>) type; 103765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return typeVariable.getName(); 104765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 105765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 106765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 107765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Appends fully qualified names of given parameter types (appends also <code>"()"</code>). 108765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 109765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye private static void appendParameterTypes(StringBuilder buffer, Type[] parameterTypes) { 110765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye buffer.append('('); 111765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye boolean firstParameter = true; 112765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye for (Type parameterType : parameterTypes) { 113765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (firstParameter) { 114765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye firstParameter = false; 115765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } else { 116765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye buffer.append(','); 117765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 118765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye buffer.append(getFullyQualifiedName(parameterType, false)); 119765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 120765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye buffer.append(')'); 121765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 122765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 123765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 124765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 125765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // Method 126765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 127765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 128765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 129765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return all declared {@link Method}'s, including protected and private. 130765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 131765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static Map<String, Method> getMethods(Class<?> clazz) { 132765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Map<String, Method> methods = Maps.newHashMap(); 133765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // process classes 134765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye for (Class<?> c = clazz; c != null; c = c.getSuperclass()) { 135765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye for (Method method : c.getDeclaredMethods()) { 136765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye String signature = getMethodSignature(method); 137765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (!methods.containsKey(signature)) { 138765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye method.setAccessible(true); 139765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye methods.put(signature, method); 140765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 141765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 142765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 143765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // process interfaces 144765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye for (Class<?> interfaceClass : clazz.getInterfaces()) { 145765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye for (Method method : interfaceClass.getDeclaredMethods()) { 146765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye String signature = getMethodSignature(method); 147765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (!methods.containsKey(signature)) { 148765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye method.setAccessible(true); 149765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye methods.put(signature, method); 150765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 151765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 152765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 153765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // done 154765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return methods; 155765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 156765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 157765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 158765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return signature for given {@link Method}. This signature is not same signature as in JVM or 159765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * JDT, just some string that unique identifies method in its {@link Class}. 160765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 161765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static String getMethodSignature(Method method) { 162765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(method); 163765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return getMethodSignature(method.getName(), method.getParameterTypes()); 164765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 165765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 166765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 167765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Returns the signature of {@link Method} with given combination of name and parameter types. 168765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * This signature is not same signature as in JVM or JDT, just some string that unique identifies 169765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * method in its {@link Class}. 170765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 171765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param name 172765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * the name of {@link Method}. 173765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param parameterTypes 174765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * the types of {@link Method} parameters. 175765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 176765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return signature of {@link Method}. 177765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 178765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static String getMethodSignature(String name, Type... parameterTypes) { 179765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(name); 180765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(parameterTypes); 181765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 182765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye StringBuilder buffer = new StringBuilder(); 183765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye buffer.append(name); 184765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye appendParameterTypes(buffer, parameterTypes); 185765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return buffer.toString(); 186765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 187765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 188765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye private static final ClassMap<Map<String, Method>> m_getMethodBySignature = ClassMap.create(); 189765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 190765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 191765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Returns the {@link Method} defined in {@link Class}. This method can have any visibility, i.e. 192765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * we can find even protected/private methods. Can return <code>null</code> if no method with 193765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * given signature found. 194765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 195765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param clazz 196765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * the {@link Class} to get method from it, or its superclass. 197765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param signature 198765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * the signature of method in same format as {@link #getMethodSignature(Method)}. 199765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 200765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return the {@link Method} for given signature, or <code>null</code> if no such method found. 201765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 202765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static Method getMethodBySignature(Class<?> clazz, String signature) { 203765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(clazz); 204765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(signature); 205765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // prepare cache 206765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Map<String, Method> cache = m_getMethodBySignature.get(clazz); 207765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (cache == null) { 208765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye cache = getMethods(clazz); 209765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye m_getMethodBySignature.put(clazz, cache); 210765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 211765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // use cache 212765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return cache.get(signature); 213765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 214765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 215765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 216765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return the {@link Object} result of invoking method with given signature. 217765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 218765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static Object invokeMethod(Object object, String signature, Object... arguments) 219765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye throws Exception { 220765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(object); 221765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(arguments); 222765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // prepare class/object 223765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Class<?> refClass = getRefClass(object); 224765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Object refObject = getRefObject(object); 225765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // prepare method 226765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Method method = getMethodBySignature(refClass, signature); 227765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.isNotNull(method, "Can not find method " + signature + " in " + refClass); 228765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // do invoke 229765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye try { 230765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return method.invoke(refObject, arguments); 231765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } catch (InvocationTargetException e) { 232765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye throw propagate(e.getCause()); 233765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 234765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 235765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 236765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 237765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Invokes method by name and parameter types. 238765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 239765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param object 240765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * the object to call, may be {@link Class} for invoking static method. 241765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param name 242765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * the name of method. 243765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param parameterTypes 244765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * the types of parameters. 245765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @param arguments 246765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * the values of argument for invocation. 247765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 248765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return the {@link Object} result of invoking method. 249765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 250765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static Object invokeMethod2(Object object, 251765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye String name, 252765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Class<?>[] parameterTypes, 253765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Object[] arguments) throws Exception { 254765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye Assert.equals(parameterTypes.length, arguments.length); 255765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye String signature = getMethodSignature(name, parameterTypes); 256765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return invokeMethod(object, signature, arguments); 257765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 258765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 259765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 260765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 261765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // Utils 262765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 263765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 264765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 265765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return the {@link Class} of given {@link Object} or casted object, if it is {@link Class} 266765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * itself. 267765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 268765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye private static Class<?> getRefClass(Object object) { 269765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return object instanceof Class<?> ? (Class<?>) object : object.getClass(); 270765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 271765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 272765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 273765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return the {@link Object} that should be used as argument for {@link Field#get(Object)} and 274765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * {@link Method#invoke(Object, Object[])}. 275765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 276765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye private static Object getRefObject(Object object) { 277765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return object instanceof Class<?> ? null : object; 278765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 279765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 280765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 281765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 282765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // Throwable propagation 283765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye // 284765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye //////////////////////////////////////////////////////////////////////////// 285765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 286765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Helper class used in {@link #propagate(Throwable)}. 287765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 288765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye private static class ExceptionThrower { 289765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye private static Throwable throwable; 290765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 291765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye private ExceptionThrower() throws Throwable { 292765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (System.getProperty("wbp.ReflectionUtils.propagate().InstantiationException") != null) { 293765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye throw new InstantiationException(); 294765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 295765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (System.getProperty("wbp.ReflectionUtils.propagate().IllegalAccessException") != null) { 296765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye throw new IllegalAccessException(); 297765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 298765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye throw throwable; 299765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 300765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 301765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static synchronized void spit(Throwable t) { 302765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (System.getProperty("wbp.ReflectionUtils.propagate().dontThrow") == null) { 303765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye ExceptionThrower.throwable = t; 304765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye try { 305765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye ExceptionThrower.class.newInstance(); 306765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } catch (InstantiationException e) { 307765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } catch (IllegalAccessException e) { 308765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } finally { 309765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye ExceptionThrower.throwable = null; 310765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 311765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 312765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 313765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 314765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye 315765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye /** 316765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * Propagates {@code throwable} as-is without any wrapping. This is trick. 317765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * 318765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * @return nothing will ever be returned; this return type is only for your convenience, to use 319765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye * this method in "throw" statement. 320765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye */ 321765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye public static RuntimeException propagate(Throwable throwable) { 322765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye if (System.getProperty("wbp.ReflectionUtils.propagate().forceReturn") == null) { 323765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye ExceptionThrower.spit(throwable); 324765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 325765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye return null; 326765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye } 327765e52e2d30d0754625b8c7af6c36e93612f15beTor Norbye} 328