From: <cg...@us...> - 2008-12-29 23:59:05
|
Revision: 5812 http://jython.svn.sourceforge.net/jython/?rev=5812&view=rev Author: cgroves Date: 2008-12-29 23:59:02 +0000 (Mon, 29 Dec 2008) Log Message: ----------- Try the current thread's context class loader instead of using Class.forName. Fixes issue1216. The implementation differs from the patch in that it tries SyspathJavaLoader before going to the context class loader so java classes can still be found on sys.path. Modified Paths: -------------- trunk/jython/Lib/test/test_java_integration.py trunk/jython/src/org/python/compiler/ProxyMaker.java trunk/jython/src/org/python/compiler/ScopeInfo.java trunk/jython/src/org/python/core/Py.java trunk/jython/src/org/python/core/SyspathJavaLoader.java Modified: trunk/jython/Lib/test/test_java_integration.py =================================================================== --- trunk/jython/Lib/test/test_java_integration.py 2008-12-29 23:56:48 UTC (rev 5811) +++ trunk/jython/Lib/test/test_java_integration.py 2008-12-29 23:59:02 UTC (rev 5812) @@ -8,8 +8,8 @@ from java.util import ArrayList, HashMap, Hashtable, StringTokenizer, Vector from java.io import FileOutputStream, FileWriter, OutputStreamWriter -from java.lang import (Boolean, ExceptionInInitializerError, Integer, Object, String, Runnable, - Thread, ThreadGroup, System, Runtime, Math, Byte) +from java.lang import (Boolean, ClassLoader, ExceptionInInitializerError, Integer, Object, String, + Runnable, Thread, ThreadGroup, System, Runtime, Math, Byte) from javax.swing.table import AbstractTableModel from javax.swing.tree import TreePath from java.math import BigDecimal @@ -55,6 +55,49 @@ pass A() +""" +public abstract class ContextAbstract { + public ContextAbstract() { + method(); + } + + public abstract void method(); +} +""" +# The following is the correspoding bytecode for ContextAbstract compiled with javac 1.5 +# Needs to be named differently than Abstract above so the class loader won't just use it +CONTEXT_ABSTRACT = '''\ +eJxdjr1uwjAUhc8lbgIh/AVegA0YQJ1BlRBSp6gdWrE7wQKjEEvBVH0tFip14AF4KMQ17YSHc3yu +vuPry/X3DOAZ3RACrRAe2gE6AWKCP9OFti8EbzBcEsTCrBShlehCvR12qSo/ZZrzJE5MJvOlLLXL +/0NhN3pP6CQLU1j1befp3pYys1N+d6fsxqwI4Yc5lJl61a7QewDHW/klIzzBjxDB58UPAKHtkEku +i/XkPd2qzIo+/1/AnQrIdVkDTlN2Yq+NfkCjEyrHO1JlbXLF3QV7lbXGKfqDEaIOCHL7ORMad7J5 +A7yvPDQ= +'''.decode('base64').decode('zlib') +class ContextClassloaderTest(unittest.TestCase): + '''Classes on the context classloader should be importable and subclassable. + + http://bugs.jython.org/issue1216''' + def setUp(self): + self.orig_context = Thread.currentThread().contextClassLoader + class AbstractLoader(ClassLoader): + def __init__(self): + ClassLoader.__init__(self) + c = self.super__defineClass("ContextAbstract", CONTEXT_ABSTRACT, 0, + len(CONTEXT_ABSTRACT), ClassLoader.protectionDomain) + self.super__resolveClass(c) + Thread.currentThread().contextClassLoader = AbstractLoader() + + def tearDown(self): + Thread.currentThread().contextClassLoader = self.orig_context + + def test_can_subclass_abstract(self): + import ContextAbstract + + class A(ContextAbstract): + def method(self): + pass + A() + class InstantiationTest(unittest.TestCase): def test_can_subclass_abstract(self): class A(Component): @@ -470,6 +513,7 @@ def test_main(): test_support.run_unittest(AbstractOnSyspathTest, + ContextClassloaderTest, InstantiationTest, BeanTest, ExtendJavaTest, Modified: trunk/jython/src/org/python/compiler/ProxyMaker.java =================================================================== --- trunk/jython/src/org/python/compiler/ProxyMaker.java 2008-12-29 23:56:48 UTC (rev 5811) +++ trunk/jython/src/org/python/compiler/ProxyMaker.java 2008-12-29 23:59:02 UTC (rev 5812) @@ -670,7 +670,7 @@ } public void addClassDictInit() throws Exception { - int n = supernames.size(); + supernames.size(); // classDictInit method classfile.addInterface(mapClass(org.python.core.ClassDictInit.class)); Modified: trunk/jython/src/org/python/compiler/ScopeInfo.java =================================================================== --- trunk/jython/src/org/python/compiler/ScopeInfo.java 2008-12-29 23:56:48 UTC (rev 5811) +++ trunk/jython/src/org/python/compiler/ScopeInfo.java 2008-12-29 23:59:02 UTC (rev 5812) @@ -125,7 +125,7 @@ public int jy_npurecell; public int cell, distance; - + public ScopeInfo up; //Resolve the names used in the given scope, and mark any freevars used in the up scope @@ -188,7 +188,7 @@ names.addElement(purecells.elementAt(i)); } } - + if (some_free && nested) { up.contains_ns_free_vars = true; } @@ -202,23 +202,25 @@ } - private void dynastuff_trouble(boolean inner_free, - CompilationContext ctxt) throws Exception { - String illegal; - if (unqual_exec && from_import_star) - illegal = "function '"+scope_name+ - "' uses import * and bare exec, which are illegal"; - else if (unqual_exec) - illegal = "unqualified exec is not allowed in function '"+ - scope_name+"'"; - else - illegal = "import * is not allowed in function '"+scope_name+"'"; - String why; - if (inner_free) - why = " because it contains a function with free variables"; - else - why = " because it contains free variables"; - ctxt.error(illegal + why, true, scope_node); + private void dynastuff_trouble(boolean inner_free, CompilationContext ctxt) throws Exception { + StringBuilder illegal = new StringBuilder(); + if (unqual_exec && from_import_star) { + illegal.append("function '") + .append(scope_name) + .append("' uses import * and bare exec, which are illegal"); + } else if (unqual_exec) { + illegal.append("unqualified exec is not allowed in function '") + .append(scope_name) + .append("'"); + } else { + illegal.append("import * is not allowed in function '").append(scope_name).append("'"); + } + if (inner_free) { + illegal.append(" because it contains a function with free variables"); + } else { + illegal.append(" because it contains free variables"); + } + ctxt.error(illegal.toString(), true, scope_node); } public Vector freevars = new Vector(); @@ -230,7 +232,7 @@ public void setup_closure() { setup_closure(up); } - + /** * setup the closure on this scope using the passed in scope. This is used * by jythonc to setup its closures. Modified: trunk/jython/src/org/python/core/Py.java =================================================================== --- trunk/jython/src/org/python/core/Py.java 2008-12-29 23:56:48 UTC (rev 5811) +++ trunk/jython/src/org/python/core/Py.java 2008-12-29 23:59:02 UTC (rev 5812) @@ -761,11 +761,15 @@ secEnv = true; } if (classLoader != null) { - return classLoader.loadClass(name); + try { + return classLoader.loadClass(name); + } catch (ClassNotFoundException cnfe) { + // let the context classloader try + } } } - return Class.forName(name); + return Thread.currentThread().getContextClassLoader().loadClass(name); } catch (ClassNotFoundException e) { // e.printStackTrace(); @@ -797,13 +801,17 @@ if (classLoader != null) { writeDebug("import", "trying " + name + " as " + reason + " in syspath loader"); - return classLoader.loadClass(name); + try { + return classLoader.loadClass(name); + } catch (ClassNotFoundException cnfe) { + // let the context classloader try + } } } writeDebug("import", "trying " + name + " as " + reason + " in Class.forName"); - return Class.forName(name); + return Thread.currentThread().getContextClassLoader().loadClass(name); } catch (ClassNotFoundException e) { return null; } catch (IllegalArgumentException e) { Modified: trunk/jython/src/org/python/core/SyspathJavaLoader.java =================================================================== --- trunk/jython/src/org/python/core/SyspathJavaLoader.java 2008-12-29 23:56:48 UTC (rev 5811) +++ trunk/jython/src/org/python/core/SyspathJavaLoader.java 2008-12-29 23:59:02 UTC (rev 5812) @@ -17,7 +17,7 @@ public class SyspathJavaLoader extends ClassLoader { private static final char SLASH_CHAR = '/'; - + public InputStream getResourceAsStream(String res) { Py.writeDebug("resource", "trying resource: " + res); PySystemState sys = Py.getSystemState(); @@ -26,7 +26,7 @@ return classLoader.getResourceAsStream(res); } - classLoader = this.getClass().getClassLoader(); + classLoader = Thread.currentThread().getContextClassLoader(); InputStream ret; @@ -47,7 +47,7 @@ res = res.replace(SLASH_CHAR, File.separatorChar); entryRes = entryRes.replace(File.separatorChar, SLASH_CHAR); } - + PyList path = sys.path; for (int i = 0; i < path.__len__(); i++) { PyObject entry = path.__getitem__(i); @@ -85,23 +85,23 @@ if (classLoader != null) { return classLoader.loadClass(name); } - + // Search the sys.path for a .class file matching the named class. try { return Class.forName(name); } catch(ClassNotFoundException e) {} - + // The current class loader may be null (e.g., when Jython is loaded // from the boot classpath); try the system class loader. try { return Class.forName(name, true, ClassLoader.getSystemClassLoader()); } catch(ClassNotFoundException e) {} - + Class c = findLoadedClass(name); if(c != null) { return c; } - + PyList path = sys.path; for(int i = 0; i < path.__len__(); i++) { InputStream fis = null; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |