/*******************************************************************************
* Copyright (c) 2011 Google, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.wb.internal.core.utils.reflect;
import com.google.common.collect.Maps;
import org.eclipse.wb.internal.core.utils.check.Assert;
import java.lang.reflect.Field;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.Map;
/**
* Contains different Java reflection utilities.
*
* @author scheglov_ke
* @coverage core.util
*/
public class ReflectionUtils {
////////////////////////////////////////////////////////////////////////////
//
// Constructor
//
////////////////////////////////////////////////////////////////////////////
private ReflectionUtils() {
}
////////////////////////////////////////////////////////////////////////////
//
// Signature
//
////////////////////////////////////////////////////////////////////////////
/**
* @param runtime
* is true
if we need name for class loading, false
if we need
* name for source generation.
*
* @return the fully qualified name of given {@link Type}.
*/
public static String getFullyQualifiedName(Type type, boolean runtime) {
Assert.isNotNull(type);
// Class
if (type instanceof Class>) {
Class> clazz = (Class>) type;
// array
if (clazz.isArray()) {
return getFullyQualifiedName(clazz.getComponentType(), runtime) + "[]";
}
// object
String name = clazz.getName();
if (!runtime) {
name = name.replace('$', '.');
}
return name;
}
// GenericArrayType
if (type instanceof GenericArrayType) {
GenericArrayType genericArrayType = (GenericArrayType) type;
return getFullyQualifiedName(genericArrayType.getGenericComponentType(), runtime) + "[]";
}
// ParameterizedType
if (type instanceof ParameterizedType) {
ParameterizedType parameterizedType = (ParameterizedType) type;
Type rawType = parameterizedType.getRawType();
// raw type
StringBuilder sb = new StringBuilder();
sb.append(getFullyQualifiedName(rawType, runtime));
// type arguments
sb.append("<");
boolean firstTypeArgument = true;
for (Type typeArgument : parameterizedType.getActualTypeArguments()) {
if (!firstTypeArgument) {
sb.append(",");
}
firstTypeArgument = false;
sb.append(getFullyQualifiedName(typeArgument, runtime));
}
sb.append(">");
// done
return sb.toString();
}
// WildcardType
if (type instanceof WildcardType) {
WildcardType wildcardType = (WildcardType) type;
return "? extends " + getFullyQualifiedName(wildcardType.getUpperBounds()[0], runtime);
}
// TypeVariable
TypeVariable> typeVariable = (TypeVariable>) type;
return typeVariable.getName();
}
/**
* Appends fully qualified names of given parameter types (appends also "()"
).
*/
private static void appendParameterTypes(StringBuilder buffer, Type[] parameterTypes) {
buffer.append('(');
boolean firstParameter = true;
for (Type parameterType : parameterTypes) {
if (firstParameter) {
firstParameter = false;
} else {
buffer.append(',');
}
buffer.append(getFullyQualifiedName(parameterType, false));
}
buffer.append(')');
}
////////////////////////////////////////////////////////////////////////////
//
// Method
//
////////////////////////////////////////////////////////////////////////////
/**
* @return all declared {@link Method}'s, including protected and private.
*/
public static Map getMethods(Class> clazz) {
Map methods = Maps.newHashMap();
// process classes
for (Class> c = clazz; c != null; c = c.getSuperclass()) {
for (Method method : c.getDeclaredMethods()) {
String signature = getMethodSignature(method);
if (!methods.containsKey(signature)) {
method.setAccessible(true);
methods.put(signature, method);
}
}
}
// process interfaces
for (Class> interfaceClass : clazz.getInterfaces()) {
for (Method method : interfaceClass.getDeclaredMethods()) {
String signature = getMethodSignature(method);
if (!methods.containsKey(signature)) {
method.setAccessible(true);
methods.put(signature, method);
}
}
}
// done
return methods;
}
/**
* @return signature for given {@link Method}. This signature is not same signature as in JVM or
* JDT, just some string that unique identifies method in its {@link Class}.
*/
public static String getMethodSignature(Method method) {
Assert.isNotNull(method);
return getMethodSignature(method.getName(), method.getParameterTypes());
}
/**
* Returns the signature of {@link Method} with given combination of name and parameter types.
* This signature is not same signature as in JVM or JDT, just some string that unique identifies
* method in its {@link Class}.
*
* @param name
* the name of {@link Method}.
* @param parameterTypes
* the types of {@link Method} parameters.
*
* @return signature of {@link Method}.
*/
public static String getMethodSignature(String name, Type... parameterTypes) {
Assert.isNotNull(name);
Assert.isNotNull(parameterTypes);
//
StringBuilder buffer = new StringBuilder();
buffer.append(name);
appendParameterTypes(buffer, parameterTypes);
return buffer.toString();
}
private static final ClassMap