Skip to content

Commit b6cdb3b

Browse files
committed
Respect the cachedir setting for scanning packages when adding a jar to
sys.path, and if it does need to be scanned, cache the results. Use Py.findClass rather than the context classloader to lookup classes in JavaImportHelper. This makes classes in jars on sys.path and the current PySystemState classloader available without package scanning in addition to those in the context classloader.
1 parent 6b0b1f6 commit b6cdb3b

10 files changed

Lines changed: 83 additions & 60 deletions

File tree

bugtests/jarmaker.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import support
2+
import sys
3+
import os
4+
5+
from java.io import File
6+
7+
package = "javapackage"
8+
clazz = "JavaClass"
9+
jardir = "simplejar"
10+
jarfn = "simple.jar"
11+
clazzfile = File(jardir + '/'+ package, "%s.class" % clazz) # java.io.File
12+
13+
def mkjar():
14+
jarfile = File(jardir, jarfn)
15+
# create a .jar file containing a .class file
16+
if not jarfile.exists():
17+
support.compileJava("%s/%s/%s.java" % (jardir, package, clazz))
18+
jarPacker = support.JarPacker(jarfile, bufsize=128)
19+
jarPacker.addFile(clazzfile, parentDirName=package)
20+
jarPacker.close()
21+
return jardir + '/' + jarfn, package, clazz
22+
23+
24+
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package javapackage;
2+
3+
public class JavaClass {}

bugtests/support.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,16 @@ def runJavaJar(jar, *args, **kw):
108108
return execCmd(cmd, kw)
109109

110110
def runJython(cls, **kw):
111+
javaargs = ''
112+
if 'javaargs' in kw:
113+
javaargs = kw['javaargs']
111114
classpath = cfg.classpath
112115
if "classpath" in kw:
113116
classpath = os.pathsep.join([cfg.classpath, kw["classpath"]])
114117
if UNIX:
115-
cmd = "%s/bin/java -classpath %s -Dpython.home=%s org.python.util.jython %s" % (cfg.java_home, classpath, cfg.jython_home, cls)
118+
cmd = "%s/bin/java -classpath %s %s -Dpython.home=%s org.python.util.jython %s" % (cfg.java_home, classpath, javaargs, cfg.jython_home, cls)
116119
elif WIN:
117-
cmd = 'cmd /C "%s/bin/java.exe -classpath %s -Dpython.home=%s org.python.util.jython %s"' % (cfg.java_home, classpath, cfg.jython_home, cls)
120+
cmd = 'cmd /C "%s/bin/java.exe -classpath %s %s -Dpython.home=%s org.python.util.jython %s"' % (cfg.java_home, classpath, javaargs, cfg.jython_home, cls)
118121
return execCmd(cmd, kw)
119122

120123
def compileJPythonc(*files, **kw):

bugtests/test385.py

Lines changed: 8 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -9,54 +9,17 @@
99
use a unique java package name for the sake of this test
1010
"""
1111

12+
import jarmaker
1213
import support
1314
import sys
14-
import os
15-
16-
from java.io import File
17-
18-
PACKAGE = "test385javapackage"
19-
CLAZZ = "test385j"
20-
JARDIR = "test385jar"
21-
JARFILE = "test385.jar"
22-
CLAZZ_FILE = File(PACKAGE, "%s.class" % CLAZZ) # java.io.File
23-
24-
def mkdir(dir):
25-
if not os.path.exists(dir):
26-
os.mkdir(dir)
27-
28-
def mkjavaclass():
29-
mkdir(PACKAGE)
30-
f = open("%s/%s.java" % (PACKAGE, CLAZZ), "w")
31-
f.write("""
32-
package %s;
33-
public class %s {
34-
}
35-
""" % (PACKAGE, CLAZZ))
36-
f.close()
37-
support.compileJava("%s/%s.java" % (PACKAGE, CLAZZ))
38-
39-
def mkjar():
40-
mkdir(JARDIR)
41-
jarFile = File(JARDIR, JARFILE)
42-
jarPacker = support.JarPacker(jarFile, bufsize=128)
43-
jarPacker.addFile(CLAZZ_FILE, parentDirName=PACKAGE)
44-
jarPacker.close()
45-
return jarFile
46-
47-
48-
# create a .jar file containing a .class file
49-
mkjavaclass()
50-
jarFile = mkjar()
51-
52-
# important: delete the class file from the file system (otherwise it can be imported)
53-
CLAZZ_FILE.delete()
54-
if CLAZZ_FILE.exists():
55-
raise AssertionError, "%s is still on the file system" % CLAZZ_FILE
5615

16+
jarfn, package, clazz = jarmaker.mkjar()
5717
# append this jar file to sys.path
58-
sys.path.append(jarFile.getAbsolutePath())
18+
sys.path.append(jarfn)
5919

6020
# try to import the class
61-
importStmt = "from %s import %s" % (PACKAGE, CLAZZ)
62-
exec(importStmt)
21+
importStmt = "from %s import %s" % (package, clazz)
22+
try:
23+
exec(importStmt)
24+
finally:
25+
sys.path.remove(jarfn)

bugtests/test402.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
'''
2+
3+
test402m adds a jar file to sys.path and imports a package from it. The first
4+
run ensures that, by default, package scanning is enabled for jars added to
5+
sys.path. The second run turns off package scanning, so it checks that the
6+
package is unimportable without the scan. Finally, we run test402n which adds
7+
the same jar to its sys.path and imports a fully qualified class from it. We
8+
run it with package scanning off to make sure that even without package
9+
scanning, jars are correctly added to sys.path and fully qualified class
10+
imports work on them.
11+
12+
'''
13+
14+
import support
15+
import jarmaker
16+
17+
jarmaker.mkjar()
18+
19+
support.runJython('test402m.py')
20+
ret = support.runJython('test402m.py', error='test402.err',
21+
javaargs='-Dpython.cachedir.skip=true', expectError=1)
22+
if ret == 0:
23+
raise support.TestError('Successfully imported a package from a jar on sys.path without caching!')
24+
support.runJython('test402n.py', javaargs='-Dpython.cachedir.skip=true')

bugtests/test402m.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import sys
2+
sys.path.append('simplejar/simple.jar')
3+
4+
import javapackage

bugtests/test402n.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import sys
2+
sys.path.append('simplejar/simple.jar')
3+
4+
from javapackage import JavaClass

src/org/python/core/JavaImportHelper.java

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -176,20 +176,12 @@ private static Map buildLoadedPackages() {
176176
}
177177

178178
/**
179-
* Check a java class on VM level.
180-
*
181-
* @param packageName
182-
* @param className
183-
*
184-
* @return <code>true</code> if the java class can be doubtlessly identified, <code>false</code> otherwise.
179+
* @return <code>true</code> if the java class can be found by the current
180+
* Py classloader setup
185181
*/
186182
private static boolean isJavaClass(String packageName, String className) {
187-
if (className != null && className.length() > 0) {
188-
className = packageName.replace('.', '/') + "/" + className + ".class";
189-
return Thread.currentThread().getContextClassLoader().getResource(className) != null;
190-
} else {
191-
return false;
192-
}
183+
return className != null && className.length() > 0
184+
&& Py.findClass(packageName + "." + className) != null;
193185
}
194186

195187
/**

src/org/python/core/PySystemState.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,10 @@ else if (PY_RELEASE_LEVEL == 0xAA)
544544

545545
public static PackageManager packageManager;
546546
public static File cachedir;
547+
548+
public static boolean isPackageCacheEnabled() {
549+
return cachedir != null;
550+
}
547551

548552
private static void initCacheDirectory(Properties props) {
549553
if (Py.frozen) {

src/org/python/core/SyspathArchive.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ public SyspathArchive(String archiveName) throws IOException {
1313
throw new IOException("path '" + archiveName + "' not an archive");
1414
}
1515
this.zipFile = new ZipFile(new File(archiveName));
16-
PySystemState.packageManager.addJar(archiveName, false);
16+
if(PySystemState.isPackageCacheEnabled()) {
17+
PySystemState.packageManager.addJar(archiveName, true);
18+
}
1719
}
1820

1921
SyspathArchive(ZipFile zipFile, String archiveName) {

0 commit comments

Comments
 (0)