mirror of
https://github.com/2003scape/deep-c-rsc.git
synced 2024-03-22 05:49:51 -04:00
183 lines
5.8 KiB
Java
183 lines
5.8 KiB
Java
/*
|
|
* @(#) $(JCGO)/goclsp/vm/java/lang/reflect/VMProxy.java --
|
|
* VM specific methods for Java class "Proxy" implementation.
|
|
**
|
|
* Project: JCGO (http://www.ivmaisoft.com/jcgo/)
|
|
* Copyright (C) 2001-2007 Ivan Maidanski <ivmai@ivmaisoft.com>
|
|
* All rights reserved.
|
|
**
|
|
* Class specification origin: GNU Classpath v0.93 vm/reference
|
|
*/
|
|
|
|
/*
|
|
* This is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2, or (at your option)
|
|
* any later version.
|
|
**
|
|
* 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. See the GNU
|
|
* General Public License (GPL) for more details.
|
|
**
|
|
* Linking this library statically or dynamically with other modules is
|
|
* making a combined work based on this library. Thus, the terms and
|
|
* conditions of the GNU General Public License cover the whole
|
|
* combination.
|
|
**
|
|
* As a special exception, the copyright holders of this library give you
|
|
* permission to link this library with independent modules to produce an
|
|
* executable, regardless of the license terms of these independent
|
|
* modules, and to copy and distribute the resulting executable under
|
|
* terms of your choice, provided that you also meet, for each linked
|
|
* independent module, the terms and conditions of the license of that
|
|
* module. An independent module is a module which is not derived from
|
|
* or based on this library. If you modify this library, you may extend
|
|
* this exception to your version of the library, but you are not
|
|
* obligated to do so. If you do not wish to do so, delete this
|
|
* exception statement from your version.
|
|
*/
|
|
|
|
package java.lang.reflect;
|
|
|
|
final class VMProxy
|
|
{
|
|
|
|
static final boolean HAVE_NATIVE_GET_PROXY_CLASS = true;
|
|
|
|
static boolean HAVE_NATIVE_GET_PROXY_DATA = false;
|
|
|
|
static boolean HAVE_NATIVE_GENERATE_PROXY_CLASS = true;
|
|
|
|
private VMProxy() {}
|
|
|
|
static Class getProxyClass(ClassLoader loader, Class[] interfaces)
|
|
{
|
|
return generateProxyClass(loader,
|
|
checkAndComputePkgName(loader, interfaces), interfaces);
|
|
}
|
|
|
|
static Proxy.ProxyData getProxyData(ClassLoader loader, Class[] interfaces)
|
|
{
|
|
/* dummy */
|
|
throw new InternalError();
|
|
}
|
|
|
|
static Class generateProxyClass(ClassLoader loader, Proxy.ProxyData data)
|
|
{
|
|
return generateProxyClass(loader, data.pack, data.interfaces);
|
|
}
|
|
|
|
static final Object invokeProxyHandler0X(Object proxyObj,
|
|
Class declaringClass, int[] intArgs, long[] longArgs, float[] floatArgs,
|
|
double[] doubleArgs, Object[] objectArgs, int slot, int proxySlot)
|
|
throws Throwable /* hard-coded method signature */
|
|
{ /* called from native code */
|
|
Proxy proxy = (Proxy) proxyObj;
|
|
InvocationHandler handler = proxy.h;
|
|
if (handler == null)
|
|
throw new NullPointerException();
|
|
return VMMethod.invokeProxyHandler(handler, proxy, declaringClass, intArgs,
|
|
longArgs, floatArgs, doubleArgs, objectArgs, slot, proxySlot);
|
|
}
|
|
|
|
private static String checkAndComputePkgName(ClassLoader loader,
|
|
Class[] interfaces)
|
|
{
|
|
String packageName = null;
|
|
int i = interfaces.length;
|
|
while (i-- > 0)
|
|
{
|
|
Class iface = interfaces[i];
|
|
String ifaceName = iface.getName();
|
|
if (!iface.isInterface())
|
|
throw new IllegalArgumentException("not an interface: " + ifaceName);
|
|
Class aclass = null;
|
|
try
|
|
{
|
|
aclass = Class.forName(ifaceName, false, loader);
|
|
}
|
|
catch (ClassNotFoundException e) {}
|
|
if (aclass != iface)
|
|
throw new IllegalArgumentException(
|
|
"interface not accessible in classloader: " + ifaceName);
|
|
if ((iface.getModifiers() & Modifier.PUBLIC) == 0)
|
|
{
|
|
String pkgName = ifaceName.substring(0, ifaceName.lastIndexOf('.') + 1);
|
|
if (packageName != null)
|
|
{
|
|
if (!packageName.equals(pkgName))
|
|
throw new IllegalArgumentException(
|
|
"non-public interfaces from different packages: " + ifaceName);
|
|
}
|
|
else packageName = pkgName;
|
|
}
|
|
for (int j = 0; j < i; j++)
|
|
if (interfaces[j] == iface)
|
|
throw new IllegalArgumentException("duplicate interface: " + ifaceName);
|
|
/* check for methods return type not implemented */
|
|
}
|
|
return packageName != null ? packageName : "";
|
|
}
|
|
|
|
private static Class generateProxyClass(ClassLoader loader,
|
|
String packageName, Class[] interfaces)
|
|
{
|
|
if (interfaces == null) /* hack */
|
|
{
|
|
try
|
|
{
|
|
invokeProxyHandler0X(new Proxy(null), null, null, null, null, null, null,
|
|
-1, -1); /* hack */
|
|
}
|
|
catch (Throwable e) {}
|
|
}
|
|
String proxyClassName = makeProxyClassName(packageName, interfaces);
|
|
if (loader == null)
|
|
loader = ClassLoader.getSystemClassLoader();
|
|
try
|
|
{
|
|
return loader.loadClass(proxyClassName);
|
|
}
|
|
catch (ClassNotFoundException e) {}
|
|
throw new OutOfMemoryError("cannot create proxy class for: " +
|
|
ifacesToString(interfaces));
|
|
}
|
|
|
|
private static String makeProxyClassName(String packageName,
|
|
Class[] interfaces)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append(packageName).append("$Proxy");
|
|
int count = interfaces.length;
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
String name = interfaces[i].getName();
|
|
int pos = -1;
|
|
while ((pos = name.indexOf('$', pos + 1) + 1) > 0)
|
|
name = name.substring(0, pos) + "$" + name.substring(pos);
|
|
sb.append("$00");
|
|
int next;
|
|
while ((next = name.indexOf('.', pos)) >= 0)
|
|
{
|
|
sb.append(name.substring(pos, next)).append("$0");
|
|
pos = next + 1;
|
|
}
|
|
sb.append(name.substring(pos));
|
|
}
|
|
return sb.toString();
|
|
}
|
|
|
|
private static String ifacesToString(Class[] interfaces)
|
|
{
|
|
int count = interfaces.length;
|
|
if (count == 0)
|
|
return "<no interfaces>";
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append(interfaces[0].getName());
|
|
for (int i = 1; i < count; i++)
|
|
sb.append(", ").append(interfaces[i].getName());
|
|
return sb.toString();
|
|
}
|
|
}
|