All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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.

There is a newer version: 2.7.4
Show newest version
// 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




© 2015 - 2024 Weber Informatics LLC | Privacy Policy