| /******************************************************************************* |
| * Copyright (c) 2011, 2012 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jdt.debug.tests.ui; |
| |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.InvocationTargetException; |
| import java.lang.reflect.Method; |
| |
| import org.eclipse.core.runtime.Assert; |
| |
| /** |
| * Helper class for accessing classes and members which cannot be accessed using standard Java |
| * access control like private or package visible elements. |
| * |
| * @since 3.7 |
| */ |
| public class Accessor { |
| |
| /** The class to access. */ |
| private Class<?> fClass; |
| /** The instance to access. */ |
| private Object fInstance; |
| |
| /** |
| * Creates an accessor for the given <code>instance</code> and <code>class</code>. Only |
| * non-inherited members that particular <code>class</code> can be accessed. |
| * |
| * @param instance |
| * the instance |
| * @param clazz |
| * the class |
| */ |
| public Accessor(Object instance, Class<?> clazz) { |
| org.eclipse.core.runtime.Assert.isNotNull(instance); |
| Assert.isNotNull(clazz); |
| fInstance = instance; |
| fClass = clazz; |
| } |
| |
| /** |
| * Creates an accessor for the given <code>instance</code> and <code>class</code>. Only |
| * non-inherited members that particular <code>class</code> can be accessed. |
| * |
| * @param instance |
| * the instance |
| * @param className |
| * the name of the class |
| * @param classLoader |
| * the class loader to use i.e. <code>getClass().getClassLoader()</code> |
| */ |
| public Accessor(Object instance, String className, ClassLoader classLoader) { |
| Assert.isNotNull(instance); |
| Assert.isNotNull(className); |
| Assert.isNotNull(classLoader); |
| fInstance = instance; |
| try { |
| fClass = Class.forName(className, true, classLoader); |
| } catch (ClassNotFoundException e) { |
| fail(); |
| } catch (ExceptionInInitializerError e) { |
| fail(); |
| } |
| } |
| |
| /** |
| * Creates an accessor for the given class. |
| * <p> |
| * In order to get the type information from the given arguments they must all be instanceof |
| * Object. Use {@link #Accessor(String, ClassLoader, Class[], Object[])} if this is not the |
| * case. |
| * </p> |
| * |
| * @param className |
| * the name of the class |
| * @param classLoader |
| * the class loader to use i.e. <code>getClass().getClassLoader()</code> |
| * @param constructorArgs |
| * the constructor arguments which must all be instance of Object |
| */ |
| public Accessor(String className, ClassLoader classLoader, Object[] constructorArgs) { |
| this(className, classLoader, getTypes(constructorArgs), constructorArgs); |
| } |
| |
| /** |
| * Creates an accessor for the given class. |
| * |
| * @param className |
| * the name of the class |
| * @param classLoader |
| * the class loader to use i.e. <code>getClass().getClassLoader()</code> |
| * @param constructorTypes |
| * the types of the constructor arguments |
| * @param constructorArgs |
| * the constructor arguments |
| */ |
| public Accessor(String className, ClassLoader classLoader, Class<?>[] constructorTypes, Object[] constructorArgs) { |
| try { |
| fClass = Class.forName(className, true, classLoader); |
| } catch (ClassNotFoundException e) { |
| fail(); |
| } catch (ExceptionInInitializerError e) { |
| fail(); |
| } |
| Constructor<?> constructor = null; |
| try { |
| constructor = fClass.getDeclaredConstructor(constructorTypes); |
| } catch (SecurityException e2) { |
| fail(); |
| } catch (NoSuchMethodException e2) { |
| fail(); |
| } |
| Assert.isNotNull(constructor); |
| constructor.setAccessible(true); |
| try { |
| fInstance = constructor.newInstance(constructorArgs); |
| } catch (IllegalArgumentException e) { |
| fail(); |
| } catch (InvocationTargetException e) { |
| fail(); |
| } catch (InstantiationException e) { |
| fail(); |
| } catch (IllegalAccessException e) { |
| fail(); |
| } |
| } |
| |
| /** |
| * Creates an accessor for the given class. |
| * <p> |
| * This constructor is used to access static stuff. |
| * </p> |
| * |
| * @param className |
| * the name of the class |
| * @param classLoader |
| * the class loader to use i.e. <code>getClass().getClassLoader()</code> |
| */ |
| public Accessor(String className, ClassLoader classLoader) { |
| try { |
| fClass = Class.forName(className, true, classLoader); |
| } catch (ClassNotFoundException e) { |
| fail(); |
| } catch (ExceptionInInitializerError e) { |
| fail(); |
| } |
| } |
| |
| /** |
| * Creates an accessor for the given class. |
| * <p> |
| * This constructor is used to access static stuff. |
| * </p> |
| * |
| * @param clazz |
| * the class |
| */ |
| public Accessor(Class<?> clazz) { |
| Assert.isNotNull(clazz); |
| fClass = clazz; |
| } |
| |
| /** |
| * Invokes the method with the given method name and arguments. |
| * <p> |
| * In order to get the type information from the given arguments all those arguments must be |
| * instance of Object. Use {@link #invoke(String, Class[], Object[])} if this is not the case. |
| * </p> |
| * |
| * @param methodName |
| * the method name |
| * @param arguments |
| * the method arguments which must all be instance of Object |
| * @return the method return value |
| */ |
| public Object invoke(String methodName, Object[] arguments) { |
| return invoke(methodName, getTypes(arguments), arguments); |
| } |
| |
| /** |
| * Invokes the method with the given method name and arguments. |
| * |
| * @param methodName |
| * the method name |
| * @param types |
| * the argument types |
| * @param arguments |
| * the method arguments |
| * @return the method return value |
| */ |
| public Object invoke(String methodName, Class<?>[] types, Object[] arguments) { |
| Method method = null; |
| try { |
| method = fClass.getDeclaredMethod(methodName, types); |
| } catch (SecurityException e) { |
| fail(); |
| } catch (NoSuchMethodException ex) { |
| fail(); |
| } |
| Assert.isNotNull(method); |
| method.setAccessible(true); |
| try { |
| return method.invoke(fInstance, arguments); |
| } catch (IllegalArgumentException e) { |
| fail(); |
| } catch (InvocationTargetException e) { |
| fail(); |
| } catch (IllegalAccessException e) { |
| fail(); |
| } |
| return null; |
| } |
| |
| /** |
| * Assigns the given value to the field with the given name. |
| * |
| * @param fieldName |
| * the field name |
| * @param value |
| * the value to assign to the field |
| */ |
| public void set(String fieldName, Object value) { |
| Field field = getField(fieldName); |
| try { |
| field.set(fInstance, value); |
| } catch (IllegalArgumentException e) { |
| fail(); |
| } catch (IllegalAccessException e) { |
| fail(); |
| } |
| } |
| |
| /** |
| * Assigns the given value to the field with the given name. |
| * |
| * @param fieldName |
| * the field name |
| * @param value |
| * the value to assign to the field |
| */ |
| public void set(String fieldName, boolean value) { |
| Field field = getField(fieldName); |
| try { |
| field.setBoolean(fInstance, value); |
| } catch (IllegalArgumentException e) { |
| fail(); |
| } catch (IllegalAccessException e) { |
| fail(); |
| } |
| } |
| |
| /** |
| * Assigns the given value to the field with the given name. |
| * |
| * @param fieldName |
| * the field name |
| * @param value |
| * the value to assign to the field |
| */ |
| public void set(String fieldName, int value) { |
| Field field = getField(fieldName); |
| try { |
| field.setInt(fInstance, value); |
| } catch (IllegalArgumentException e) { |
| fail(); |
| } catch (IllegalAccessException e) { |
| fail(); |
| } |
| } |
| |
| /** |
| * Returns the value of the field with the given name. |
| * |
| * @param fieldName |
| * the field name |
| * @return the value of the field |
| */ |
| public Object get(String fieldName) { |
| Field field = getField(fieldName); |
| try { |
| return field.get(fInstance); |
| } catch (IllegalArgumentException e) { |
| fail(); |
| } catch (IllegalAccessException e) { |
| fail(); |
| } |
| // Unreachable code |
| return null; |
| } |
| |
| /** |
| * Returns the value of the field with the given name. |
| * |
| * @param fieldName |
| * the field name |
| * @return the value of the field |
| */ |
| public boolean getBoolean(String fieldName) { |
| Field field = getField(fieldName); |
| try { |
| return field.getBoolean(fInstance); |
| } catch (IllegalArgumentException e) { |
| fail(); |
| } catch (IllegalAccessException e) { |
| fail(); |
| } |
| // Unreachable code |
| return false; |
| } |
| |
| /** |
| * Returns the value of the field with the given name. |
| * |
| * @param fieldName |
| * the field name |
| * @return the value of the field |
| */ |
| public int getInt(String fieldName) { |
| Field field = getField(fieldName); |
| try { |
| return field.getInt(fInstance); |
| } catch (IllegalArgumentException e) { |
| fail(); |
| } catch (IllegalAccessException e) { |
| fail(); |
| } |
| // Unreachable code |
| return 0; |
| } |
| |
| public Field getField(String fieldName) { |
| Field field = null; |
| try { |
| field = fClass.getDeclaredField(fieldName); |
| } catch (SecurityException e) { |
| fail(); |
| } catch (NoSuchFieldException e) { |
| fail(); |
| } |
| field.setAccessible(true); |
| return field; |
| } |
| |
| private static Class<?>[] getTypes(Object[] objects) { |
| if (objects == null) |
| return null; |
| |
| int length = objects.length; |
| Class<?>[] classes = new Class[length]; |
| for (int i = 0; i < length; i++) { |
| Assert.isNotNull(objects[i]); |
| classes[i] = objects[i].getClass(); |
| } |
| return classes; |
| } |
| |
| private void fail() { |
| Assert.isTrue(false); |
| } |
| } |