org.python.compiler.ProxyMaker Maven / Gradle / Ivy
Go to download
Jython is an implementation of the high-level, dynamic, object-oriented
language Python written in 100% Pure Java, and seamlessly integrated with
the Java platform. It thus allows you to run Python on any Java platform.
// Copyright (c) Corporation for National Research Initiatives
package org.python.compiler;
import java.util.Hashtable;
import java.util.Enumeration;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Constructor;
import java.io.*;
import org.python.core.Py;
public class ProxyMaker implements ClassConstants
{
public static final int tBoolean=0;
public static final int tByte=1;
public static final int tShort=2;
public static final int tInteger=3;
public static final int tLong=4;
public static final int tFloat=5;
public static final int tDouble=6;
public static final int tCharacter=7;
public static final int tVoid=8;
public static final int tOther=9;
public static final int tNone=10;
public static Hashtable types=fillTypes();
public static Hashtable fillTypes() {
Hashtable types = new Hashtable();
types.put(Boolean.TYPE, new Integer(tBoolean));
types.put(Byte.TYPE, new Integer(tByte));
types.put(Short.TYPE, new Integer(tShort));
types.put(Integer.TYPE, new Integer(tInteger));
types.put(Long.TYPE, new Integer(tLong));
types.put(Float.TYPE, new Integer(tFloat));
types.put(Double.TYPE, new Integer(tDouble));
types.put(Character.TYPE, new Integer(tCharacter));
types.put(Void.TYPE, new Integer(tVoid));
return types;
}
public static int getType(Class c) {
if (c == null) return tNone;
Object i = types.get(c);
if (i == null) return tOther;
else return ((Integer)i).intValue();
}
Class superclass;
Class[] interfaces;
Hashtable names;
Hashtable supernames = new Hashtable();
public ClassFile classfile;
public String myClass;
public boolean isAdapter=false;
// Ctor used by makeProxy and AdapterMaker.
public ProxyMaker(String classname, Class superclass) {
this.myClass = "org.python.proxies."+classname;
if (superclass.isInterface()) {
this.superclass = Object.class;
this.interfaces = new Class[] {superclass};
} else {
this.superclass = superclass;
this.interfaces = new Class[0];
}
}
// Ctor used by javamaker.
public ProxyMaker(String myClass, Class superclass, Class[] interfaces) {
this.myClass = myClass;
if (superclass == null)
superclass = Object.class;
this.superclass = superclass;
if (interfaces == null)
interfaces = new Class[0];
this.interfaces = interfaces;
}
public static String mapClass(Class c) {
String name = c.getName();
int index = name.indexOf(".");
if (index == -1)
return name;
StringBuffer buf = new StringBuffer(name.length());
int last_index = 0;
while (index != -1) {
buf.append(name.substring(last_index, index));
buf.append("/");
last_index = index+1;
index = name.indexOf(".", last_index);
}
buf.append(name.substring(last_index, name.length()));
return buf.toString();
}
public static String mapType(Class type) {
if (type.isArray())
return "["+mapType(type.getComponentType());
switch (getType(type)) {
case tByte: return "B";
case tCharacter: return "C";
case tDouble: return "D";
case tFloat: return "F";
case tInteger: return "I";
case tLong: return "J";
case tShort: return "S";
case tBoolean: return "Z";
case tVoid: return "V";
default:
return "L"+mapClass(type)+";";
}
}
public static String makeSignature(Class[] sig, Class ret) {
StringBuffer buf=new StringBuffer();
buf.append("(");
for (int i=0; i", "()V", Modifier.STATIC);
code.return_();
}
public static void doReturn(Code code, Class type) throws Exception {
switch (getType(type)) {
case tNone:
break;
case tCharacter:
case tBoolean:
case tByte:
case tShort:
case tInteger:
code.ireturn();
break;
case tLong:
code.lreturn();
break;
case tFloat:
code.freturn();
break;
case tDouble:
code.dreturn();
break;
case tVoid:
code.return_();
break;
default:
code.areturn();
break;
}
}
public static void doNullReturn(Code code, Class type) throws Exception {
switch (getType(type)) {
case tNone:
break;
case tCharacter:
case tBoolean:
case tByte:
case tShort:
case tInteger:
code.iconst(0);
code.ireturn();
break;
case tLong:
code.ldc(code.pool.Long(0));
code.lreturn();
break;
case tFloat:
code.ldc(code.pool.Float((float)0.));
code.freturn();
break;
case tDouble:
code.ldc(code.pool.Double(0.));
code.dreturn();
break;
case tVoid:
code.return_();
break;
default:
code.aconst_null();
code.areturn();
break;
}
}
public void callSuper(Code code, String name, String superclass,
Class[] parameters, Class ret,
String sig)
throws Exception
{
code.aload(0);
int local_index;
int i;
for (i=0, local_index=1; i 0) {
start = code.getLabel();
end = code.getLabel();
jcallName = "_jcallexc";
instLocal = code.getLocal("org/python/core/PyObject");
code.astore(instLocal);
start.setPosition();
code.aload(instLocal);
}
getArgs(code, parameters);
switch (getType(ret)) {
case tCharacter:
doJavaCall(code, "char", "C", jcallName);
break;
case tBoolean:
doJavaCall(code, "boolean", "Z", jcallName);
break;
case tByte:
case tShort:
case tInteger:
doJavaCall(code, "int", "I", jcallName);
break;
case tLong:
doJavaCall(code, "long", "J", jcallName);
break;
case tFloat:
doJavaCall(code, "float", "F", jcallName);
break;
case tDouble:
doJavaCall(code, "double", "D", jcallName);
break;
case tVoid:
doJavaCall(code, "void", "V", jcallName);
break;
default:
int jcall = code.pool.Methodref(
"org/python/core/PyObject", jcallName,
"(" + $objArr + ")" + $pyObj);
code.invokevirtual(jcall);
/* catching exceptions is not vm mandatory
Label forname_start =code.getLabel();
Label forname_end = code.getLabel();
Label forname_exch_start = code.getLabel();
Label forname_exch_end = code.getLabel();
forname_start.setPosition();
*/
int forname = code.pool.Methodref(
"java/lang/Class","forName",
"(" + $str + ")" + $clss);
code.ldc(ret.getName());
code.invokestatic(forname);
/*
forname_end.setPosition();
code.goto_(forname_exch_end);
forname_exch_start.setPosition();
code.stack = 1;
// never reached, but this code keeps the verifier happy
code.pop();
code.aconst_null();
code.dup();
forname_exch_end.setPosition();
code.addExceptionHandler(forname_start,forname_end,
forname_exch_start,
code.pool.Class("java/lang/ClassNotFoundException"));
*/
int tojava = code.pool.Methodref(
"org/python/core/Py", "tojava",
"(" + $pyObj + $clss + ")" + $obj);
code.invokestatic(tojava);
// I guess I need this checkcast to keep the verifier happy
code.checkcast(code.pool.Class(mapClass(ret)));
break;
}
if (exceptions.length > 0)
end.setPosition();
doReturn(code, ret);
if (exceptions.length > 0) {
boolean throwableFound = false;
Label handlerStart = null;
for (int i = 0; i < exceptions.length; i++) {
handlerStart = code.getLabel();
handlerStart.setPosition();
code.stack = 1;
int excLocal = code.getLocal("java/lang/Throwable");
code.astore(excLocal);
code.aload(excLocal);
code.athrow();
code.addExceptionHandler(start, end, handlerStart,
code.pool.Class(mapClass(exceptions[i])));
doNullReturn(code, ret);
code.freeLocal(excLocal);
if (exceptions[i] == Throwable.class)
throwableFound = true;
}
if (!throwableFound) {
// The final catch (Throwable)
handlerStart = code.getLabel();
handlerStart.setPosition();
code.stack = 1;
int excLocal = code.getLocal("java/lang/Throwable");
code.astore(excLocal);
code.aload(instLocal);
code.aload(excLocal);
int jthrow = code.pool.Methodref(
"org/python/core/PyObject", "_jthrow",
"(" + $throwable + ")V");
code.invokevirtual(jthrow);
code.addExceptionHandler(start, end, handlerStart,
code.pool.Class("java/lang/Throwable"));
code.freeLocal(excLocal);
doNullReturn(code, ret);
}
code.freeLocal(instLocal);
}
}
public void addMethod(Method method, int access) throws Exception {
boolean isAbstract = false;
if (Modifier.isAbstract(access)) {
access = access & ~Modifier.ABSTRACT;
isAbstract = true;
}
Class[] parameters = method.getParameterTypes();
Class ret = method.getReturnType();
String sig = makeSignature(parameters, ret);
String name = method.getName();
// System.out.println(name+": "+sig);
names.put(name, name);
Code code = classfile.addMethod(name, sig, access);
code.aload(0);
code.ldc(name);
if (!isAbstract) {
int tmp = code.getLocal("org/python/core/PyObject");
int jfindattr = code.pool.Methodref(
"org/python/core/Py",
"jfindattr",
"(" + $pyProxy + $str + ")" + $pyObj);
code.invokestatic(jfindattr);
code.astore(tmp);
code.aload(tmp);
Label callPython = code.getLabel();
code.ifnonnull(callPython);
String superclass = mapClass(method.getDeclaringClass());
callSuper(code, name, superclass, parameters, ret, sig);
callPython.setPosition();
code.aload(tmp);
callMethod(code, name, parameters, ret,
method.getExceptionTypes());
addSuperMethod("super__"+name, name, superclass, parameters,
ret, sig, access);
}
else {
if (!isAdapter) {
int jgetattr = code.pool.Methodref(
"org/python/core/Py",
"jgetattr",
"(" + $pyProxy + $str + ")" + $pyObj);
code.invokestatic(jgetattr);
callMethod(code, name, parameters, ret,
method.getExceptionTypes());
}
else {
int jfindattr = code.pool.Methodref(
"org/python/core/Py",
"jfindattr",
"(" + $pyProxy + $str + ")" + $pyObj);
code.invokestatic(jfindattr);
code.dup();
Label returnNull = code.getLabel();
code.ifnull(returnNull);
callMethod(code, name, parameters, ret,
method.getExceptionTypes());
returnNull.setPosition();
code.pop();
doNullReturn(code, ret);
}
}
}
private String methodString(Method m) {
StringBuffer buf = new StringBuffer(m.getName());
buf.append(":");
Class[] params = m.getParameterTypes();
for (int i=0; i", sig, access);
callSuper(code, "", name, parameters, Void.TYPE, sig);
}
public void addConstructors(Class c) throws Exception {
Constructor[] constructors = c.getDeclaredConstructors();
String name = mapClass(c);
for (int i=0; i