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/01/14 15:50:52 UTC
svn commit: r734410 -
/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java
Author: sjanuary
Date: Wed Jan 14 06:50:41 2009
New Revision: 734410
URL: http://svn.apache.org/viewvc?rev=734410&view=rev
Log:
Pack200 - Initial implementation for packing large archives as multiple segments
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=734410&r1=734409&r2=734410&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 Wed Jan 14 06:50:41 2009
@@ -33,7 +33,6 @@
import org.objectweb.asm.ClassReader;
-
/**
*
*/
@@ -42,10 +41,13 @@
private final JarInputStream inputStream;
private final OutputStream outputStream;
private JarFile jarFile;
+ private final long segmentLimit = 1000000;
+ private long currentSegmentSize;
- public Archive(JarInputStream inputStream, OutputStream outputStream, boolean gzip) throws IOException {
+ public Archive(JarInputStream inputStream, OutputStream outputStream,
+ boolean gzip) throws IOException {
this.inputStream = inputStream;
- if(gzip) {
+ if (gzip) {
outputStream = new GZIPOutputStream(outputStream);
}
this.outputStream = new BufferedOutputStream(outputStream);
@@ -60,49 +62,89 @@
public void pack() throws Pack200Exception, IOException {
List classes = new ArrayList();
List files = new ArrayList();
- List classNames = new ArrayList();
- List classModtimes = new ArrayList();
- Manifest manifest = jarFile != null ? jarFile.getManifest() : inputStream.getManifest();
- if(manifest!= null) {
+ Manifest manifest = jarFile != null ? jarFile.getManifest()
+ : inputStream.getManifest();
+ if (manifest != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
manifest.write(baos);
files.add(new File("META-INF/MANIFEST.MF", baos.toByteArray(), 0));
}
- if(inputStream != null) {
- while(inputStream.available() > 0) {
+ if (inputStream != null) {
+ while (inputStream.available() > 0) {
JarEntry jarEntry = inputStream.getNextJarEntry();
- if(jarEntry != null) {
- addJarEntry(jarEntry, new BufferedInputStream(inputStream), classes, files);
+ if (jarEntry != null) {
+ boolean added = addJarEntry(jarEntry,
+ new BufferedInputStream(inputStream), classes,
+ files);
+ if (!added) { // not added because segment has reached
+ // maximum size
+ new Segment().pack(classes, files, outputStream);
+ classes = new ArrayList();
+ files = new ArrayList();
+ currentSegmentSize = 0;
+ if (!addJarEntry(jarEntry, new BufferedInputStream(
+ inputStream), classes, files)) {
+ throw new Pack200Exception(
+ "Segment limit is too small");
+ }
+ }
}
}
} else {
Enumeration jarEntries = jarFile.entries();
- while(jarEntries.hasMoreElements()) {
+ while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = (JarEntry) jarEntries.nextElement();
- addJarEntry(jarEntry, new BufferedInputStream(jarFile.getInputStream(jarEntry)), classes, files);
+ boolean added = addJarEntry(jarEntry, new BufferedInputStream(
+ jarFile.getInputStream(jarEntry)), classes, files);
+ if (!added) { // not added because segment has reached maximum
+ // size
+ new Segment().pack(classes, files, outputStream);
+ 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");
+ }
+ }
}
}
- new Segment().pack(classes, files, outputStream); // TODO: Multiple segments
+ if(classes.size() > 0 || files.size() > 0) {
+ new Segment().pack(classes, files, outputStream);
+ }
outputStream.close();
}
- private void addJarEntry(JarEntry jarEntry, InputStream stream, List javaClasses, List files) throws IOException, Pack200Exception {
+ private boolean addJarEntry(JarEntry jarEntry, InputStream stream,
+ List javaClasses, List files) throws IOException, Pack200Exception {
String name = jarEntry.getName();
long size = jarEntry.getSize();
if (size > Integer.MAX_VALUE) {
throw new RuntimeException("Large Class!");
}
- byte[] bytes = new byte[(int)size];
+ int packedSize = name.endsWith(".class") ? estimatePackedSize(size)
+ : (int) size;
+ if (packedSize + currentSegmentSize > segmentLimit) {
+ return false;
+ } else {
+ currentSegmentSize += packedSize;
+ }
+ byte[] bytes = new byte[(int) size];
int read = stream.read(bytes);
- if(read != size) {
+ if (read != size) {
throw new RuntimeException("Error reading from stream");
}
- if(name.endsWith(".class")) {
+ if (name.endsWith(".class")) {
ClassReader classParser = new Pack200ClassReader(bytes);
javaClasses.add(classParser);
bytes = new byte[0];
}
files.add(new File(name, bytes, jarEntry.getTime()));
+ return true;
+ }
+
+ private int estimatePackedSize(long size) {
+ return (int) size; // TODO: try to match the RI as closely as possible
}
static class File {