/******************************************************************************* * Copyright (c) 2008 Olivier Moises * * 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: * Olivier Moises- initial API and implementation *******************************************************************************/ package org.eclipse.wazaabi.engine.edp.tests; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.eclipse.wazaabi.engine.edp.coderesolution.AbstractCodeDescriptor; public class ReflectionUtils { /** * Sets a private field unsig java reflection. * * @param target * The object owning the field to be set. * @param privateFieldName * The name of the field to set. * @param newValue * The future field value. */ public static void setPrivateField(Object target, String privateFieldName, Object newValue) { Field privateField; try { privateField = target.getClass().getDeclaredField(privateFieldName); privateField.setAccessible(true); privateField.set(target, newValue); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchFieldException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * Shortcut allowing execution of a CodeDescriptor Method while checking the * existence of the method. * * @param codeDescriptor * @param methodName * @param parameterTypes * @param returnType * @param parameterValues * @return */ public static Object invokeMethod(AbstractCodeDescriptor codeDescriptor, String methodName, Class<?>[] parameterTypes, Class<?> returnType, Object[] parameterValues) { assertTrue(codeDescriptor != null); String[] parameterNames = new String[] { "eventDispatcher", "eventHandler", "event" }; AbstractCodeDescriptor.MethodDescriptor methodDescriptor = codeDescriptor .getMethodDescriptor(methodName, parameterNames , parameterTypes, returnType); assertTrue(methodDescriptor != null); return codeDescriptor.invokeMethod(methodDescriptor, parameterValues); } /** * Invoke a static private method on the given class. Due to * <code>ClassLoader</code> differences, types must be given as string * instead of java classes. * * @param clazz * The java.lang.class of the type on which invoke the method, in * osgi model, the class must be attached to the class loader * which owns it (not the JUnit classloader). The classloader * must be compatible with the parameters classloader too. * @param methodName * The method to invoke * @param parameterTypeNames * A array of java.lang.String, can be null or empty * @param returnTypeName * The name of the returned type * @param parameterValues * The values of the parameters. * @return The result of the invocation of the method. * * @see #getDeclaredMethod(Class, String, String[], String) */ public static Object invokeStaticPrivateMethod(Class<?> clazz, String methodName, String[] parameterTypeNames, String returnTypeName, Object[] parameterValues) { Method method = getDeclaredMethod(clazz, methodName, parameterTypeNames, returnTypeName); if (method != null) { try { method.setAccessible(true); return method.invoke(null, parameterValues); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } else throw new RuntimeException("Declared method " + methodName + " not found in " + clazz); } /** * Invoke a public method on the given class. Due to * <code>ClassLoader</code> issues, types must be given as string instead of * java classes. * * @param target * The object on which invoke the method, in osgi model, the * object is given by the plugin owning it and must be attached * to a classloader compatible with the parameters one. * @param methodName * The method to invoke * @param parameterTypeNames * A array of java.lang.String, can be null or empty * @param returnTypeName * The name of the returned type * @param parameterValues * The values of the parameters. * @return The result of the invocation of the method. * * @see #getDeclaredMethod(Class, String, String[], String) */ public static Object invokePublicMethod(Object target, String methodName, String[] parameterTypeNames, String returnTypeName, Object[] parameterValues) { assertNotNull(target); Method method = getMethod(target.getClass(), methodName, parameterTypeNames, returnTypeName); if (method != null) { try { return method.invoke(target, parameterValues); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } return null; } else throw new RuntimeException("Declared method " + methodName + " not found in " + target.getClass()); } /** * Returns a method found in the declared methods (@see * {@link java.lang.Class#getDeclaredMethods()} of the given class. In order * to avoid <code>ClassLoader</code> issues, type names are given instead of * <code>java.lang.Class</code>. * * @param clazz * The java.lang.class of the type on which invoke the method, in * osgi model, the class must be attached to the classloader of * the bundle which owns it (not the JUnit classloader). * @param methodName * The method to invoke * @param parameterTypeNames * A array of java.lang.String, can be null or empty * @param returnTypeName * The name of the returned type * @return A <code>java.lang.reflect.method</code> if found, null otherwise. */ public static Method getDeclaredMethod(Class<?> clazz, String methodName, String[] parameterTypeNames, String returnTypeName) { assertTrue(clazz != null); assertNotNull(methodName); assertTrue(!methodName.equals("")); //$NON-NLS-1$ if (parameterTypeNames == null) parameterTypeNames = new String[0]; for (Method method : clazz.getDeclaredMethods()) { if (methodName.equals(method.getName())) { if (parameterTypeNames.length != method.getParameterTypes().length) continue; if (returnTypeName == null && method.getReturnType() != null) continue; if (returnTypeName != null && method.getReturnType() == null) continue; if (returnTypeName != null && method.getReturnType() != null && !returnTypeName.equals(method.getReturnType() .getName())) continue; boolean areSameTypes = true; for (int i = 0; i < parameterTypeNames.length; i++) { if (!method.getParameterTypes()[i].getName().equals( parameterTypeNames[i])) { areSameTypes = false; break; } } if (areSameTypes) return method; } } return null; } /** * Returns a method found in the methods (@see * {@link java.lang.Class#getMethods()} of the given class. In order to * avoid <code>ClassLoader</code> issues, type names are given instead of * <code>java.lang.Class</code>. * * @param clazz * The java.lang.class of the type on which invoke the method, in * osgi model, the class must be attached to the classloader of * the bundle which owns it (not the JUnit classloader). * @param methodName * The method to invoke * @param parameterTypeNames * A array of java.lang.String, can be null or empty * @param returnTypeName * The name of the returned type * @return A <code>java.lang.reflect.method</code> if found, null otherwise. */ public static Method getMethod(Class<?> clazz, String methodName, String[] parameterTypeNames, String returnTypeName) { assertTrue(clazz != null); assertNotNull(methodName); assertTrue(!methodName.equals("")); //$NON-NLS-1$ if (parameterTypeNames == null) parameterTypeNames = new String[0]; for (Method method : clazz.getMethods()) { if (methodName.equals(method.getName())) { if (parameterTypeNames.length != method.getParameterTypes().length) continue; if (returnTypeName == null && method.getReturnType() != null) continue; if (returnTypeName != null && method.getReturnType() == null) continue; if (returnTypeName != null && method.getReturnType() != null && !returnTypeName.equals(method.getReturnType() .getName())) continue; boolean areSameTypes = true; for (int i = 0; i < parameterTypeNames.length; i++) { if (!method.getParameterTypes()[i].getName().equals( parameterTypeNames[i])) { areSameTypes = false; break; } } if (areSameTypes) return method; } } return null; } }