Index: PackageManager.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/core/PackageManager.java,v retrieving revision 2.8 diff -u -r2.8 PackageManager.java --- PackageManager.java 2001/03/13 20:19:53 2.8 +++ PackageManager.java 2001/07/22 12:48:41 @@ -58,6 +58,14 @@ */ public abstract void addJarDir(String dir); + /** + * Append a jar file to the list of locations searched for + * java packages and java classes. + * + * @param jarfile A directory name. + */ + public abstract void addJar(String jarfile); + /** Basic helper implementation of {@link #doDir}. * It merges information from jpkg {@link PyJavaPackage#clsSet} * and {@link PyJavaPackage#__dict__}. Index: SysPackageManager.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/core/SysPackageManager.java,v retrieving revision 1.7 diff -u -r1.7 SysPackageManager.java --- SysPackageManager.java 2001/03/13 20:22:25 1.7 +++ SysPackageManager.java 2001/07/22 12:48:41 @@ -36,6 +36,10 @@ } } + public void addJar(String jarfile) { + addJarToPackages(new File(jarfile), false); + } + public void addJarDir(String jdir) { File file = new File(jdir); if (!file.isDirectory()) return; Index: SyspathJavaLoader.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/core/SyspathJavaLoader.java,v retrieving revision 2.3 diff -u -r2.3 SyspathJavaLoader.java --- SyspathJavaLoader.java 2001/02/02 09:28:37 2.3 +++ SyspathJavaLoader.java 2001/07/22 12:48:42 @@ -5,6 +5,7 @@ import java.io.*; import java.util.StringTokenizer; import java.util.Hashtable; +import java.util.zip.*; public class SyspathJavaLoader extends ClassLoader { @@ -28,7 +29,18 @@ PyList path = Py.getSystemState().path; for (int i=0; i < path.__len__(); i++) { - String dir = path.get(i).__str__().toString(); + PyObject entry = path.__getitem__(i); + if (entry instanceof SyspathArchive) { + SyspathArchive archive = (SyspathArchive) entry; + ZipEntry ze = archive.getEntry(res); + if (ze != null) { + try { + return archive.getInputStream(ze); + } catch (IOException e) { ; } + } + continue; + } + String dir = entry.__str__().toString(); if (dir.length() == 0) dir = null; try { return new BufferedInputStream( @@ -75,10 +87,25 @@ { PyList path = Py.getSystemState().path; for (int i=0; i < path.__len__(); i++) { - String dir = path.get(i).__str__().toString(); - FileInputStream fis = open(dir, name); - if (fis == null) + InputStream fis = null; + PyObject entry = path.__getitem__(i); + if (entry instanceof SyspathArchive) { + SyspathArchive archive = (SyspathArchive) entry; + String entryname = name.replace('.', File.separatorChar) + + ".class"; + ZipEntry ze = archive.getEntry(entryname); + if (ze != null) { + try { + fis = archive.getInputStream(ze); + } catch (IOException exc) { ; } + } + } else { + String dir = entry.__str__().toString(); + fis = open(dir, name); + } + if (fis == null) { continue; + } try { int size = fis.available(); byte[] buffer = new byte[size]; Index: imp.java =================================================================== RCS file: /cvsroot/jython/jython/org/python/core/imp.java,v retrieving revision 2.48 diff -u -r2.48 imp.java --- imp.java 2001/07/17 20:34:35 2.48 +++ imp.java 2001/07/22 12:48:44 @@ -5,6 +5,7 @@ import java.io.*; import java.util.Hashtable; import java.util.Properties; +import java.util.zip.*; /** * Utility functions for "import" support. @@ -155,6 +156,19 @@ return createFromCode(name, code); } + private static PyObject createFromSource(String name, InputStream fp, + String filename, + String outFilename) + { + byte[] bytes = compileSource(name, fp, filename, outFilename); + + Py.writeComment("import", "'" + name + "' as " + filename); + + PyCode code = BytecodeLoader.makeCode(name+"$py", bytes); + return createFromCode(name, code); + } + + static PyObject createFromCode(String name, PyCode c) { PyModule module = addModule(name); @@ -264,6 +278,80 @@ return null; } + static PyObject loadFromZipFile(String name, String modName, + SyspathArchive zipArchive) { + PyObject o = null; + ZipEntry pkgEntry = null; + String entryName = name; + + String pyName = entryName +".py"; + String className = entryName +"$py.class"; + + try { + String sourceName = entryName + "/__init__.py"; + String compledName = entryName + "/__init__$py.class"; + ZipEntry sourceEntry = zipArchive.getEntry(sourceName); + ZipEntry compiledEntry = zipArchive.getEntry(compledName); + if (sourceEntry != null || compiledEntry != null) { + Py.writeDebug("import", "trying package: " + modName + + " in jar/zip file " + zipArchive); + PyModule m = addModule(modName); + + SyspathArchive subArchive = zipArchive.makeSubfolder(modName); + PyList zipPath = new PyList(new PyObject[] { subArchive }); + m.__dict__.__setitem__("__path__", zipPath); + o = loadFromZipFile("__init__", modName, subArchive); + if (o != null) { + return m; + } + } + + ZipEntry pyEntry = zipArchive.getEntry(pyName); + ZipEntry classEntry = zipArchive.getEntry(className); + if (pyEntry != null) { + Py.writeDebug("import", "trying source entry: " + pyName + + " from jar/zip file " + zipArchive); + if (classEntry != null) { + Py.writeDebug("import", "trying precompiled entry " + + className + " from jar/zip file " + + zipArchive); + long pyTime = pyEntry.getTime(); + long classTime = classEntry.getTime(); + if (classTime >= pyTime) { + InputStream is = zipArchive.getInputStream(classEntry); + o = createFromPyClass(modName, is, true, + classEntry.getName()); + if (o != null) { + return o; + } + } + } + InputStream is = zipArchive.getInputStream(pyEntry); + return createFromSource(modName, is, pyEntry.getName(), null); + } + } catch (Exception e) { + Py.writeDebug("import", "loadFromZipFile exception: " + + e.toString()); + e.printStackTrace(); + } + return null; + } + + private static boolean isSyspathArchive(PyObject entry) { + if (entry instanceof SyspathArchive) + return true; + String dir = entry.toString(); + int idx = dir.indexOf('!'); + if (idx > 0) { + dir = dir.substring(0, idx); + } + if (dir.length() < 5) { + return false; + } + String ext = dir.substring(dir.length() - 4); + return ext.equalsIgnoreCase(".zip") || ext.equalsIgnoreCase(".jar"); + } + static PyObject loadFromPath(String name, PyList path) { return loadFromPath(name, name, path); } @@ -279,13 +367,28 @@ int n = path.__len__(); for (int i=0; i 0) { + archiveName = archiveName.substring(0, idx); + } + zipFile = new ZipFile(new File(archiveName)); + Py.getSystemState().packageManager.addJar(archiveName); + } + + SyspathArchive(ZipFile zipFile, String archiveName) { + super(archiveName); + this.zipFile = zipFile; + } + + public SyspathArchive makeSubfolder(String folder) { + return new SyspathArchive(zipFile, super.toString() + "!" + folder); + } + + private String makeEntry(String entry) { + String archive = super.toString(); + int idx = archive.indexOf('!'); + if (idx < 0) { + return entry; + } + String folder = archive.substring(idx+1); + return folder + "/" + entry; + } + + ZipEntry getEntry(String entryName) { + return zipFile.getEntry(makeEntry(entryName)); + } + + InputStream getInputStream(ZipEntry entry) throws IOException { + InputStream istream = zipFile.getInputStream(entry); + + // Some jdk1.1 VMs have problems with detecting the end of a zip + // stream correctly. If you read beyond the end, you get a + // EOFException("Unexpected end of ZLIB input stream"), not a + // -1 return value. + // As a workaround we read the file fully here, but only getSize() + // bytes. + int len = (int) entry.getSize(); + byte[] buffer = new byte[len]; + int off = 0; + while (len > 0) { + int l = istream.read(buffer, off, buffer.length - off); + if (l < 0) + return null; + off += l; + len -= l; + } + istream.close(); + return new ByteArrayInputStream(buffer); + } + +/* + protected void finalize() { + System.out.println("closing zip file " + toString()); + try { + zipFile.close(); + } catch (IOException e) { + Py.writeDebug("import", "closing zipEntry failed"); + } + } +*/ +}