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

org.python.core.PyJavaClass 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.core;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * A wrapper around a java class.
 */

public class PyJavaClass extends PyClass
{
    public PyReflectedConstructor __init__;

    public PackageManager __mgr__;

    private static InternalTables tbl;

    public synchronized final static InternalTables getInternalTables() {
        if(tbl == null)
          tbl = InternalTables.createInternalTables();
        return tbl;
    }

    public final boolean isLazy() {
        return proxyClass == null;
    }

    public static final PyJavaClass lookup(String name,PackageManager mgr) {
        if (tbl.queryCanonical(name)) {
            Class c = mgr.findClass(null,name,"forced java class");
            check_lazy_allowed(c); // xxx
            return lookup(c);
        }
        PyJavaClass ret = new PyJavaClass(name, mgr);
        tbl.putLazyCanonical(name, ret);
        return ret;
    }

    public synchronized static final PyJavaClass lookup(Class c) {
        if (tbl == null) {
            tbl = InternalTables.createInternalTables();
            PyJavaClass jc = new PyJavaClass(true);
            jc.init(PyJavaClass.class);
            tbl.putCanonical(PyJavaClass.class,jc);
        }
        PyJavaClass ret = tbl.getCanonical(c);
        if (ret != null)
            return ret;
        PyJavaClass lazy = tbl.getLazyCanonical(c.getName());
        if (lazy != null) {
            initLazy(lazy);
            if (lazy.proxyClass == c) return lazy;
        }

        Class parent = c.getDeclaringClass();
        if (parent == null)
            ret = new PyJavaClass(c);
        else
            ret = new PyJavaInnerClass(c, lookup(parent));
        tbl.putCanonical(c,ret);

        return ret;
    }

    private PyJavaClass(boolean fakeArg) {
        super(true);
    }

    protected PyJavaClass(Class c) {
        init(c);
    }

    protected PyJavaClass(String name,PackageManager mgr) {
        __name__ = name;
        this.__mgr__ = mgr;
    }

    protected void findModule(PyObject dict) {}

    protected Class getProxyClass() {
        initialize();
        return proxyClass;
    }

    // for the moment trying to lazily load a PyObject subclass
    // is not allowed, (because of the PyJavaClass vs PyType class mismatch)
    // pending PyJavaClass becoming likely a subclass of PyType
    private static final void check_lazy_allowed(Class c) {
        if (PyObject.class.isAssignableFrom(c)) { // xxx
            throw Py.TypeError("cannot lazy load PyObject subclass");
        }
    }

    private static final void initLazy(PyJavaClass jc) {
        Class c = jc.__mgr__.findClass(null,jc.__name__,"lazy java class");
        check_lazy_allowed(c); // xxx
        jc.init(c);
        tbl.putCanonical(jc.proxyClass,jc);
        jc.__mgr__ = null;
    }

    private boolean initialized=false;

    // Prevent recursive calls to initialize()
    private boolean initializing=false;

    private synchronized void initialize() {
        if (initialized || initializing)
            return;
        initializing = true;
        synchronized(PyJavaClass.class) {
            if (proxyClass == null) {
                initLazy(this);
            }
        }
        init__bases__(proxyClass);
        init__dict__();

        if (ClassDictInit.class.isAssignableFrom(proxyClass)
                            && proxyClass != ClassDictInit.class) {
            try {
                Method m = proxyClass.getMethod("classDictInit",
                     new Class[] { PyObject.class });
                m.invoke(null, new Object[] { __dict__ });
            }
            catch (Exception exc) {
                // System.err.println("Got exception: " + exc + " " +
                //                    proxyClass);
                throw Py.JavaError(exc);
            }
        }

        if (InitModule.class.isAssignableFrom(proxyClass)) {
            try {
                InitModule m = (InitModule)proxyClass.newInstance();
                m.initModule(__dict__);
            }
            catch (Exception exc) {
//                 System.err.println("Got exception: " + exc);
                throw Py.JavaError(exc);
            }
        }

        initialized = true;
        initializing = false;
    }

    private synchronized void init__dict__() {
        if (__dict__ != null)
            return;
        PyStringMap d = new PyStringMap();
//         d.__setitem__("__module__", Py.None);
        __dict__ = d;
        try {
            Method[] methods = getAccessibleMethods(proxyClass);
            setBeanInfoCustom(proxyClass, methods);
            setFields(proxyClass);
            setMethods(proxyClass, methods);
        } catch(SecurityException se) {}
    }
    
    private synchronized void init__class__(Class c) {
        /* xxx disable opt, will need similar opt for types
        if (!PyObject.class.isAssignableFrom(c))
            return;
        try {
            Field field = c.getField("__class__");
            if (Modifier.isStatic(field.getModifiers()) &&
                field.getType().isAssignableFrom(PyJavaClass.class) &&
                field.getDeclaringClass() == c)
            {
                field.set(null, this);
            }
        }
        catch (NoSuchFieldException exc) {}
        catch (IllegalAccessException exc1) {} */
    }

    private synchronized void init__bases__(Class c) {
        if (__bases__ != null) return;

        Class interfaces[] = getAccessibleInterfaces(c);
        int nInterfaces = interfaces.length;
        int nBases = 0;
        int i;
        for (i=0; i 7)
                    continue;
                PyObject prop = lookup(name, false);
                if (prop != null && prop instanceof PyBeanProperty) {
                    PyBeanProperty beanProp = ((PyBeanProperty)prop).copy();
                    beanProp.field = field;
                    __dict__.__setitem__(name, beanProp);
                    continue;
                }
            }
            __dict__.__setitem__(name, new PyReflectedField(field));
        }
    }

    /* Produce a good Python name for a Java method.  If the Java method
       ends in '$', strip it (this handles reserved Java keywords) Don't
       make any changes to keywords since this is now handled by parser
    */

    private String getName(String name) {
        if (name.endsWith("$")) name = name.substring(0, name.length()-1);
        return name.intern();
    }

    private void addMethod(Method meth) {
        String name = getName(meth.getName());
        if (name == "_getPyInstance" || name == "_setPyInstance" ||
            name == "_getPySystemState" || name == "_setPySystemState")
        {
            return;
        }

        // Special case to handle a few troublesome methods in java.awt.*.
        // These methods are all deprecated and interfere too badly with
        // bean properties to be tolerated.  This is totally a hack, but a
        // lot of code that uses java.awt will break without it.
        String classname = proxyClass.getName();
        if (classname.startsWith("java.awt.") &&
            classname.indexOf('.', 9) == -1)
        {
            if (name == "layout" || name == "insets" ||
                name == "size" || name == "minimumSize" ||
                name == "preferredSize" || name == "maximumSize" ||
                name == "bounds" || name == "enable")
            {
                return;
            }
        }

        // See if any of my superclasses are using 'name' for something
        // else.  Or if I'm already using it myself
        PyObject o = lookup(name, false);
        // If it's being used as a function, then things get more
        // interesting...
        PyReflectedFunction func;
        if (o != null && o instanceof PyReflectedFunction) {
            func = (PyReflectedFunction)o;

            PyObject o1 = __dict__.__finditem__(name);

            /* If this function already exists, add this method to the
               signature.  If this alters the signature of the function in
               some significant way, then return a duplicate and stick it in
               the __dict__ */
            if (o1 != o) {
                if (func.handles(meth)){
                    return;
                }
                func = func.copy();
            }
            func.addMethod(meth);
        } else {
            func = new PyReflectedFunction(meth);
            try {
                Field docField = proxyClass.getField("__doc__" + name);
                int mods = docField.getModifiers();
                if (docField.getType() == PyString.class &&
                       Modifier.isPublic(mods) &&
                       Modifier.isStatic(mods));
                    func.__doc__ = (PyString) docField.get(null);
            } catch (NoSuchFieldException ex) {
            } catch (SecurityException ex) {
            } catch (IllegalAccessException ex) {}
        }
        __dict__.__setitem__(name, func);
    }
    
     /**
      * Return the list of all accessible methods for a class.  This will
      * only the public methods unless Options.respectJavaAccessibility is
      * false, in which case all methods are returned.
      */
    private static Method[] getAccessibleMethods(Class c) {
        if (!JavaAccessibility.accessIsMutable())
            // returns just the public methods
            return c.getMethods();
        Method[] declared = c.getDeclaredMethods();
        for (int i=0; i < declared.length; i++) {
            // TBD: this is a permanent change.  Should we provide a way to
            // restore the original accessibility flag?
            JavaAccessibility.setAccessible(declared[i], true);
        }
        return declared;
    }

    private boolean ignoreMethod(Method method) {
        Class[] exceptions = method.getExceptionTypes();
        for (int j = 0; j < exceptions.length; j++) {
            if (exceptions[j] == PyIgnoreMethodTag.class) {
                return true;
            }
        }
        return false;
    }

    /* Add all methods declared by this class */
    private void setMethods(Class c, Method[] methods) {
        for (int i=0; i 1 && Character.isUpperCase(s.charAt(1)))
                return s;
            char[] cs = s.toCharArray();
            cs[0] = Character.toLowerCase(c0);
            return new String(cs);
        } else {
            return s;
        }
    }

    // This method is a workaround for Netscape's stupid security bug!
    private void setBeanInfoCustom(Class c, Method[] meths) {
        //try {
        int i;
        int n = meths.length;
        for (i=0; i 0)
                 eClass.getInterfaces()[0].getClassLoader();
            // And of Mac workaround

            if (!(java.util.EventListener.class.isAssignableFrom(eClass)))
                continue;

            String name = eClass.getName();
            int idot = name.lastIndexOf('.');
            if (idot != -1)
                name = decapitalize(name.substring(idot+1));

            addEvent(name, eClass, method, eClass.getMethods());
        }
        /*} catch (Throwable t) {
          System.err.println("Custom Bean error: "+t);
          t.printStackTrace();
          }*/
    }

     /**
      * Return the list of all accessible constructors for a class.  This
      * will only the public constructors unless
      * Options.respectJavaAccessibility is false, in which case all
      * constructors are returned.  Note that constructors are not
      * inherited like methods or fields.
      */
    private static Constructor[] getAccessibleConstructors(Class c) {
        if (!JavaAccessibility.accessIsMutable())
            // returns just the public fields
            return c.getConstructors();
        // return all constructors


        Constructor[] declared = c.getDeclaredConstructors();
        for (int i=0; i < declared.length; i++) {
            // TBD: this is a permanent change.  Should we provide a way to
            // restore the original accessibility flag?
            JavaAccessibility.setAccessible(declared[i], true);
        }
        return declared;
    }

    private boolean ignoreConstructor(Constructor method) {
        Class[] exceptions = method.getExceptionTypes();
        for (int j = 0; j < exceptions.length; j++) {
            if (exceptions[j] == PyIgnoreMethodTag.class) {
                return true;
            }
        }
        return false;
    }

    private void setConstructors(Class c) {
        if (Modifier.isInterface(c.getModifiers())) {
            __init__ = null;
        } else {
            Constructor[] constructors = getAccessibleConstructors(c);
            for (int i = 0; i < constructors.length; i++) {
                if (ignoreConstructor(constructors[i])) {
                    continue;
                }
                if (__init__ == null) {
                    __init__ = new PyReflectedConstructor(constructors[i]);
                } else {
                    __init__.addConstructor(constructors[i]);
                }
            }
            if (__init__ != null) {
                __dict__.__setitem__("__init__", __init__);
            }
        }
    }
    private boolean constructorsInitialized=false;
    synchronized void initConstructors() {
        if (constructorsInitialized)
            return;
        initialize();
        setConstructors(proxyClass);
        constructorsInitialized = true;
    }

    /*
      If the new name conflicts with a Python keyword, add an '_'
    */
    private static java.util.Hashtable keywords=null;
    private static String unmangleKeyword(String name) {
        if (keywords == null) {
            keywords = new java.util.Hashtable();
            String[] words = new String[]
            {"or", "and", "not", "is", "in", "lambda", "if", "else", "elif",
             "while", "for", "try", "except", "def", "class", "finally",
             "print",
             "pass", "break", "continue", "return", "import", "from", "del",
             "raise", "global", "exec", "assert"};
            for (int i=0; i";
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy