/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.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.eclipse.org/legal/epl-v10.html * * 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 com.google.dart.tools.internal.corext.refactoring.util; import org.eclipse.core.runtime.Assert; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * Simple reflection utilities. * * @coverage dart.editor.ui.refactoring.core */ public class ReflectionUtils { /** * @return the name of the {@link Class} for signature. */ public static String getClassName(Class<?> clazz) { if (clazz.isArray()) { return getClassName(clazz.getComponentType()) + "[]"; } return clazz.getName(); } /** * @return the declared {@link Field} with given name, may be private. */ public static Field getField(Object target, String name) { Assert.isNotNull(target); Assert.isNotNull(name); Class<?> targetClass = getTargetClass(target); while (targetClass != null) { Field[] declaredFields = targetClass.getDeclaredFields(); for (Field field : declaredFields) { if (field.getName().equals(name)) { field.setAccessible(true); return field; } } targetClass = targetClass.getSuperclass(); } return null; } /** * @return the value of the field with given name, may be even private. */ @SuppressWarnings("unchecked") public static <T> T getFieldObject(Object target, String name) { Assert.isNotNull(target); Assert.isNotNull(name); Field field = getField(target, name); if (field == null) { Class<?> targetClass = getTargetClass(target); throw new IllegalArgumentException(name + " in " + targetClass); } try { return (T) field.get(target); } catch (Throwable e) { throw ExecutionUtils.propagate(e); } } /** * @return the declared {@link Method} with given signature, may be private. */ public static Method getMethod(Object target, String signature) { Assert.isNotNull(target); Assert.isNotNull(signature); Class<?> targetClass = getTargetClass(target); while (targetClass != null) { for (Method method : targetClass.getDeclaredMethods()) { if (getMethodSignature(method).equals(signature)) { method.setAccessible(true); return method; } } targetClass = targetClass.getSuperclass(); } return null; } /** * Invokes method declared in <code>target</code>, may be private. Re-throws any {@link Exception} * as is, without declaring or wrapping them. */ @SuppressWarnings("unchecked") public static <T> T invokeMethod(Object target, String signature, Object... args) { Assert.isNotNull(target); Assert.isNotNull(signature); Method method = getMethod(target, signature); if (method == null) { Class<?> targetClass = getTargetClass(target); throw new IllegalArgumentException(signature + " in " + targetClass); } try { return (T) method.invoke(target, args); } catch (Throwable e) { if (e instanceof InvocationTargetException) { e = e.getCause(); } throw ExecutionUtils.propagate(e); } } /** * Sets the new for field with given name. */ public static void setField(Object target, String name, Object value) { Assert.isNotNull(target); Assert.isNotNull(name); Field field = getField(target, name); if (field == null) { Class<?> targetClass = getTargetClass(target); throw new IllegalArgumentException(name + " in " + targetClass); } try { field.set(target, value); } catch (Throwable e) { throw ExecutionUtils.propagate(e); } } /** * @return the signature of the given {@link Method}, not JVM signature however, just some * reasonable signature to write manually. */ private static String getMethodSignature(Method method) { StringBuilder sb = new StringBuilder(); sb.append(method.getName()); sb.append('('); boolean firstParameter = true; for (Class<?> parameterType : method.getParameterTypes()) { if (!firstParameter) { sb.append(','); } firstParameter = false; sb.append(getClassName(parameterType)); } sb.append(')'); return sb.toString(); } /** * @return the {@link Class} or the given "target" - "target" itself if it is {@link Class} or its * {@link Class} if just some object. */ private static Class<?> getTargetClass(Object target) { if (target instanceof Class) { return (Class<?>) target; } return target.getClass(); } }