You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by sj...@apache.org on 2009/02/26 12:32:36 UTC

svn commit: r748097 - /harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java

Author: sjanuary
Date: Thu Feb 26 11:32:35 2009
New Revision: 748097

URL: http://svn.apache.org/viewvc?rev=748097&view=rev
Log:
Pack200 - better implementation of segment limit option (now compatible with RI)

Modified:
    harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java

Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java?rev=748097&r1=748096&r2=748097&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java Thu Feb 26 11:32:35 2009
@@ -76,6 +76,8 @@
         if (manifest != null) {
             ByteArrayOutputStream baos = new ByteArrayOutputStream();
             manifest.write(baos);
+            // TODO: Need to add this in some cases, but I'm not sure which at the moment
+//            files.add(new File("META-INF", new byte[0], 0));
             files.add(new File("META-INF/MANIFEST.MF", baos.toByteArray(), 0));
         }
         if (inputStream != null) {
@@ -91,14 +93,11 @@
                         classes = new ArrayList();
                         files = new ArrayList();
                         currentSegmentSize = 0;
+                        addJarEntry(jarEntry, new BufferedInputStream(inputStream), classes, files);
+                        currentSegmentSize = 0; // ignore the size of the first entry for compatibility with the RI
                     }
-                    if (!addJarEntry(jarEntry, new BufferedInputStream(
-                            inputStream), classes, files)) {
-                        throw new Pack200Exception(
-                                "Segment limit is too small for the files you are trying to pack");
-                    }
-                } else if (segmentLimit == 0) {
-                    // create a new segment for each class
+                } else if (segmentLimit == 0 && estimateSize(jarEntry) > 0) {
+                    // create a new segment for each class unless size = 0
                     new Segment().pack(classes, files, outputStream, stripDebug);
                     classes = new ArrayList();
                     files = new ArrayList();
@@ -117,12 +116,11 @@
                     classes = new ArrayList();
                     files = new ArrayList();
                     currentSegmentSize = 0;
-                    if (!addJarEntry(jarEntry, new BufferedInputStream(jarFile
-                            .getInputStream(jarEntry)), classes, files)) {
-                        throw new Pack200Exception("Segment limit is too small");
-                    }
-                } else if (segmentLimit == 0) {
-                    // create a new segment for each class
+                    addJarEntry(jarEntry, new BufferedInputStream(jarFile
+                            .getInputStream(jarEntry)), classes, files);
+                    currentSegmentSize = 0; // ignore the size of the first entry for compatibility with the RI
+                } else if (segmentLimit == 0 && estimateSize(jarEntry) > 0) {
+                    // create a new segment for each class unless size = 0
                     new Segment().pack(classes, files, outputStream, stripDebug);
                     classes = new ArrayList();
                     files = new ArrayList();
@@ -140,23 +138,19 @@
         String name = jarEntry.getName();
         long size = jarEntry.getSize();
         if (size > Integer.MAX_VALUE) {
-            throw new RuntimeException("Large Class!");
+            throw new RuntimeException("Large Class!"); // TODO: Should probably allow this
         } else if (size < 0) {
             throw new RuntimeException("Error: size for " + name + " is " + size);
         }
         if(segmentLimit != -1 && segmentLimit != 0) {
             // -1 is a special case where only one segment is created and
-            // 0 is a special case where one segment is created for each file
-
-            // This is fairly close to the RI, but still a little smaller as the exact sum is not given in the spec.
-            int packedSize  = (int)size // size of the file
-                    + 24 // 3x8 bytes for 3 longs in file_modtime, file_options and file_size bands
-                    + (name.endsWith(".class") ? 1 : name.getBytes().length); // size of entry in file_name band
+            // 0 is a special case where one segment is created for each file except for files in "META-INF"
 
-            if (packedSize + currentSegmentSize > segmentLimit) {
-                return false;
+            long packedSize = estimateSize(jarEntry);
+            if (packedSize + currentSegmentSize > segmentLimit && currentSegmentSize > 0) {
+                return false; // don't add this JarEntry to the current segment
             } else {
-                currentSegmentSize += packedSize;
+                currentSegmentSize += packedSize; // do add this JarEntry
             }
         }
         byte[] bytes = new byte[(int) size];
@@ -173,6 +167,20 @@
         return true;
     }
 
+    private long estimateSize(JarEntry jarEntry) {
+        // The heuristic used here is for compatibility with the RI and should not be changed
+        String name = jarEntry.getName();
+        if(name.startsWith("META-INF") || name.startsWith("/META-INF")) {
+            return 0;
+        } else {
+            long fileSize = jarEntry.getSize();
+            if(fileSize < 0) {
+                fileSize = 0;
+            }
+            return name.length() + fileSize + 5;
+        }
+    }
+
     static class File {
 
         private final String name;
@@ -196,6 +204,10 @@
         public long getModtime() {
             return modtime;
         }
+
+        public String toString() {
+            return name;
+        }
     }
 
 }