Index: src/org/python/core/packagecache/CachedJarsPackageManager.java =================================================================== --- src/org/python/core/packagecache/CachedJarsPackageManager.java (revision 7024) +++ src/org/python/core/packagecache/CachedJarsPackageManager.java (working copy) @@ -397,7 +397,10 @@ for (Entry kv : zipPackages.entrySet()) { String classes = kv.getValue(); ostream.writeUTF(kv.getKey()); - ostream.writeUTF(classes); + // Make sure each package is not larger than 64k + for (String part : splitString(classes, 65535)) { + ostream.writeUTF(part); + } } ostream.close(); } catch (IOException ioe) { @@ -406,6 +409,35 @@ } /** + * Split up a string into several chunks based on a certain size + * + * The writeCacheFile method will use the writeUTF method on a + * DataOutputStream which only allows writing 64k chunks, so use + * this utility method to split it up + * + * @param str - The string to split up into chunks + * @param maxLength - The max size a string should be + * @return - An array of strings, each of which will not be larger than maxLength + */ + protected static String[] splitString(String str, int maxLength) { + if (str == null) { + return null; + } + + int len = str.length(); + if (len <= maxLength) { + return new String[] {str}; + } + + int chunkCount = (int) Math.ceil((float) len / maxLength); + String[] chunks = new String[chunkCount]; + for (int i = 0; i < chunkCount; i++) { + chunks[i] = str.substring(i * maxLength, Math.min(i * maxLength + maxLength, len)); + } + return chunks; + } + + /** * Initializes cache. Eventually reads back cache index. Index persistent * storage is accessed through inOpenIndex(). */ Index: tests/java/org/python/core/packagecache/CachedJarsOver64kTest.java =================================================================== --- tests/java/org/python/core/packagecache/CachedJarsOver64kTest.java (revision 0) +++ tests/java/org/python/core/packagecache/CachedJarsOver64kTest.java (revision 0) @@ -0,0 +1,63 @@ +package org.python.core.packagecache; + +import java.io.File; + +import org.python.core.PyJavaPackage; +import org.python.core.PyList; +import org.python.core.packagecache.CachedJarsPackageManager; + +import junit.framework.TestCase; + +public class CachedJarsOver64kTest extends TestCase { + + private TestCachePackageManager packageManager = null; + + private File jarFile = null; + + @Override + public void setUp() { + // Find the jar to use + packageManager = new TestCachePackageManager(new File(System + .getProperty("java.io.tmpdir"))); + jarFile = new File(System.getProperty("python.test.source.dir") + + "/org/python/core/packagecache", "vim25.jar"); + } + + public void testJarOver64k() { + assertTrue(jarFile.exists()); + packageManager.addJarToPackages(jarFile, true); + assertFalse(packageManager.failed); + } + + private class TestCachePackageManager extends CachedJarsPackageManager { + + public boolean failed; + + public TestCachePackageManager(File cachedir) { + if (useCacheDir(cachedir)){ + initCache(); + } + } + + @Override + protected void warning(String msg){ + if (msg.contains("can't write cache file for")) { + failed = true; + } + } + + @Override + public void addDirectory(File dir) {} + @Override + public void addJar(String jarfile, boolean cache) {} + @Override + public void addJarDir(String dir, boolean cache) {} + @Override + public PyList doDir(PyJavaPackage jpkg, boolean instantiate, boolean exclpkgs) { + return null; + } + @Override + public Class findClass(String pkg, String name, String reason) { return null; } + @Override + public boolean packageExists(String pkg, String name) { return false; } + } +}