001// License: GPL. For details, see LICENSE file. 002package org.openstreetmap.josm.tools; 003 004import java.lang.reflect.AccessibleObject; 005import java.security.AccessController; 006import java.security.PrivilegedAction; 007import java.util.Collection; 008import java.util.function.Function; 009 010import org.openstreetmap.josm.plugins.PluginHandler; 011 012/** 013 * Reflection utilities. 014 * @since 14977 015 */ 016public final class ReflectionUtils { 017 018 private ReflectionUtils() { 019 // Hide default constructor for utils classes 020 } 021 022 /** 023 * Sets {@code AccessibleObject}(s) accessible. 024 * @param objects objects 025 * @see AccessibleObject#setAccessible 026 */ 027 public static void setObjectsAccessible(final AccessibleObject... objects) { 028 if (objects != null && objects.length > 0) { 029 AccessController.doPrivileged((PrivilegedAction<Object>) () -> { 030 for (AccessibleObject o : objects) { 031 if (o != null) { 032 o.setAccessible(true); 033 } 034 } 035 return null; 036 }); 037 } 038 } 039 040 /** 041 * To use from a method to know which class called it. 042 * @param exclusions classes to exclude from the search. Can be null 043 * @return the first calling class not present in {@code exclusions} 044 */ 045 public static Class<?> findCallerClass(Collection<Class<?>> exclusions) { 046 return findCaller(x -> { 047 try { 048 return Class.forName(x.getClassName()); 049 } catch (ClassNotFoundException e) { 050 for (ClassLoader cl : PluginHandler.getPluginClassLoaders()) { 051 try { 052 return Class.forName(x.getClassName(), true, cl); 053 } catch (ClassNotFoundException ex) { 054 Logging.trace(ex); 055 } 056 } 057 Logging.error(e); 058 return null; 059 } 060 }, exclusions); 061 } 062 063 private static <T extends Object> T findCaller(Function<StackTraceElement, T> getter, Collection<T> exclusions) { 064 StackTraceElement[] stack = Thread.currentThread().getStackTrace(); 065 for (int i = 3; i < stack.length; i++) { 066 T t = getter.apply(stack[i]); 067 if (exclusions == null || !exclusions.contains(t)) { 068 return t; 069 } 070 } 071 return null; 072 } 073}