deep-c-rsc/JCGO/sunawt/fix/sun/reflect/misc/MethodUtil.java
2021-07-16 17:12:20 -05:00

358 lines
12 KiB
Java

/*
* This file is modified by Ivan Maidanski <ivmai@ivmaisoft.com>
* Project name: JCGO-SUNAWT (http://www.ivmaisoft.com/jcgo/)
*/
/*
* @(#)MethodUtil.java
*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package sun.reflect.misc;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.PrivilegedExceptionAction;
import java.security.SecureClassLoader;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public final class MethodUtil extends SecureClassLoader
{
private static final class Signature
{
private final String methodName;
private final Class[] argClasses;
private volatile int hashCode;
Signature(Method method) {
methodName = method.getName();
argClasses = method.getParameterTypes();
}
public int hashCode() {
if (hashCode == 0) {
int v = 17;
v = 37 * v + methodName.hashCode();
if (argClasses != null) {
for (int j = 0; j < argClasses.length; j++) {
v = 37 * v + (argClasses[j] != null ?
argClasses[j].hashCode() : 0);
}
}
hashCode = v;
}
return hashCode;
}
public boolean equals(Object obj) {
if (this == obj)
return true;
Signature signature = (Signature)obj;
if (!methodName.equals(signature.methodName))
return false;
if (argClasses.length != signature.argClasses.length)
return false;
for (int i = 0; i < argClasses.length; i++) {
if (argClasses[i] != signature.argClasses[i])
return false;
}
return true;
}
}
private static /* final */ String MISC_PKG = "sun.reflect.misc.";
private static final String TRAMPOLINE = MISC_PKG + "Trampoline";
private static final Method bounce = getTrampoline();
private MethodUtil() {
}
private static Class getTrampolineClass() {
try {
return Class.forName(TRAMPOLINE, true, new MethodUtil());
}
catch (ClassNotFoundException e) {
return null;
}
}
private static Method getTrampoline() {
Method method = null;
try {
method = (Method)AccessController.doPrivileged(
new PrivilegedExceptionAction() {
public Object run() throws Exception {
Class klass = Trampoline.class; // MethodUtil.getTrampolineClass();
Class parameterTypes[] = {
java.lang.reflect.Method.class,
Object.class,
Object[].class
};
Method m = klass.getDeclaredMethod("invoke", parameterTypes);
m.setAccessible(true);
return m;
}
});
}
catch (Exception e) {
throw new InternalError("bouncer cannot be found");
}
return method;
}
private static byte[] getBytes(URL url) throws IOException {
URLConnection urlconnection = url.openConnection();
if (urlconnection instanceof HttpURLConnection) {
if (((HttpURLConnection)urlconnection).getResponseCode() >= 400)
throw new IOException("open HTTP connection failed.");
}
int i = urlconnection.getContentLength();
BufferedInputStream bufferedinputstream =
new BufferedInputStream(urlconnection.getInputStream());
byte abyte0[];
try {
if (i != -1) {
abyte0 = new byte[i];
int l;
for (; i > 0; i -= l) {
l = bufferedinputstream.read(abyte0, abyte0.length - i, i);
if (l == -1)
throw new IOException("unexpected EOF");
}
} else {
abyte0 = new byte[8192];
int i1 = 0;
do {
int j;
if ((j = bufferedinputstream.read(abyte0, i1,
abyte0.length - i1)) == -1)
break;
i1 += j;
if (i1 >= abyte0.length) {
byte abyte1[] = new byte[i1 * 2];
System.arraycopy(abyte0, 0, abyte1, 0, i1);
abyte0 = abyte1;
}
} while (true);
if (i1 != abyte0.length) {
byte abyte2[] = new byte[i1];
System.arraycopy(abyte0, 0, abyte2, 0, i1);
abyte0 = abyte2;
}
}
} finally {
bufferedinputstream.close();
}
return abyte0;
}
protected Class findClass(String name)
throws ClassNotFoundException {
if (!name.startsWith(MISC_PKG))
throw new ClassNotFoundException(name);
String s1 = name.replace('.', '/').concat(".class");
URL url = getResource(s1);
if (url != null) {
try {
return defineClass(name, url);
}
catch (IOException ioexception) {
throw new ClassNotFoundException(name, ioexception);
}
}
else {
throw new ClassNotFoundException(name);
}
}
protected synchronized Class loadClass(String name, boolean flag)
throws ClassNotFoundException {
ReflectUtil.checkPackageAccess(name);
Class klass = findLoadedClass(name);
if (klass == null) {
try {
klass = findClass(name);
}
catch (ClassNotFoundException classnotfoundexception) {
}
if (klass == null)
klass = getParent().loadClass(name);
}
if (flag)
resolveClass(klass);
return klass;
}
public static Method[] getMethods(Class klass) {
ReflectUtil.checkPackageAccess(klass);
return klass.getMethods();
}
public static Method[] getPublicMethods(Class klass) {
if (System.getSecurityManager() == null)
return klass.getMethods();
HashMap hashmap = new HashMap();
do {
if (klass == null)
break;
boolean flag = getInternalPublicMethods(klass, hashmap);
if (flag)
break;
getInterfaceMethods(klass, hashmap);
klass = klass.getSuperclass();
} while (true);
Collection collection = hashmap.values();
return (Method[])collection.toArray(new Method[collection.size()]);
}
private static void addMethod(Map map, Method method) {
Signature signature = new Signature(method);
if (!map.containsKey(signature)) {
map.put(signature, method);
} else {
if (!method.getDeclaringClass().isInterface()) {
Method m = (Method)map.get(signature);
if (m.getDeclaringClass().isInterface())
map.put(signature, method);
}
}
}
protected PermissionCollection getPermissions(CodeSource codesource) {
PermissionCollection permissioncollection =
super.getPermissions(codesource);
permissioncollection.add(new AllPermission());
return permissioncollection;
}
private static void getInterfaceMethods(Class klass, Map map) {
Class interfaces[] = klass.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
Class class2 = interfaces[i];
if (!getInternalPublicMethods(class2, map))
getInterfaceMethods(class2, map);
}
}
private static boolean getInternalPublicMethods(Class class1, Map map) {
Method amethod[] = null;
try {
if (!Modifier.isPublic(class1.getModifiers()))
return false;
if (!ReflectUtil.isPackageAccessible(class1))
return false;
amethod = class1.getMethods();
}
catch (SecurityException securityexception) {
return false;
}
boolean flag = true;
int i = 0;
do {
if (i >= amethod.length)
break;
Class class2 = amethod[i].getDeclaringClass();
if (!Modifier.isPublic(class2.getModifiers())) {
flag = false;
break;
}
i++;
} while (true);
if (flag) {
for (int j = 0; j < amethod.length; j++)
addMethod(map, amethod[j]);
} else {
for (int k = 0; k < amethod.length; k++) {
Class class3 = amethod[k].getDeclaringClass();
if (class1.equals(class3))
addMethod(map, amethod[k]);
}
}
return flag;
}
private Class defineClass(String name, URL url) throws IOException {
byte abyte0[] = getBytes(url);
CodeSource codesource = new CodeSource(null,
(java.security.cert.Certificate[])null);
if (!name.equals(TRAMPOLINE)) {
throw new IOException("MethodUtil: bad name " + name);
}
return defineClass(name, abyte0, 0, abyte0.length, codesource);
}
public static Object invoke(Method method, Object obj, Object aobj[])
throws InvocationTargetException, IllegalAccessException {
if (method.getDeclaringClass().equals(
java.security.AccessController.class) ||
method.getDeclaringClass().equals(java.lang.reflect.Method.class))
throw new InvocationTargetException(
new UnsupportedOperationException("invocation not supported"));
try {
return bounce.invoke(null, new Object[] { method, obj, aobj });
}
catch (InvocationTargetException invocationtargetexception) {
Throwable throwable = invocationtargetexception.getCause();
if (throwable instanceof InvocationTargetException)
throw (InvocationTargetException)throwable;
if (throwable instanceof IllegalAccessException)
throw (IllegalAccessException)throwable;
if (throwable instanceof RuntimeException)
throw (RuntimeException)throwable;
if (throwable instanceof Error)
throw (Error)throwable;
throw new Error("Unexpected invocation error", throwable);
}
catch (IllegalAccessException illegalaccessexception) {
throw new Error("Unexpected invocation error",
illegalaccessexception);
}
}
public static Method getMethod(Class class1, String name,
Class parameterTypes[])
throws NoSuchMethodException {
ReflectUtil.checkPackageAccess(class1);
return class1.getMethod(name, parameterTypes);
}
}
class Trampoline
{
Trampoline() {
}
private static Object invoke(Method method, Object obj, Object aobj[])
throws InvocationTargetException, IllegalAccessException {
return method.invoke(obj, aobj);
}
}