From: <cg...@us...> - 2007-10-08 01:56:12
|
Revision: 3577 http://jython.svn.sourceforge.net/jython/?rev=3577&view=rev Author: cgroves Date: 2007-10-07 18:56:03 -0700 (Sun, 07 Oct 2007) Log Message: ----------- Expose BytecodeLoader's existing Classloader for use by the new generation stuff, and hook @Exposed classes into PyType by generating their bytecode dynamically when they show up in addFromClass. Will need to add static generation of the bytecode eventually so we don't end up with our classic inability to run with secure class loading in place Modified Paths: -------------- branches/exposed_annotation/src/org/python/core/BytecodeLoader.java branches/exposed_annotation/src/org/python/core/PyType.java branches/exposed_annotation/src/org/python/expose/Exposer.java branches/exposed_annotation/src/org/python/expose/TypeExposer.java branches/exposed_annotation/tests/java/org/python/expose/MethodExposerTest.java branches/exposed_annotation/tests/java/org/python/expose/TypeExposerTest.java Removed Paths: ------------- branches/exposed_annotation/tests/java/org/python/expose/ByteLoader.java Modified: branches/exposed_annotation/src/org/python/core/BytecodeLoader.java =================================================================== --- branches/exposed_annotation/src/org/python/core/BytecodeLoader.java 2007-10-07 00:57:10 UTC (rev 3576) +++ branches/exposed_annotation/src/org/python/core/BytecodeLoader.java 2007-10-08 01:56:03 UTC (rev 3577) @@ -1,8 +1,9 @@ // Copyright (c) Corporation for National Research Initiatives - package org.python.core; import java.security.SecureClassLoader; +import java.util.ArrayList; +import java.util.List; import java.util.Vector; /** @@ -11,67 +12,57 @@ */ public class BytecodeLoader { - static Vector init() { - Vector parents = new Vector(); - parents.addElement(imp.getSyspathJavaLoader()); - return parents; - } - - static Class findParentClass(Vector parents, String name) - throws ClassNotFoundException { - for (int i = 0; i < parents.size(); i++) { + /** + * Turn the java byte code in data into a java class. + * + * @param name + * the name of the class + * @param data + * the java byte code. + * @param referents + * superclasses and interfaces that the new class will reference. + */ + public static Class makeClass(String name, byte[] data, Class... referents) { + Loader loader = new Loader(); + for(int i = 0; i < referents.length; i++) { try { - return ((ClassLoader) parents.elementAt(i)).loadClass(name); - } catch (ClassNotFoundException e) { - } + ClassLoader cur = referents[i].getClassLoader(); + if(cur != null) { + loader.addParent(cur); + } + } catch(SecurityException e) {} } - // couldn't find the .class file on sys.path - throw new ClassNotFoundException(name); + return loader.loadClassFromBytes(name, data); } - static void compileClass (Class c) { - Compiler.compileClass(c); - } - - private static Loader makeLoader() { - return new Loader(); - } - /** * Turn the java byte code in data into a java class. * - * @param name the name of the class - * @param referents a list of superclass and interfaces that the new class - * will reference. - * @param data the java byte code. + * @param name + * the name of the class + * @param referents + * superclasses and interfaces that the new class will reference. + * @param data + * the java byte code. */ - public static Class makeClass(String name, Vector referents, byte[] data) { - Loader loader = makeLoader(); - - if (referents != null) { - for (int i = 0; i < referents.size(); i++) { - try { - Class cls = (Class) referents.elementAt(i); - ClassLoader cur = cls.getClassLoader(); - if (cur != null) { - loader.addParent(cur); - } - } catch (SecurityException e) { - } - } + public static Class makeClass(String name, Vector<Class> referents, byte[] data) { + if(referents != null) { + return makeClass(name, data, referents.toArray(new Class[0])); } - return loader.loadClassFromBytes(name, data); + return makeClass(name, data); } /** * Turn the java byte code for a compiled python module into a java class. * - * @param name the name of the class - * @param data the java byte code. + * @param name + * the name of the class + * @param data + * the java byte code. */ public static PyCode makeCode(String name, byte[] data, String filename) { try { - Class c = makeClass(name, null, data); + Class c = makeClass(name, data); Object o = c.getConstructor(new Class[] {String.class}) .newInstance(new Object[] {filename}); return ((PyRunnable)o).getMain(); @@ -79,35 +70,25 @@ throw Py.JavaError(e); } } - - private static class Loader extends SecureClassLoader { - private Vector parents; + public static class Loader extends SecureClassLoader { + + private List<ClassLoader> parents = new ArrayList<ClassLoader>(); + public Loader() { - this.parents = BytecodeLoader.init(); + parents.add(imp.getSyspathJavaLoader()); } public void addParent(ClassLoader referent) { - if (!this.parents.contains(referent)) { - this.parents.add(0, referent); + if(!parents.contains(referent)) { + parents.add(0, referent); } } - // override from abstract base class - protected Class loadClass(String name, boolean resolve) - throws ClassNotFoundException { - Class c = findLoadedClass(name); - if (c != null) { - return c; - } - return BytecodeLoader.findParentClass(this.parents, name); - } - public Class loadClassFromBytes(String name, byte[] data) { - Class c = defineClass(name, data, 0, data.length, this.getClass() - .getProtectionDomain()); + Class c = defineClass(name, data, 0, data.length, getClass().getProtectionDomain()); resolveClass(c); - BytecodeLoader.compileClass(c); + Compiler.compileClass(c); return c; } } Modified: branches/exposed_annotation/src/org/python/core/PyType.java =================================================================== --- branches/exposed_annotation/src/org/python/core/PyType.java 2007-10-07 00:57:10 UTC (rev 3576) +++ branches/exposed_annotation/src/org/python/core/PyType.java 2007-10-08 01:56:03 UTC (rev 3577) @@ -10,6 +10,10 @@ import java.util.Iterator; import java.util.List; +import org.python.expose.Exposed; +import org.python.expose.TypeBuilder; +import org.python.expose.TypeExposer; + /** * first-class Python type. * @@ -915,12 +919,9 @@ return null; } - private static Method get_descr_method( - Class c, - String name, - Class[] parmtypes) { + private static Method get_descr_method(Class c, String name, Class[] parmtypes) { Method meth = get_non_static_method(c, name, parmtypes); - if (meth != null && meth.getDeclaringClass() != PyObject.class) { + if(meth != null && meth.getDeclaringClass() != PyObject.class) { return meth; } return null; @@ -945,7 +946,8 @@ Class base, boolean newstyle, Method setup, - String[] exposed_methods) { + String[] exposed_methods, + TypeBuilder tb) { if(base == null) { base = c.getSuperclass(); @@ -966,7 +968,7 @@ newtype.builtin = true; boolean top = false; // basic mro, base, bases - PyType[] mro = null; + PyType[] mro; if(base == Object.class) { mro = new PyType[] {newtype}; top = true; @@ -979,12 +981,20 @@ newtype.bases = new PyObject[] {basetype}; } newtype.mro = mro; - PyObject dict = new PyStringMap(); - if(newstyle) { - fillInNewstyle(newtype, setup, exposed_methods, dict); + PyObject dict; + if(tb != null) { + dict = tb.getDict(); } else { - fillInClassic(c, base, dict); + dict = new PyStringMap(); + if(newstyle) { + fillInNewstyle(newtype, setup, exposed_methods, dict); + } else { + fillInClassic(c, base, dict); + } } + if(newstyle) { + newtype.non_instantiable = dict.__finditem__("__new__") == null; + } boolean has_set = false, has_delete = false; if(!top) { if(get_descr_method(c, "__set__", OO) != null || /* backw comp */ @@ -1151,10 +1161,10 @@ try { setup.invoke(null, new Object[] {dict, null}); } catch(Exception e) { + e.printStackTrace(); throw error(e); } } - newtype.non_instantiable = dict.__finditem__("__new__") == null; } private static HashMap class_to_type; @@ -1168,40 +1178,45 @@ Class base = null; String name = null; String[] exposed_methods = null; - try { - setup = - c.getDeclaredMethod( - "typeSetup", - new Class[] { PyObject.class, Newstyle.class }); + TypeBuilder tb = null; + if(c.getAnnotation(Exposed.class) != null) { + tb = new TypeExposer(c).makeBuilder(); + name = tb.getName(); + base = PyObject.class; newstyle = true; - } catch (NoSuchMethodException e) { - } catch (Exception e) { - throw error(e); - } - if(newstyle) { // newstyle - base = (Class)exposed_decl_get_object(c, "base"); - name = (String)exposed_decl_get_object(c, "name"); - if(base == null) { - Class cur = c; - while(cur != PyObject.class) { - Class exposed_as = (Class)exposed_decl_get_object(cur, "as"); - if(exposed_as != null) { - PyType exposed_as_type = fromClass(exposed_as); - class_to_type.put(c, exposed_as_type); - return exposed_as_type; + } else { + try { + setup = c.getDeclaredMethod("typeSetup", new Class[] {PyObject.class, + Newstyle.class}); + newstyle = true; + } catch(NoSuchMethodException e) {} catch(Exception e) { + throw error(e); + } + if(newstyle) { // newstyle + base = (Class)exposed_decl_get_object(c, "base"); + name = (String)exposed_decl_get_object(c, "name"); + if(base == null) { + Class cur = c; + while(cur != PyObject.class) { + Class exposed_as = (Class)exposed_decl_get_object(cur, "as"); + if(exposed_as != null) { + PyType exposed_as_type = fromClass(exposed_as); + class_to_type.put(c, exposed_as_type); + return exposed_as_type; + } + cur = cur.getSuperclass(); } - cur = cur.getSuperclass(); } + exposed_methods = (String[])exposed_decl_get_object(c, "methods"); + if(exposed_methods == null) + exposed_methods = EMPTY; } - exposed_methods = (String[]) exposed_decl_get_object(c, "methods"); - if (exposed_methods == null) - exposed_methods = EMPTY; } PyType newtype = (PyType)class_to_type.get(c); if (newtype == null) { newtype = c == PyType.class ? new PyType(true) : new PyType(); class_to_type.put(c, newtype); - fillFromClass(newtype, name, c, base, newstyle, setup, exposed_methods); + fillFromClass(newtype, name, c, base, newstyle, setup, exposed_methods, tb); } return newtype; } Modified: branches/exposed_annotation/src/org/python/expose/Exposer.java =================================================================== --- branches/exposed_annotation/src/org/python/expose/Exposer.java 2007-10-07 00:57:10 UTC (rev 3576) +++ branches/exposed_annotation/src/org/python/expose/Exposer.java 2007-10-08 01:56:03 UTC (rev 3577) @@ -1,9 +1,12 @@ package org.python.expose; import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; import org.objectweb.asm.MethodVisitor; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; +import org.objectweb.asm.util.CheckClassAdapter; +import org.python.core.BytecodeLoader; import org.python.core.Py; import org.python.core.PyBuiltinFunction; import org.python.core.PyBuiltinMethod; @@ -34,6 +37,15 @@ * class. cv is set to the ClassVisitor to be used when this is called. */ protected abstract void generate(); + + /** + * Generates this Exposer and loads it into the given Loader. + */ + protected Class load(BytecodeLoader.Loader l) { + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + generate(new CheckClassAdapter(cw)); + return l.loadClassFromBytes(getClassName(), cw.toByteArray()); + } protected Type getGeneratedType() { return thisType; Modified: branches/exposed_annotation/src/org/python/expose/TypeExposer.java =================================================================== --- branches/exposed_annotation/src/org/python/expose/TypeExposer.java 2007-10-07 00:57:10 UTC (rev 3576) +++ branches/exposed_annotation/src/org/python/expose/TypeExposer.java 2007-10-08 01:56:03 UTC (rev 3577) @@ -5,6 +5,7 @@ import java.util.List; import org.objectweb.asm.Type; +import org.python.core.BytecodeLoader; import org.python.core.PyBuiltinFunction; import org.python.core.PyMethodDescr; import org.python.core.PyObject; @@ -17,7 +18,7 @@ public class TypeExposer extends Exposer { public TypeExposer(Class<?> cls) { - super(BaseTypeBuilder.class, cls.getName() + "$PyExposer"); + super(BaseTypeBuilder.class, getExposedName(cls)); this.cls = cls; exp = cls.getAnnotation(Exposed.class); if(exp == null) { @@ -25,7 +26,30 @@ } } + public TypeBuilder makeBuilder() { + BytecodeLoader.Loader l = new BytecodeLoader.Loader(); + for(Method m : findMethods()) { + new MethodExposer(m).load(l); + } + Class descriptor = load(l); + try { + return (TypeBuilder)descriptor.newInstance(); + } catch(Exception e) { + // If we're unable to create the generated class, the process is + // definitely ill, but that shouldn't be the case most of the time + // so make this a runtime exception + throw new RuntimeException("Unable to create generated builder", e); + } + } + /** + * @return - the name of the class that would be generated to expose cls. + */ + public static String getExposedName(Class cls) { + return cls.getName() + "$PyExposer"; + } + + /** * @return - the methods on the exposed class that should be exposed. */ public List<Method> findMethods() { @@ -74,13 +98,15 @@ public BaseTypeBuilder(String name, Class typeClass, PyBuiltinFunction[] funcs) { this.typeClass = typeClass; this.name = name; + this.funcs = funcs; + } + + public PyObject getDict() { + PyObject dict = new PyStringMap(); for(PyBuiltinFunction func : funcs) { PyMethodDescr pmd = new PyMethodDescr(typeClass, func); dict.__setitem__(pmd.getName(), pmd); } - } - - public PyObject getDict() { return dict; } @@ -91,12 +117,12 @@ public Class getTypeClass() { return typeClass; } + + private PyBuiltinFunction[] funcs; private Class typeClass; private String name; - - private PyStringMap dict = new PyStringMap(); } private Exposed exp; Deleted: branches/exposed_annotation/tests/java/org/python/expose/ByteLoader.java =================================================================== --- branches/exposed_annotation/tests/java/org/python/expose/ByteLoader.java 2007-10-07 00:57:10 UTC (rev 3576) +++ branches/exposed_annotation/tests/java/org/python/expose/ByteLoader.java 2007-10-08 01:56:03 UTC (rev 3577) @@ -1,10 +0,0 @@ -package org.python.expose; - -public class ByteLoader extends ClassLoader { - - public Class loadClassFromBytes(String name, byte[] data) { - Class c = defineClass(name, data, 0, data.length, this.getClass().getProtectionDomain()); - resolveClass(c); - return c; - } -} Modified: branches/exposed_annotation/tests/java/org/python/expose/MethodExposerTest.java =================================================================== --- branches/exposed_annotation/tests/java/org/python/expose/MethodExposerTest.java 2007-10-07 00:57:10 UTC (rev 3576) +++ branches/exposed_annotation/tests/java/org/python/expose/MethodExposerTest.java 2007-10-08 01:56:03 UTC (rev 3577) @@ -1,12 +1,8 @@ package org.python.expose; -import java.io.PrintWriter; - import junit.framework.TestCase; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.util.CheckClassAdapter; -import org.objectweb.asm.util.TraceClassVisitor; +import org.python.core.BytecodeLoader; import org.python.core.Py; import org.python.core.PyBuiltinFunction; import org.python.core.PyBuiltinMethod; @@ -23,11 +19,7 @@ assertEquals(SimpleExposed.class, mp.getMethodClass()); assertEquals("org/python/expose/SimpleExposed$exposed_simple_method", mp.getInternalName()); assertEquals("org.python.expose.SimpleExposed$exposed_simple_method", mp.getClassName()); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - TraceClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), - new PrintWriter(System.out)); - mp.generate(cv); - Class descriptor = new ByteLoader().loadClassFromBytes(mp.getClassName(), cw.toByteArray()); + Class descriptor = mp.load(new BytecodeLoader.Loader()); PyBuiltinMethod instance = (PyBuiltinMethod)descriptor.newInstance(); assertSame("simple_method", instance.__getattr__("__name__").toString()); SimpleExposed simpleExposed = new SimpleExposed(); Modified: branches/exposed_annotation/tests/java/org/python/expose/TypeExposerTest.java =================================================================== --- branches/exposed_annotation/tests/java/org/python/expose/TypeExposerTest.java 2007-10-07 00:57:10 UTC (rev 3576) +++ branches/exposed_annotation/tests/java/org/python/expose/TypeExposerTest.java 2007-10-08 01:56:03 UTC (rev 3577) @@ -37,21 +37,8 @@ } catch(IllegalArgumentException iae) {} } - public void testGenerate() throws InstantiationException, IllegalAccessException { - ByteLoader l = new ByteLoader(); - TypeExposer ecp = new TypeExposer(SimpleExposed.class); - for(Method m : ecp.findMethods()) { - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - MethodExposer mp = new MethodExposer(m); - mp.generate(cw); - l.loadClassFromBytes(mp.getClassName(), cw.toByteArray()); - } - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - TraceClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), - new PrintWriter(System.out)); - ecp.generate(cv); - Class descriptor = l.loadClassFromBytes(ecp.getClassName(), cw.toByteArray()); - TypeBuilder t = (TypeBuilder)descriptor.newInstance(); + public void testMakeBuilder() throws InstantiationException, IllegalAccessException { + TypeBuilder t = new TypeExposer(SimpleExposed.class).makeBuilder(); assertEquals("SimpleExposed", t.getName()); assertEquals(SimpleExposed.class, t.getTypeClass()); assertNotNull(t.getDict().__finditem__("simple_method")); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |