/* * Distributed as part of mchange-commons-java 0.2.11 * * Copyright (C) 2015 Machinery For Change, Inc. * * Author: Steve Waldman <swaldman@mchange.com> * * This library is free software; you can redistribute it and/or modify * it under the terms of EITHER: * * 1) The GNU Lesser General Public License (LGPL), version 2.1, as * published by the Free Software Foundation * * OR * * 2) The Eclipse Public License (EPL), version 1.0 * * You may choose which license to accept if you wish to redistribute * or modify this work. You may offer derivatives of this work * under the license you have chosen, or you may provide the same * choice of license which you have been offered here. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * You should have received copies of both LGPL v2.1 and EPL v1.0 * along with this software; see the files LICENSE-EPL and LICENSE-LGPL. * If not, the text of these licenses are currently available at * * LGPL v2.1: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html * EPL v1.0: http://www.eclipse.org/org/documents/epl-v10.php * */ package com.mchange.v2.reflect; import java.lang.reflect.*; import java.util.*; public final class ReflectUtils { public final static Class[] PROXY_CTOR_ARGS = new Class[]{ InvocationHandler.class }; public static Constructor findProxyConstructor(ClassLoader proxyClassLoader, Class intfc) throws NoSuchMethodException { return findProxyConstructor( proxyClassLoader, new Class[] { intfc } ); } public static Constructor findProxyConstructor(ClassLoader proxyClassLoader, Class[] interfaces) throws NoSuchMethodException { Class proxyCl = Proxy.getProxyClass(proxyClassLoader, interfaces); return proxyCl.getConstructor( PROXY_CTOR_ARGS ); } public static boolean isPublic( Member m ) { return ((m.getModifiers() & Modifier.PUBLIC) != 0); } public static boolean isPublic( Class cl ) { return ((cl.getModifiers() & Modifier.PUBLIC) != 0); } public static Class findPublicParent( Class cl ) { do cl = cl.getSuperclass(); while (cl != null && ! isPublic(cl) ); return cl; } public static Iterator traverseInterfaces( Class cl ) { Set set = new HashSet(); if (cl.isInterface()) set.add( cl ); addParentInterfaces( set, cl ); return set.iterator(); } private static void addParentInterfaces(Set set, Class cl) { Class[] intfcs = cl.getInterfaces(); for (int i = 0, len = intfcs.length; i < len; ++i) { set.add( intfcs[i] ); addParentInterfaces( set, intfcs[i] ); } } /** * Finds a version of the Method m in a public class * or interface. Classes versions will be found before * interface versions, but no guarantees about which * interface if the method is declared in both. */ public static Method findInPublicScope( Method m ) { if (! isPublic(m)) return null; Class origClass = m.getDeclaringClass(); if (isPublic( origClass )) return m; //climb for public parent class Class cl = origClass; while ((cl = findPublicParent(cl)) != null) { try { return cl.getMethod( m.getName(), m.getParameterTypes() ); } catch (NoSuchMethodException e) { /* IGNORE... we didn't find it (this'll be slow) */ } } Iterator ii = traverseInterfaces( origClass ); while ( ii.hasNext() ) { cl = (Class) ii.next(); if ( isPublic( cl ) ) { try { return cl.getMethod( m.getName(), m.getParameterTypes() ); } catch (NoSuchMethodException e) { /* IGNORE... we didn't find it (this'll be slow) */ } } } return null; } private ReflectUtils() {} }