/******************************************************************************* * Copyright (c) 2015, 2016 Oracle and/or its affiliates. * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * 05/14/2015-2.7 Tomas Kraus * - Initial API and implementation. ******************************************************************************/ package org.eclipse.persistence.testing.framework; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import sun.misc.Unsafe; /** * Reflection helper methods. */ public class ReflectionHelper { private static final Unsafe unsafe; static { try { Field field = Unsafe.class.getDeclaredField("theUnsafe"); field.setAccessible(true); unsafe = (Unsafe)field.get(null); } catch (Exception e) { throw new RuntimeException(e); } } /** * Set value of private static field. * @param c Class containing static field. * @param name Static field name to be modified. * @param newValue New value to be set. * @throws NoSuchFieldException If a field with the specified name is not found. * @throws SecurityException If a security manager is present and access to the field was denied. * @throws IllegalArgumentException If an unwrapping conversion fails. * @throws IllegalAccessException If the underlying field is either inaccessible or final. */ public static final void setPrivateStatic(final Class c, final String name, final Object newValue) throws ReflectiveOperationException { final Field field = c.getDeclaredField(name); final boolean accessible = field.isAccessible(); field.setAccessible(true); field.set(null, newValue); field.setAccessible(accessible); } /** * Set value of private static final field. * Uses {@link sun.misc.Unsafe} which seems to be the only way to modify such a field in some cases. * @param c Class containing static field. * @param name Static field name to be modified. * @param newValue New value to be set. * @throws NoSuchFieldException If a field with the specified name is not found. * @throws SecurityException If a security manager is present and access to the field was denied. * @throws IllegalArgumentException If an unwrapping conversion fails. * @throws IllegalAccessException If the underlying field is either inaccessible or final. */ public static final void setPrivateStaticFinal(final Class c, final String name, final Object newValue) throws ReflectiveOperationException { final Field field = c.getDeclaredField(name); final Object base = unsafe.staticFieldBase(field); final long offset = unsafe.staticFieldOffset(field); unsafe.putObject(base, offset, newValue); } /** * Get value of private static field. * @param c Class containing static field. * @param name Static field name to be retrieved. * @return Static field value. * @throws NoSuchFieldException If a field with the specified name is not found. * @throws SecurityException If a security manager is present and access to the field was denied. * @throws IllegalArgumentException If an unwrapping conversion fails. * @throws IllegalAccessException If the underlying field is either inaccessible or final. */ public static final <T> T getPrivateStatic(final Class c, final String name) throws ReflectiveOperationException { final Field field = c.getDeclaredField(name); final boolean accessible = field.isAccessible(); field.setAccessible(true); final Object value = field.get(null); field.setAccessible(accessible); return (T)value; } /** * Create a new instance of the specified class. * @param c Class containing constructor. * @param parameterTypes Constructor parameter array. * @param args An array of objects to be passed as arguments to the constructor call * @throws InvocationTargetException If the underlying constructor throws an exception. * @throws IllegalArgumentException If an unwrapping conversion fails. * @throws IllegalAccessException If the underlying field is either inaccessible or final. * @throws InstantiationException If the class that declares the underlying constructor represents * an abstract class. * @throws SecurityException If a security manager is present and access to the field was denied. * @throws NoSuchMethodException If a field with the specified name is not found. */ public static final <T> T getInstance(final Class<T> c, final Class<?>[] parameterTypes, final Object... args) throws ReflectiveOperationException { Constructor<T> co = c.getDeclaredConstructor(parameterTypes); return co.newInstance(args); } /** * Invoke a method of the specified class instance. * @param name Method name. * @param obj Class instance containing method to invoke. * @param parameterTypes Method parameter array. * @param args An array of objects to be passed as arguments to the method call * @throws InvocationTargetException If the underlying constructor throws an exception. * @throws IllegalArgumentException If an unwrapping conversion fails. * @throws IllegalAccessException If the underlying field is either inaccessible or final. * @throws SecurityException If a security manager is present and access to the field was denied. * @throws NoSuchMethodException If a field with the specified name is not found. */ public static final Object invokeMethod( final String name, final Object obj, final Class<?>[] parameterTypes, final Object... args) throws ReflectiveOperationException { Method m = obj.getClass().getDeclaredMethod(name, parameterTypes); boolean accessible = m.isAccessible(); if (!accessible) { m.setAccessible(true); } Object result = m.invoke(obj, args); if (!accessible) { m.setAccessible(accessible); } return result; } /** * Invoke static method of the specified class. * @param name Method name. * @param c Class containing method to invoke. * @param parameterTypes Method parameter array. * @param args An array of objects to be passed as arguments to the method call * @throws InvocationTargetException If the underlying constructor throws an exception. * @throws IllegalArgumentException If an unwrapping conversion fails. * @throws IllegalAccessException If the underlying field is either inaccessible or final. * @throws SecurityException If a security manager is present and access to the field was denied. * @throws NoSuchMethodException If a field with the specified name is not found. */ public static final Object invokeStaticMethod( final String name, final Class c, final Class<?>[] parameterTypes, final Object... args) throws ReflectiveOperationException { Method m = c.getDeclaredMethod(name, parameterTypes); boolean accessible = m.isAccessible(); if (!accessible) { m.setAccessible(true); } Object result = m.invoke(null, args); if (!accessible) { m.setAccessible(accessible); } return result; } }