From: <fwi...@us...> - 2007-05-18 00:30:16
|
Revision: 3232 http://svn.sourceforge.net/jython/?rev=3232&view=rev Author: fwierzbicki Date: 2007-05-17 17:30:12 -0700 (Thu, 17 May 2007) Log Message: ----------- moved package cache related classes into their own package. Modified Paths: -------------- branches/2.3/Lib/jxxload_help/PackageManager.java branches/2.3/bugtests/test398.py branches/2.3/src/org/python/core/InternalTables.java branches/2.3/src/org/python/core/PyJavaClass.java branches/2.3/src/org/python/core/PyJavaPackage.java branches/2.3/src/org/python/core/PySystemState.java Added Paths: ----------- branches/2.3/src/org/python/core/packagecache/ branches/2.3/src/org/python/core/packagecache/CachedJarsPackageManager.java branches/2.3/src/org/python/core/packagecache/PackageManager.java branches/2.3/src/org/python/core/packagecache/PathPackageManager.java branches/2.3/src/org/python/core/packagecache/SysPackageManager.java Removed Paths: ------------- branches/2.3/src/org/python/core/CachedJarsPackageManager.java branches/2.3/src/org/python/core/PackageManager.java branches/2.3/src/org/python/core/PathPackageManager.java branches/2.3/src/org/python/core/SysPackageManager.java Modified: branches/2.3/Lib/jxxload_help/PackageManager.java =================================================================== --- branches/2.3/Lib/jxxload_help/PackageManager.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/Lib/jxxload_help/PackageManager.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -2,7 +2,7 @@ package jxxload_help; -public class PackageManager extends org.python.core.PathPackageManager { +public class PackageManager extends org.python.core.packagecache.PathPackageManager { private JavaLoaderFactory factory; private ClassLoader loader; Modified: branches/2.3/bugtests/test398.py =================================================================== --- branches/2.3/bugtests/test398.py 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/bugtests/test398.py 2007-05-18 00:30:12 UTC (rev 3232) @@ -16,7 +16,7 @@ from java.io import File from java.lang import String from java.util import Properties -from org.python.core import SysPackageManager +from org.python.core.packagecache import SysPackageManager PACKAGE = "test398javapackage" CACHEDIR = "test398cache" Deleted: branches/2.3/src/org/python/core/CachedJarsPackageManager.java =================================================================== --- branches/2.3/src/org/python/core/CachedJarsPackageManager.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/src/org/python/core/CachedJarsPackageManager.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -1,595 +0,0 @@ -// Copyright (c) Corporation for National Research Initiatives -// Copyright 2000 Samuele Pedroni - -package org.python.core; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.EOFException; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Modifier; -import java.net.URL; -import java.net.URLConnection; -import java.security.AccessControlException; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * Abstract package manager that gathers info about statically known classes - * from a set of jars. This info can be eventually cached. Off-the-shelf this - * class offers a local file-system based cache impl. - */ -public abstract class CachedJarsPackageManager extends PackageManager { - - /** - * Message log method - hook. This default impl does nothing. - * - * @param msg message text - */ - protected void message(String msg) { - } - - /** - * Warning log method - hook. This default impl does nothing. - * - * @param warn warning text - */ - protected void warning(String warn) { - } - - /** - * Comment log method - hook. This default impl does nothing. - * - * @param msg message text - */ - protected void comment(String msg) { - } - - /** - * Debug log method - hook. This default impl does nothing. - * - * @param msg message text - */ - protected void debug(String msg) { - } - - /** - * Filter class/pkg by name helper method - hook. The default impl. is used - * by {@link #addJarToPackages} in order to filter out classes whose name - * contains '$' (e.g. inner classes,...). Should be used or overriden by - * derived classes too. Also to be used in {@link #doDir}. - * - * @param name class/pkg name - * @param pkg if true, name refers to a pkg - * @return true if name must be filtered out - */ - protected boolean filterByName(String name, boolean pkg) { - return name.indexOf('$') != -1; - } - - /** - * Filter class by access perms helper method - hook. The default impl. is - * used by {@link #addJarToPackages} in order to filter out non-public - * classes. Should be used or overriden by derived classes too. Also to be - * used in {@link #doDir}. Access perms can be read with - * {@link #checkAccess}. - * - * @param name class name - * @param acc class access permissions as int - * @return true if name must be filtered out - */ - protected boolean filterByAccess(String name, int acc) { - return (acc & Modifier.PUBLIC) != Modifier.PUBLIC; - } - - private boolean indexModified; - - private Hashtable jarfiles; - - private static String vectorToString(Vector vec) { - int n = vec.size(); - StringBuffer ret = new StringBuffer(); - for (int i = 0; i < n; i++) { - ret.append((String) vec.elementAt(i)); - if (i < n - 1) { - ret.append(","); - } - } - return ret.toString(); - } - - // Add a single class from zipFile to zipPackages - // Only add valid, public classes - private void addZipEntry(Hashtable zipPackages, ZipEntry entry, - ZipInputStream zip) throws IOException { - String name = entry.getName(); - // System.err.println("entry: "+name); - if (!name.endsWith(".class")) { - return; - } - - char sep = '/'; - int breakPoint = name.lastIndexOf(sep); - if (breakPoint == -1) { - breakPoint = name.lastIndexOf('\\'); - sep = '\\'; - } - - String packageName; - if (breakPoint == -1) { - packageName = ""; - } else { - packageName = name.substring(0, breakPoint).replace(sep, '.'); - } - - String className = name.substring(breakPoint + 1, name.length() - 6); - - if (filterByName(className, false)) { - return; - } - - Vector[] vec = (Vector[]) zipPackages.get(packageName); - if (vec == null) { - vec = new Vector[] { new Vector(), new Vector() }; - zipPackages.put(packageName, vec); - } - int access = checkAccess(zip); - if ((access != -1) && !filterByAccess(name, access)) { - vec[0].addElement(className); - } else { - vec[1].addElement(className); - } - } - - // Extract all of the packages in a single jarfile - private Hashtable getZipPackages(InputStream jarin) throws IOException { - Hashtable zipPackages = new Hashtable(); - - ZipInputStream zip = new ZipInputStream(jarin); - - ZipEntry entry; - while ((entry = zip.getNextEntry()) != null) { - addZipEntry(zipPackages, entry, zip); - zip.closeEntry(); - } - - // Turn each vector into a comma-separated String - for (Enumeration e = zipPackages.keys(); e.hasMoreElements();) { - Object key = e.nextElement(); - Vector[] vec = (Vector[]) zipPackages.get(key); - String classes = vectorToString(vec[0]); - if (vec[1].size() > 0) { - classes += '@' + vectorToString(vec[1]); - } - zipPackages.put(key, classes); - } - - return zipPackages; - } - - /** - * Gathers classes info from jar specified by jarurl URL. Eventually just - * using previously cached info. Eventually updated info is not cached. - * Persistent cache storage access goes through inOpenCacheFile() and - * outCreateCacheFile(). - */ - public void addJarToPackages(java.net.URL jarurl) { - addJarToPackages(jarurl, null, false); - } - - /** - * Gathers classes info from jar specified by jarurl URL. Eventually just - * using previously cached info. Eventually updated info is (re-)cached if - * param cache is true. Persistent cache storage access goes through - * inOpenCacheFile() and outCreateCacheFile(). - */ - public void addJarToPackages(URL jarurl, boolean cache) { - addJarToPackages(jarurl, null, cache); - } - - /** - * Gathers classes info from jar specified by File jarfile. Eventually just - * using previously cached info. Eventually updated info is not cached. - * Persistent cache storage access goes through inOpenCacheFile() and - * outCreateCacheFile(). - */ - public void addJarToPackages(File jarfile) { - addJarToPackages(null, jarfile, false); - } - - /** - * Gathers classes info from jar specified by File jarfile. Eventually just - * using previously cached info. Eventually updated info is (re-)cached if - * param cache is true. Persistent cache storage access goes through - * inOpenCacheFile() and outCreateCacheFile(). - */ - public void addJarToPackages(File jarfile, boolean cache) { - addJarToPackages(null, jarfile, cache); - } - - private void addJarToPackages(URL jarurl, File jarfile, boolean cache) { - try { - boolean caching = this.jarfiles != null; - - URLConnection jarconn = null; - boolean localfile = true; - - if (jarfile == null) { - jarconn = jarurl.openConnection(); - // This is necessary because 'file:' url-connections - // return always 0 through getLastModified (bug?). - // And in order to handle localfiles (from urls too) - // uniformly. - if (jarconn.getURL().getProtocol().equals("file")) { - // ??pending: need to use java2 URLDecoder.decode? - String jarfilename = jarurl.getFile(); - jarfilename = jarfilename.replace('/', File.separatorChar); - jarfile = new File(jarfilename); - } else { - localfile = false; - } - } - - if (localfile && !jarfile.exists()) { - return; - } - - Hashtable zipPackages = null; - - long mtime = 0; - String jarcanon = null; - JarXEntry entry = null; - boolean brandNew = false; - - if (caching) { - - if (localfile) { - mtime = jarfile.lastModified(); - jarcanon = jarfile.getCanonicalPath(); - } else { - mtime = jarconn.getLastModified(); - jarcanon = jarurl.toString(); - } - - entry = (JarXEntry) this.jarfiles.get(jarcanon); - - if ((entry == null || !(new File(entry.cachefile).exists())) - && cache) { - message("processing new jar, '" + jarcanon + "'"); - - String jarname; - if (localfile) { - jarname = jarfile.getName(); - } else { - jarname = jarurl.getFile(); - int slash = jarname.lastIndexOf('/'); - if (slash != -1) - jarname = jarname.substring(slash + 1); - } - jarname = jarname.substring(0, jarname.length() - 4); - - entry = new JarXEntry(jarname); - this.jarfiles.put(jarcanon, entry); - - brandNew = true; - } - - if (mtime != 0 && entry != null && entry.mtime == mtime) { - zipPackages = readCacheFile(entry, jarcanon); - } - - } - - if (zipPackages == null) { - caching = caching && cache; - - if (caching) { - this.indexModified = true; - if (entry.mtime != 0) { - message("processing modified jar, '" + jarcanon + "'"); - } - entry.mtime = mtime; - } - - InputStream jarin; - if (jarconn == null) { - jarin = new BufferedInputStream( - new FileInputStream(jarfile)); - } else { - jarin = jarconn.getInputStream(); - } - - zipPackages = getZipPackages(jarin); - - if (caching) { - writeCacheFile(entry, jarcanon, zipPackages, brandNew); - } - } - - addPackages(zipPackages, jarcanon); - } catch (IOException ioe) { - // silently skip any bad directories - warning("skipping bad jar, '" - + (jarfile != null ? jarfile.toString() : jarurl.toString()) - + "'"); - } - - } - - private void addPackages(Hashtable zipPackages, String jarfile) { - for (Enumeration e = zipPackages.keys(); e.hasMoreElements();) { - String pkg = (String) e.nextElement(); - String classes = (String) zipPackages.get(pkg); - - int idx = classes.indexOf('@'); - if (idx >= 0 && Options.respectJavaAccessibility) { - classes = classes.substring(0, idx); - } - - makeJavaPackage(pkg, classes, jarfile); - } - } - - // Read in cache file storing package info for a single .jar - // Return null and delete this cachefile if it is invalid - private Hashtable readCacheFile(JarXEntry entry, String jarcanon) { - String cachefile = entry.cachefile; - long mtime = entry.mtime; - - debug("reading cache, '" + jarcanon + "'"); - - try { - DataInputStream istream = inOpenCacheFile(cachefile); - String old_jarcanon = istream.readUTF(); - long old_mtime = istream.readLong(); - if ((!old_jarcanon.equals(jarcanon)) || (old_mtime != mtime)) { - comment("invalid cache file: " + cachefile + ", " + jarcanon - + ":" + old_jarcanon + ", " + mtime + ":" + old_mtime); - deleteCacheFile(cachefile); - return null; - } - Hashtable packs = new Hashtable(); - try { - while (true) { - String packageName = istream.readUTF(); - String classes = istream.readUTF(); - packs.put(packageName, classes); - } - } catch (EOFException eof) { - ; - } - istream.close(); - - return packs; - } catch (IOException ioe) { - // if (cachefile.exists()) cachefile.delete(); - return null; - } - } - - // Write a cache file storing package info for a single .jar - private void writeCacheFile(JarXEntry entry, String jarcanon, - Hashtable zipPackages, boolean brandNew) { - try { - DataOutputStream ostream = outCreateCacheFile(entry, brandNew); - ostream.writeUTF(jarcanon); - ostream.writeLong(entry.mtime); - comment("rewriting cachefile for '" + jarcanon + "'"); - - for (Enumeration e = zipPackages.keys(); e.hasMoreElements();) { - String packageName = (String) e.nextElement(); - String classes = (String) zipPackages.get(packageName); - ostream.writeUTF(packageName); - ostream.writeUTF(classes); - } - ostream.close(); - } catch (IOException ioe) { - warning("can't write cache file for '" + jarcanon + "'"); - } - } - - /** - * Initializes cache. Eventually reads back cache index. Index persistent - * storage is accessed through inOpenIndex(). - */ - protected void initCache() { - this.indexModified = false; - this.jarfiles = new Hashtable(); - - try { - DataInputStream istream = inOpenIndex(); - if (istream == null) { - return; - } - - try { - while (true) { - String jarcanon = istream.readUTF(); - String cachefile = istream.readUTF(); - long mtime = istream.readLong(); - this.jarfiles - .put(jarcanon, new JarXEntry(cachefile, mtime)); - } - } catch (EOFException eof) { - ; - } - istream.close(); - } catch (IOException ioe) { - warning("invalid index file"); - } - - } - - /** - * Write back cache index. Index persistent storage is accessed through - * outOpenIndex(). - */ - public void saveCache() { - if (this.jarfiles == null || !this.indexModified) { - return; - } - - this.indexModified = false; - - comment("writing modified index file"); - - try { - DataOutputStream ostream = outOpenIndex(); - for (Enumeration e = this.jarfiles.keys(); e.hasMoreElements();) { - String jarcanon = (String) e.nextElement(); - JarXEntry entry = (JarXEntry) this.jarfiles.get(jarcanon); - ostream.writeUTF(jarcanon); - ostream.writeUTF(entry.cachefile); - ostream.writeLong(entry.mtime); - } - ostream.close(); - } catch (IOException ioe) { - warning("can't write index file"); - } - } - - // hooks for changing cache storage - - /** - * To pass a cachefile id by ref. And for internal use. See - * outCreateCacheFile - */ - public static class JarXEntry extends Object { - /** cachefile id */ - public String cachefile; - - public long mtime; - - public JarXEntry(String cachefile) { - this.cachefile = cachefile; - } - - public JarXEntry(String cachefile, long mtime) { - this.cachefile = cachefile; - this.mtime = mtime; - } - - } - - /** - * Open cache index for reading from persistent storage - hook. Must Return - * null if this is absent. This default impl is part of the off-the-shelf - * local file-system cache impl. Can be overriden. - */ - protected DataInputStream inOpenIndex() throws IOException { - File indexFile = new File(this.cachedir, "packages.idx"); - - if (!indexFile.exists()) { - return null; - } - - DataInputStream istream = new DataInputStream(new BufferedInputStream( - new FileInputStream(indexFile))); - - return istream; - } - - /** - * Open cache index for writing back to persistent storage - hook. This - * default impl is part of the off-the-shelf local file-system cache impl. - * Can be overriden. - */ - protected DataOutputStream outOpenIndex() throws IOException { - File indexFile = new File(this.cachedir, "packages.idx"); - - return new DataOutputStream(new BufferedOutputStream( - new FileOutputStream(indexFile))); - } - - /** - * Open cache file for reading from persistent storage - hook. This default - * impl is part of the off-the-shelf local file-system cache impl. Can be - * overriden. - */ - protected DataInputStream inOpenCacheFile(String cachefile) - throws IOException { - return new DataInputStream(new BufferedInputStream(new FileInputStream( - cachefile))); - } - - /** - * Delete (invalidated) cache file from persistent storage - hook. This - * default impl is part of the off-the-shelf local file-system cache impl. - * Can be overriden. - */ - protected void deleteCacheFile(String cachefile) { - new File(cachefile).delete(); - } - - /** - * Create/open cache file for rewriting back to persistent storage - hook. - * If create is false, cache file is supposed to exist and must be opened - * for rewriting, entry.cachefile is a valid cachefile id. If create is - * true, cache file must be created. entry.cachefile is a flat jarname to be - * used to produce a valid cachefile id (to be put back in entry.cachefile - * on exit). This default impl is part of the off-the-shelf local - * file-system cache impl. Can be overriden. - */ - protected DataOutputStream outCreateCacheFile(JarXEntry entry, - boolean create) throws IOException { - File cachefile = null; - - if (create) { - int index = 1; - String suffix = ""; - String jarname = entry.cachefile; - while (true) { - cachefile = new File(this.cachedir, jarname + suffix + ".pkc"); - // System.err.println("try cachefile: "+cachefile); - if (!cachefile.exists()) { - break; - } - suffix = "$" + index; - index += 1; - } - entry.cachefile = cachefile.getCanonicalPath(); - } else - cachefile = new File(entry.cachefile); - - return new DataOutputStream(new BufferedOutputStream( - new FileOutputStream(cachefile))); - } - - // for default cache (local fs based) impl - - private File cachedir; - - /** - * Initialize off-the-shelf (default) local file-system cache impl. Must be - * called before {@link #initCache}. cachedir is the cache repository - * directory, this is eventually created. Returns true if dir works. - */ - protected boolean useCacheDir(File aCachedir1) { - if (aCachedir1 == null) { - return false; - } - try { - if(!aCachedir1.isDirectory() && aCachedir1.mkdirs() == false) { - warning("can't create package cache dir, '" + aCachedir1 + "'"); - return false; - } - } catch(AccessControlException ace) { - warning("The java security manager isn't allowing access to the package cache dir, '" + aCachedir1 + "'"); - return false; - } - - this.cachedir = aCachedir1; - - return true; - } - -} Modified: branches/2.3/src/org/python/core/InternalTables.java =================================================================== --- branches/2.3/src/org/python/core/InternalTables.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/src/org/python/core/InternalTables.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -2,6 +2,8 @@ package org.python.core; +import org.python.core.packagecache.PackageManager; + import java.util.StringTokenizer; public abstract class InternalTables { @@ -134,4 +136,4 @@ } } -} \ No newline at end of file +} Deleted: branches/2.3/src/org/python/core/PackageManager.java =================================================================== --- branches/2.3/src/org/python/core/PackageManager.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/src/org/python/core/PackageManager.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -1,227 +0,0 @@ -// Copyright (c) Corporation for National Research Initiatives -// Copyright 2000 Samuele Pedroni - -package org.python.core; - -/** - * Abstract package manager. - */ -public abstract class PackageManager extends Object { - - public PyJavaPackage topLevelPackage; - - public PackageManager() { - this.topLevelPackage = new PyJavaPackage("", this); - } - - abstract public Class findClass(String pkg, String name, String reason); - - public Class findClass(String pkg, String name) { - return findClass(pkg, name, "java class"); - } - - public void notifyPackageImport(String pkg, String name) { - } - - /** - * Dynamically check if pkg.name exists as java pkg in the controlled - * hierarchy. Should be overriden. - * - * @param pkg parent pkg name - * @param name candidate name - * @return true if pkg exists - */ - public abstract boolean packageExists(String pkg, String name); - - /** - * Reports the specified package content names. Should be overriden. Used by - * {@link PyJavaPackage#__dir__} and {@link PyJavaPackage#fillDir}. - * - * @return resulting list of names (PyList of PyString) - * @param jpkg queried package - * @param instantiate if true then instatiate reported names in package dict - * @param exclpkgs exclude packages (just when instantiate is false) - */ - public abstract PyList doDir(PyJavaPackage jpkg, boolean instantiate, - boolean exclpkgs); - - /** - * Append a directory to the list of directories searched for java packages - * and java classes. - * - * @param dir A directory. - */ - public abstract void addDirectory(java.io.File dir); - - /** - * Append a directory to the list of directories searched for java packages - * and java classes. - * - * @param dir A directory name. - */ - public abstract void addJarDir(String dir, boolean cache); - - /** - * 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, boolean cache); - - /** - * Basic helper implementation of {@link #doDir}. It merges information - * from jpkg {@link PyJavaPackage#clsSet} and {@link PyJavaPackage#__dict__}. - */ - protected PyList basicDoDir(PyJavaPackage jpkg, boolean instantiate, - boolean exclpkgs) { - PyStringMap dict = jpkg.__dict__; - PyStringMap cls = jpkg.clsSet; - - if (!instantiate) { - PyList ret = cls.keys(); - - PyList dictKeys = dict.keys(); - - for (int i = 0; i < dictKeys.__len__(); i++) { - PyObject name = dictKeys.pyget(i); - if (!cls.has_key(name)) { - if (exclpkgs && dict.get(name) instanceof PyJavaPackage) - continue; - ret.append(name); - } - } - - return ret; - } - - PyList clsNames = cls.keys(); - - for (int i = 0; i < clsNames.__len__(); i++) { - PyObject name = clsNames.pyget(i); - if (!dict.has_key(name)) - jpkg.addLazyClass(name.toString()); - } - - return dict.keys(); - } - - /** - * Helper merging list2 into list1. Returns list1. - */ - protected PyList merge(PyList list1, PyList list2) { - for (int i = 0; i < list2.__len__(); i++) { - PyObject name = list2.pyget(i); - list1.append(name); - } - - return list1; - } - - public PyObject lookupName(String name) { - PyObject top = this.topLevelPackage; - do { - int dot = name.indexOf('.'); - String firstName = name; - String lastName = null; - if (dot != -1) { - firstName = name.substring(0, dot); - lastName = name.substring(dot + 1, name.length()); - } - firstName = firstName.intern(); - top = top.__findattr__(firstName); - if (top == null) - return null; - // ??pending: test for jpkg/jclass? - name = lastName; - } while (name != null); - return top; - } - - /** - * Creates package/updates statically known classes info. Uses - * {@link PyJavaPackage#addPackage(java.lang.String, java.lang.String) }, - * {@link PyJavaPackage#addPlaceholders}. - * - * @param name package name - * @param classes comma-separated string - * @param jarfile involved jarfile; can be null - * @return created/updated package - */ - public PyJavaPackage makeJavaPackage(String name, String classes, - String jarfile) { - PyJavaPackage p = this.topLevelPackage; - if (name.length() != 0) - p = p.addPackage(name, jarfile); - - if (classes != null) - p.addPlaceholders(classes); - - return p; - } - - /** - * Check that a given stream is a valid Java .class file. And return its - * access permissions as an int. - */ - static protected int checkAccess(java.io.InputStream cstream) - throws java.io.IOException { - java.io.DataInputStream istream = new java.io.DataInputStream(cstream); - - int magic = istream.readInt(); - - //int minor = - istream.readShort(); - //int major = - istream.readShort(); - - if (magic != 0xcafebabe) - return -1; - // Check versions??? - // System.out.println("magic: "+magic+", "+major+", "+minor); - int nconstants = istream.readShort(); - for (int i = 1; i < nconstants; i++) { - int cid = istream.readByte(); - // System.out.println(""+i+" : "+cid); - switch (cid) { - case 7: - istream.skipBytes(2); - break; - case 9: - case 10: - case 11: - istream.skipBytes(4); - break; - case 8: - istream.skipBytes(2); - break; - case 3: - case 4: - istream.skipBytes(4); - break; - case 5: - case 6: - istream.skipBytes(8); - i++; - break; - case 12: - istream.skipBytes(4); - break; - case 1: - // System.out.println("utf: "+istream.readUTF()+";"); - int slength = istream.readUnsignedShort(); - istream.skipBytes(slength); - break; - default: - // System.err.println("unexpected cid: "+cid+", "+i+", "+ - // nconstants); - // for (int j=0; j<10; j++) - // System.err.print(", "+istream.readByte()); - // System.err.println(); - return -1; - } - } - return istream.readShort(); - } - -} Deleted: branches/2.3/src/org/python/core/PathPackageManager.java =================================================================== --- branches/2.3/src/org/python/core/PathPackageManager.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/src/org/python/core/PathPackageManager.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -1,230 +0,0 @@ -// Copyright (c) Corporation for National Research Initiatives -// Copyright 2000 Samuele Pedroni - -package org.python.core; - -import java.io.BufferedInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FilenameFilter; -import java.io.IOException; - -/** - * Path package manager. Gathering classes info dynamically from a set of - * directories in path {@link #searchPath}, and statically from a set of jars, - * like {@link CachedJarsPackageManager}. - */ -public abstract class PathPackageManager extends CachedJarsPackageManager { - - public PyList searchPath; - - public PathPackageManager() { - this.searchPath = new PyList(); - } - - /** - * Helper for {@link #packageExists(java.lang.String,java.lang.String)}. - * Scans for package pkg.name the directories in path. - */ - protected boolean packageExists(PyList path, String pkg, String name) { - String child = pkg.replace('.', File.separatorChar) + File.separator - + name; - - for (int i = 0; i < path.__len__(); i++) { - String dir = imp.defaultEmptyPathDirectory(path.pyget(i).__str__().toString()); - - File f = new File(dir, child); - if (f.isDirectory() && imp.caseok(f, name, name.length())) { - /* - * Figure out if we have a directory a mixture of python and - * java or just an empty directory (which means Java) or a - * directory with only Python source (which means Python). - */ - PackageExistsFileFilter m = new PackageExistsFileFilter(); - f.listFiles(m); - boolean exists = m.packageExists(); - if (exists) { - Py.writeComment("import", "java package as '" - + f.getAbsolutePath() + "'"); - } - return exists; - } - } - return false; - } - - class PackageExistsFileFilter implements FilenameFilter { - private boolean java; - - private boolean python; - - public boolean accept(File dir, String name) { - if(name.endsWith(".py") || name.endsWith("$py.class") || name.endsWith("$_PyInner.class")) { - python = true; - }else if (name.endsWith(".class")) { - java = true; - } - return false; - } - - public boolean packageExists() { - if (this.python && !this.java) { - return false; - } - return true; - } - } - - /** - * Helper for {@link #doDir(PyJavaPackage,boolean,boolean)}. Scans for - * package jpkg content over the directories in path. Add to ret the founded - * classes/pkgs. Filter out classes using {@link #filterByName},{@link #filterByAccess}. - */ - protected void doDir(PyList path, PyList ret, PyJavaPackage jpkg, - boolean instantiate, boolean exclpkgs) { - String child = jpkg.__name__.replace('.', File.separatorChar); - - for (int i = 0; i < path.__len__(); i++) { - String dir = path.pyget(i).__str__().toString(); - if (dir.length() == 0) { - dir = null; - } - - File childFile = new File(dir, child); - - String[] list = childFile.list(); - if (list == null) { - continue; - } - - doList: for (int j = 0; j < list.length; j++) { - String jname = list[j]; - - File cand = new File(childFile, jname); - - int jlen = jname.length(); - - boolean pkgCand = false; - - if (cand.isDirectory()) { - if (!instantiate && exclpkgs) { - continue; - } - pkgCand = true; - } else { - if (!jname.endsWith(".class")) { - continue; - } - jlen -= 6; - } - - jname = jname.substring(0, jlen); - PyString name = new PyString(jname); - - if (filterByName(jname, pkgCand)) { - continue; - } - - // for opt maybe we should some hash-set for ret - if (jpkg.__dict__.has_key(name) || jpkg.clsSet.has_key(name) - || ret.__contains__(name)) { - continue; - } - - if (!Character.isJavaIdentifierStart(jname.charAt(0))) { - continue; - } - - for (int k = 1; k < jlen; k++) { - if (!Character.isJavaIdentifierPart(jname.charAt(k))) { - continue doList; - } - } - - if (!pkgCand) { - try { - int acc = checkAccess(new BufferedInputStream( - new FileInputStream(cand))); - if ((acc == -1) || filterByAccess(jname, acc)) { - continue; - } - } catch (IOException e) { - continue; - } - } - - if (instantiate) { - if (pkgCand) { - jpkg.addPackage(jname); - } else { - jpkg.addLazyClass(jname); - } - } - - ret.append(name); - - } - } - - } - - /** - * Add directory dir (if exists) to {@link #searchPath}. - */ - public void addDirectory(File dir) { - try { - if (dir.getPath().length() == 0) { - this.searchPath.append(Py.EmptyString); - } else { - this.searchPath.append(new PyString(dir.getCanonicalPath())); - } - } catch (IOException e) { - warning("skipping bad directory, '" + dir + "'"); - } - } - - // ??pending: - // Uses simply split and not a StringTokenizer+trim to adhere to - // sun jvm parsing of classpath. - // E.g. "a;" is parsed by sun jvm as a, ""; the latter is interpreted - // as cwd. jview trims and cwd is per default in classpath. - // The logic here should work for both(...). Need to distinguish? - // This code does not avoid duplicates in searchPath. - // Should cause no problem (?). - - /** - * Adds "classpath" entry. Calls {@link #addDirectory} if path refers to a - * dir, {@link #addJarToPackages(java.io.File, boolean)} with param cache - * true if path refers to a jar. - */ - public void addClassPath(String path) { - PyList paths = new PyString(path).split(java.io.File.pathSeparator); - - for (int i = 0; i < paths.__len__(); i++) { - String entry = paths.pyget(i).toString(); - if (entry.endsWith(".jar") || entry.endsWith(".zip")) { - addJarToPackages(new File(entry), true); - } else { - File dir = new File(entry); - if (entry.length() == 0 || dir.isDirectory()) { - addDirectory(dir); - } - } - } - } - - public PyList doDir(PyJavaPackage jpkg, boolean instantiate, - boolean exclpkgs) { - PyList basic = basicDoDir(jpkg, instantiate, exclpkgs); - PyList ret = new PyList(); - - doDir(this.searchPath, ret, jpkg, instantiate, exclpkgs); - - return merge(basic, ret); - } - - public boolean packageExists(String pkg, String name) { - return packageExists(this.searchPath, pkg, name); - } - -} Modified: branches/2.3/src/org/python/core/PyJavaClass.java =================================================================== --- branches/2.3/src/org/python/core/PyJavaClass.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/src/org/python/core/PyJavaClass.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -1,6 +1,8 @@ // Copyright (c) Corporation for National Research Initiatives package org.python.core; +import org.python.core.packagecache.PackageManager; + import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; Modified: branches/2.3/src/org/python/core/PyJavaPackage.java =================================================================== --- branches/2.3/src/org/python/core/PyJavaPackage.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/src/org/python/core/PyJavaPackage.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -3,6 +3,8 @@ package org.python.core; +import org.python.core.packagecache.PackageManager; + import java.util.StringTokenizer; /** Modified: branches/2.3/src/org/python/core/PySystemState.java =================================================================== --- branches/2.3/src/org/python/core/PySystemState.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/src/org/python/core/PySystemState.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -4,6 +4,9 @@ package org.python.core; +import org.python.core.packagecache.PackageManager; +import org.python.core.packagecache.SysPackageManager; + import java.io.File; import java.io.FileInputStream; import java.io.FilterInputStream; Deleted: branches/2.3/src/org/python/core/SysPackageManager.java =================================================================== --- branches/2.3/src/org/python/core/SysPackageManager.java 2007-05-16 19:47:04 UTC (rev 3231) +++ branches/2.3/src/org/python/core/SysPackageManager.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -1,162 +0,0 @@ -// Copyright (c) Corporation for National Research Initiatives -// Copyright 2000 Samuele Pedroni - -package org.python.core; - -import java.util.Properties; -import java.util.StringTokenizer; -import java.io.*; - -/** - * System package manager. Used by org.python.core.PySystemState. - */ -public class SysPackageManager extends PathPackageManager { - - protected void message(String msg) { - Py.writeMessage("*sys-package-mgr*", msg); - } - - protected void warning(String warn) { - Py.writeWarning("*sys-package-mgr*", warn); - } - - protected void comment(String msg) { - Py.writeComment("*sys-package-mgr*", msg); - } - - protected void debug(String msg) { - Py.writeDebug("*sys-package-mgr*", msg); - } - - public SysPackageManager(File cachedir, Properties registry) { - if (useCacheDir(cachedir)) { - initCache(); - findAllPackages(registry); - saveCache(); - } - } - - public void addJar(String jarfile, boolean cache) { - addJarToPackages(new File(jarfile), cache); - if (cache) { - saveCache(); - } - } - - public void addJarDir(String jdir, boolean cache) { - addJarDir(jdir, cache, cache); - } - - private void addJarDir(String jdir, boolean cache, boolean saveCache) { - File file = new File(jdir); - if (!file.isDirectory()) { - return; - } - String[] files = file.list(); - for (int i = 0; i < files.length; i++) { - String entry = files[i]; - if (entry.endsWith(".jar") || entry.endsWith(".zip")) { - addJarToPackages(new File(jdir, entry), cache); - } - } - if (saveCache) { - saveCache(); - } - } - - private void addJarPath(String path) { - StringTokenizer tok = new StringTokenizer(path, - java.io.File.pathSeparator); - while (tok.hasMoreTokens()) { - // ??pending: do jvms trim? how is interpreted entry=""? - String entry = tok.nextToken(); - addJarDir(entry, true, false); - } - } - - private void findAllPackages(Properties registry) { - String paths = registry.getProperty("python.packages.paths", - "java.class.path,sun.boot.class.path"); - String directories = registry.getProperty( - "python.packages.directories", "java.ext.dirs"); - String fakepath = registry - .getProperty("python.packages.fakepath", null); - StringTokenizer tok = new StringTokenizer(paths, ","); - while (tok.hasMoreTokens()) { - String entry = tok.nextToken().trim(); - String tmp = registry.getProperty(entry); - if (tmp == null) { - continue; - } - addClassPath(tmp); - } - - tok = new StringTokenizer(directories, ","); - while (tok.hasMoreTokens()) { - String entry = tok.nextToken().trim(); - String tmp = registry.getProperty(entry); - if (tmp == null) { - continue; - } - addJarPath(tmp); - } - - if (fakepath != null) { - addClassPath(fakepath); - } - } - - public void notifyPackageImport(String pkg, String name) { - if (pkg != null && pkg.length() > 0) { - name = pkg + '.' + name; - } - Py.writeComment("import", "'" + name + "' as java package"); - } - - public Class findClass(String pkg, String name) { - Class c = super.findClass(pkg, name); - if (c != null) { - Py.writeComment("import", "'" + name + "' as java class"); - } - return c; - } - - public Class findClass(String pkg, String name, String reason) { - if (pkg != null && pkg.length() > 0) { - name = pkg + '.' + name; - } - return Py.findClassEx(name, reason); - } - - public PyList doDir(PyJavaPackage jpkg, boolean instantiate, - boolean exclpkgs) { - PyList basic = basicDoDir(jpkg, instantiate, exclpkgs); - PyList ret = new PyList(); - - doDir(this.searchPath, ret, jpkg, instantiate, exclpkgs); - - PySystemState system = Py.getSystemState(); - - if (system.getClassLoader() == null) { - doDir(system.path, ret, jpkg, instantiate, exclpkgs); - } - - return merge(basic, ret); - } - - public boolean packageExists(String pkg, String name) { - if (packageExists(this.searchPath, pkg, name)) { - return true; - } - - PySystemState system = Py.getSystemState(); - - if (system.getClassLoader() == null - && packageExists(Py.getSystemState().path, pkg, name)) { - return true; - } - - return false; - } - -} Copied: branches/2.3/src/org/python/core/packagecache/CachedJarsPackageManager.java (from rev 3231, branches/2.3/src/org/python/core/CachedJarsPackageManager.java) =================================================================== --- branches/2.3/src/org/python/core/packagecache/CachedJarsPackageManager.java (rev 0) +++ branches/2.3/src/org/python/core/packagecache/CachedJarsPackageManager.java 2007-05-18 00:30:12 UTC (rev 3232) @@ -0,0 +1,597 @@ +// Copyright (c) Corporation for National Research Initiatives +// Copyright 2000 Samuele Pedroni + +package org.python.core.packagecache; + +import org.python.core.Options; + +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.EOFException; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Modifier; +import java.net.URL; +import java.net.URLConnection; +import java.security.AccessControlException; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +/** + * Abstract package manager that gathers info about statically known classes + * from a set of jars. This info can be eventually cached. Off-the-shelf this + * class offers a local file-system based cache impl. + */ +public abstract class CachedJarsPackageManager extends PackageManager { + + /** + * Message log method - hook. This default impl does nothing. + * + * @param msg message text + */ + protected void message(String msg) { + } + + /** + * Warning log method - hook. This default impl does nothing. + * + * @param warn warning text + */ + protected void warning(String warn) { + } + + /** + * Comment log method - hook. This default impl does nothing. + * + * @param msg message text + */ + protected void comment(String msg) { + } + + /** + * Debug log method - hook. This default impl does nothing. + * + * @param msg message text + */ + protected void debug(String msg) { + } + + /** + * Filter class/pkg by name helper method - hook. The default impl. is used + * by {@link #addJarToPackages} in order to filter out classes whose name + * contains '$' (e.g. inner classes,...). Should be used or overriden by + * derived classes too. Also to be used in {@link #doDir}. + * + * @param name class/pkg name + * @param pkg if true, name refers to a pkg + * @return true if name must be filtered out + */ + protected boolean filterByName(String name, boolean pkg) { + return name.indexOf('$') != -1; + } + + /** + * Filter class by access perms helper method - hook. The default impl. is + * used by {@link #addJarToPackages} in order to filter out non-public + * classes. Should be used or overriden by derived classes too. Also to be + * used in {@link #doDir}. Access perms can be read with + * {@link #checkAccess}. + * + * @param name class name + * @param acc class access permissions as int + * @return true if name must be filtered out + */ + protected boolean filterByAccess(String name, int acc) { + return (acc & Modifier.PUBLIC) != Modifier.PUBLIC; + } + + private boolean indexModified; + + private Hashtable jarfiles; + + private static String vectorToString(Vector vec) { + int n = vec.size(); + StringBuffer ret = new StringBuffer(); + for (int i = 0; i < n; i++) { + ret.append((String) vec.elementAt(i)); + if (i < n - 1) { + ret.append(","); + } + } + return ret.toString(); + } + + // Add a single class from zipFile to zipPackages + // Only add valid, public classes + private void addZipEntry(Hashtable zipPackages, ZipEntry entry, + ZipInputStream zip) throws IOException { + String name = entry.getName(); + // System.err.println("entry: "+name); + if (!name.endsWith(".class")) { + return; + } + + char sep = '/'; + int breakPoint = name.lastIndexOf(sep); + if (breakPoint == -1) { + breakPoint = name.lastIndexOf('\\'); + sep = '\\'; + } + + String packageName; + if (breakPoint == -1) { + packageName = ""; + } else { + packageName = name.substring(0, breakPoint).replace(sep, '.'); + } + + String className = name.substring(breakPoint + 1, name.length() - 6); + + if (filterByName(className, false)) { + return; + } + + Vector[] vec = (Vector[]) zipPackages.get(packageName); + if (vec == null) { + vec = new Vector[] { new Vector(), new Vector() }; + zipPackages.put(packageName, vec); + } + int access = checkAccess(zip); + if ((access != -1) && !filterByAccess(name, access)) { + vec[0].addElement(className); + } else { + vec[1].addElement(className); + } + } + + // Extract all of the packages in a single jarfile + private Hashtable getZipPackages(InputStream jarin) throws IOException { + Hashtable zipPackages = new Hashtable(); + + ZipInputStream zip = new ZipInputStream(jarin); + + ZipEntry entry; + while ((entry = zip.getNextEntry()) != null) { + addZipEntry(zipPackages, entry, zip); + zip.closeEntry(); + } + + // Turn each vector into a comma-separated String + for (Enumeration e = zipPackages.keys(); e.hasMoreElements();) { + Object key = e.nextElement(); + Vector[] vec = (Vector[]) zipPackages.get(key); + String classes = vectorToString(vec[0]); + if (vec[1].size() > 0) { + classes += '@' + vectorToString(vec[1]); + } + zipPackages.put(key, classes); + } + + return zipPackages; + } + + /** + * Gathers classes info from jar specified by jarurl URL. Eventually just + * using previously cached info. Eventually updated info is not cached. + * Persistent cache storage access goes through inOpenCacheFile() and + * outCreateCacheFile(). + */ + public void addJarToPackages(java.net.URL jarurl) { + addJarToPackages(jarurl, null, false); + } + + /** + * Gathers classes info from jar specified by jarurl URL. Eventually just + * using previously cached info. Eventually updated info is (re-)cached if + * param cache is true. Persistent cache storage access goes through + * inOpenCacheFile() and outCreateCacheFile(). + */ + public void addJarToPackages(URL jarurl, boolean cache) { + addJarToPackages(jarurl, null, cache); + } + + /** + * Gathers classes info from jar specified by File jarfile. Eventually just + * using previously cached info. Eventually updated info is not cached. + * Persistent cache storage access goes through inOpenCacheFile() and + * outCreateCacheFile(). + */ + public void addJarToPackages(File jarfile) { + addJarToPackages(null, jarfile, false); + } + + /** + * Gathers classes info from jar specified by File jarfile. Eventually just + * using previously cached info. Eventually updated info is (re-)cached if + * param cache is true. Persistent cache storage access goes through + * inOpenCacheFile() and outCreateCacheFile(). + */ + public void addJarToPackages(File jarfile, boolean cache) { + addJarToPackages(null, jarfile, cache); + } + + private void addJarToPackages(URL jarurl, File jarfile, boolean cache) { + try { + boolean caching = this.jarfiles != null; + + URLConnection jarconn = null; + boolean localfile = true; + + if (jarfile == null) { + jarconn = jarurl.openConnection(); + // This is necessary because 'file:' url-connections + // return always 0 through getLastModified (bug?). + // And in order to handle localfiles (from urls too) + // uniformly. + if (jarconn.getURL().getProtocol().equals("file")) { + // ??pending: need to use java2 URLDecoder.decode? + String jarfilename = jarurl.getFile(); + jarfilename = jarfilename.replace('/', File.separatorChar); + jarfile = new File(jarfilename); + } else { + localfile = false; + } + } + + if (localfile && !jarfile.exists()) { + return; + } + + Hashtable zipPackages = null; + + long mtime = 0; + String jarcanon = null; + JarXEntry entry = null; + boolean brandNew = false; + + if (caching) { + + if (localfile) { + mtime = jarfile.lastModified(); + jarcanon = jarfile.getCanonicalPath(); + } else { + mtime = jarconn.getLastModified(); + jarcanon = jarurl.toString(); + } + + entry = (JarXEntry) this.jarfiles.get(jarcanon); + + if ((entry == null || !(new File(entry.cachefile).exists())) + && cache) { + message("processing new jar, '" + jarcanon + "'"); + + String jarname; + if (localfile) { + jarname = jarfile.getName(); + } else { + jarname = jarurl.getFile(); + int slash = jarname.lastIndexOf('/'); + if (slash != -1) + jarname = jarname.substring(slash + 1); + } + jarname = jarname.substring(0, jarname.length() - 4); + + entry = new JarXEntry(jarname); + this.jarfiles.put(jarcanon, entry); + + brandNew = true; + } + + if (mtime != 0 && entry != null && entry.mtime == mtime) { + zipPackages = readCacheFile(entry, jarcanon); + } + + } + + if (zipPackages == null) { + caching = caching && cache; + + if (caching) { + this.indexModified = true; + if (entry.mtime != 0) { + message("processing modified jar, '" + jarcanon + "'"); + } + entry.mtime = mtime; + } + + InputStream jarin; + if (jarconn == null) { + jarin = new BufferedInputStream( + new FileInputStream(jarfile)); + } else { + jarin = jarconn.getInputStream(); + } + + zipPackages = getZipPackages(jarin); + + if (caching) { + writeCacheFile(entry, jarcanon, zipPackages, brandNew); + } + } + + addPackages(zipPackages, jarcanon); + } catch (IOException ioe) { + // silently skip any bad directories + warning("skipping bad jar, '" + + (jarfile != null ? jarfile.toString() : jarurl.toString()) + + "'"); + } + + } + + private void addPackages(Hashtable zipPackages, String jarfile) { + for (Enumeration e = zipPackages.keys(); e.hasMoreElements();) { + String pkg = (String) e.nextElement(); + String classes = (String) zipPackages.get(pkg); + + int idx = classes.indexOf('@'); + if (idx >= 0 && Options.respectJavaAccessibility) { + classes = classes.substring(0, idx); + } + + makeJavaPackage(pkg, classes, jarfile); + } + } + + // Read in cache file storing package info for a single .jar + // Return null and delete this cachefile if it is invalid + private Hashtable readCacheFile(JarXEntry entry, String jarcanon) { + String cachefile = entry.cachefile; + long mtime = entry.mtime; + + debug("reading cache, '" + jarcanon + "'"); + + try { + DataInputStream istream = inOpenCacheFile(cachefile); + String old_jarcanon = istream.readUTF(); + long old_mtime = istream.readLong(); + if ((!old_jarcanon.equals(jarcanon)) || (old_mtime != mtime)) { + comment("invalid cache file: " + cachefile + ", " + jarcanon + + ":" + old_jarcanon + ", " + mtime + ":" + old_mtime); + deleteCacheFile(cachefile); + return null; + } + Hashtable packs = new Hashtable(); + try { + while (true) { + String packageName = istream.readUTF(); + String classes = istream.readUTF(); + packs.put(packageName, classes); + } + } catch (EOFException eof) { + ; + } + istream.close(); + + return packs; + } catch (IOException ioe) { + // if (cachefile.exists()) cachefile.delete(); + return null; + } + } + + // Write a cache file storing package info for a single .jar + private void writeCacheFile(JarXEntry entry, String jarcanon, + Hashtable zipPackages, boolean brandNew) { + try { + DataOutputStream ostream = outCreateCacheFile(entry, brandNew); + ostream.writeUTF(jarcanon); + ostream.writeLong(entry.mtime); + comment("rewriting cachefile for '" + jarcanon + "'"); + + for (Enumeration e = zipPackages.keys(); e.hasMoreElements();) { + String packageName = (String) e.nextElem... [truncated message content] |