Index: src/main/java/org/apache/harmony/unpack200/Segment.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/Segment.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/Segment.java (working copy) @@ -17,7 +17,7 @@ package org.apache.harmony.unpack200; import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; +import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; @@ -97,6 +97,12 @@ private PrintWriter logStream; + private byte[][] classFilesContents; + + private boolean[] fileDeflate; + + private boolean[] fileIsClass; + private ClassFile buildClassFile(int classNum) throws Pack200Exception { ClassFile classFile = new ClassFile(); classFile.major = header.getDefaultClassMajorVersion(); // TODO If @@ -353,8 +359,8 @@ } /** - * This performs the actual work of parsing against a non-static instance of - * Segment. + * This performs reading the data from the stream into non-static instance of + * Segment. After the completion of this method stream can be freed. * * @param in * the input stream to read from @@ -364,25 +370,91 @@ * if a problem occurs with an unexpected value or unsupported * codec */ - private void parseSegment(InputStream in) throws IOException, + private void readSegment(InputStream in) throws IOException, Pack200Exception { log(LOG_LEVEL_VERBOSE, "-------"); header = new SegmentHeader(this); - header.unpack(in); + header.read(in); cpBands = new CpBands(this); - cpBands.unpack(in); + cpBands.read(in); attrDefinitionBands = new AttrDefinitionBands(this); - attrDefinitionBands.unpack(in); + attrDefinitionBands.read(in); icBands = new IcBands(this); - icBands.unpack(in); + icBands.read(in); classBands = new ClassBands(this); - classBands.unpack(in); + classBands.read(in); bcBands = new BcBands(this); - bcBands.unpack(in); + bcBands.read(in); fileBands = new FileBands(this); - fileBands.unpack(in); + fileBands.read(in); + + fileBands.processFileBits(); } + /** + * This performs the actual work of parsing against a non-static instance of + * Segment. This method is intended to run concurrently for multiple segments. + * + * @throws IOException + * if a problem occurs during reading from the underlying stream + * @throws Pack200Exception + * if a problem occurs with an unexpected value or unsupported + * codec + */ + private void parseSegment() throws IOException, Pack200Exception { + + header.unpack(); + cpBands.unpack(); + attrDefinitionBands.unpack(); + icBands.unpack(); + classBands.unpack(); + bcBands.unpack(); + fileBands.unpack(); + + int classNum = 0; + int numberOfFiles = header.getNumberOfFiles(); + String[] fileName = fileBands.getFileName(); + long[] fileOptions = fileBands.getFileOptions(); + SegmentOptions options = header.getOptions(); + + classFilesContents = new byte[numberOfFiles][]; + fileDeflate = new boolean[numberOfFiles]; + fileIsClass = new boolean[numberOfFiles]; + + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(bos); + + for (int i = 0; i < numberOfFiles; i++) { + String name = fileName[i]; + + boolean nameIsEmpty = (name == null) || name.equals(""); + boolean isClass = (fileOptions[i] & 2) == 2 || nameIsEmpty; + if (isClass && nameIsEmpty) { + name = cpBands.getCpClass()[classBands.getClassThisInts()[classNum]] + ".class"; + fileName[i] = name; + } + + if (!overrideDeflateHint) { + fileDeflate[i] = (fileOptions[i] & 1) == 1 || options.shouldDeflate(); + } else { + fileDeflate[i] = deflateHint; + } + + fileIsClass[i] = isClass; + + if (isClass) { + ClassFile classFile = buildClassFile(classNum); + classFile.write(dos); + dos.flush(); + + classFilesContents[classNum] = bos.toByteArray(); + bos.reset(); + + classNum++; + } + } + } + /** * Unpacks a packed stream (either .pack. or .pack.gz) into a corresponding * JarOuputStream. @@ -394,9 +466,25 @@ */ public void unpack(InputStream in, JarOutputStream out) throws IOException, Pack200Exception { + unpackRead(in); + unpackProcess(); + unpackWrite(out); + } + + /* + * Package-private accessors for unpacking stages + */ + void unpackRead(InputStream in) throws IOException, Pack200Exception { if (!in.markSupported()) in = new BufferedInputStream(in); - parseSegment(in); + readSegment(in); + } + + void unpackProcess() throws IOException, Pack200Exception { + parseSegment(); + } + + void unpackWrite(JarOutputStream out) throws IOException, Pack200Exception { writeJar(out); } @@ -415,13 +503,9 @@ * if an error occurs while processing data */ public void writeJar(JarOutputStream out) throws IOException, - Pack200Exception { - fileBands.processFileBits(); - BufferedOutputStream buffer = new BufferedOutputStream(out); - DataOutputStream dos = new DataOutputStream(buffer); + Pack200Exception { String[] fileName = fileBands.getFileName(); - long[] fileModtime = fileBands.getFileModtime(); - long[] fileOptions = fileBands.getFileOptions(); + long[] fileModtime = fileBands.getFileModtime(); long[] fileSize = fileBands.getFileSize(); byte[][] fileBits = fileBands.getFileBits(); @@ -430,43 +514,31 @@ int classNum = 0; int numberOfFiles = header.getNumberOfFiles(); long archiveModtime = header.getArchiveModtime(); - SegmentOptions options = header.getOptions(); + for (int i = 0; i < numberOfFiles; i++) { String name = fileName[i]; long modtime = archiveModtime + fileModtime[i]; - boolean deflate = (fileOptions[i] & 1) == 1 - || options.shouldDeflate(); - if (overrideDeflateHint) { // Overridden by a command line argument - deflate = deflateHint; - } - boolean isClass = (fileOptions[i] & 2) == 2 || name == null - || name.equals(""); - if (isClass) { - // pull from headers - if (name == null || name.equals("")) - name = cpBands.getCpClass()[classBands.getClassThisInts()[classNum]] + ".class"; - } + boolean deflate = fileDeflate[i]; + JarEntry entry = new JarEntry(name); if (deflate) entry.setMethod(ZipEntry.DEFLATED); entry.setTime(modtime); out.putNextEntry(entry); - if (isClass) { + if (fileIsClass[i]) { // write to dos - ClassFile classFile = buildClassFile(classNum); - classFile.write(dos); - dos.flush(); - classNum++; + entry.setSize(classFilesContents[classNum].length); + out.write(classFilesContents[classNum]); + classNum++; } else { long size = fileSize[i]; entry.setSize(size); - // TODO pull from in + byte[] data = fileBits[i]; out.write(data); } } - dos.flush(); } public SegmentConstantPool getConstantPool() { Index: src/main/java/org/apache/harmony/unpack200/IcBands.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/IcBands.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/IcBands.java (working copy) @@ -52,7 +52,7 @@ * * @see org.apache.harmony.unpack200.BandSet#unpack(java.io.InputStream) */ - public void unpack(InputStream in) throws IOException, Pack200Exception { + public void read(InputStream in) throws IOException, Pack200Exception { // Read IC bands int innerClassCount = header.getInnerClassCount(); int[] icThisClassInts = decodeBandInt("ic_this_class", in, @@ -104,6 +104,11 @@ } } + public void unpack() throws IOException, Pack200Exception { + + } + + public IcTuple[] getIcTuples() { return icAll; } @@ -205,4 +210,5 @@ return orderedRelevantTuples; } + } \ No newline at end of file Index: src/main/java/org/apache/harmony/unpack200/CpBands.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/CpBands.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/CpBands.java (working copy) @@ -103,7 +103,7 @@ super(segment); } - public void unpack(InputStream in) throws IOException, Pack200Exception { + public void read(InputStream in) throws IOException, Pack200Exception { parseCpUtf8(in); parseCpInt(in); parseCpFloat(in); @@ -130,6 +130,10 @@ imethodOffset = methodOffset + cpMethodClass.length; } + public void unpack() { + + } + /** * Parses the constant pool class names, using {@link #cpClassCount} to * populate {@link #cpClass} from {@link #cpUTF8}. Index: src/main/java/org/apache/harmony/unpack200/SegmentHeader.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/SegmentHeader.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/SegmentHeader.java (working copy) @@ -94,7 +94,7 @@ this.segment = segment; } - public void unpack(InputStream in) throws IOException, Pack200Exception, + public void read(InputStream in) throws IOException, Pack200Exception, Error, Pack200Exception { long word[] = decodeScalar("archive_magic_word", in, Codec.BYTE1, magic.length); @@ -118,6 +118,10 @@ setBandHeadersData(bandHeaders); } } + + public void unpack() { + + } /** * Sets the minor version of this archive Index: src/main/java/org/apache/harmony/unpack200/ClassBands.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/ClassBands.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/ClassBands.java (working copy) @@ -133,7 +133,7 @@ * * @see org.apache.harmony.unpack200.BandSet#unpack(java.io.InputStream) */ - public void unpack(InputStream in) throws IOException, Pack200Exception { + public void read(InputStream in) throws IOException, Pack200Exception { int classCount = header.getClassCount(); classThisInts = decodeBandInt("class_this", in, Codec.DELTA5, classCount); classThis = getReferences(classThisInts, cpBands.getCpClass()); @@ -154,6 +154,10 @@ } + public void unpack() { + + } + private void parseFieldBands(InputStream in) throws IOException, Pack200Exception { fieldDescrInts = decodeBandInt("field_descr", in, Codec.DELTA5, Index: src/main/java/org/apache/harmony/unpack200/BandSet.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/BandSet.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/BandSet.java (working copy) @@ -43,9 +43,16 @@ */ public abstract class BandSet { - public abstract void unpack(InputStream inputStream) throws IOException, + public abstract void read(InputStream inputStream) throws IOException, Pack200Exception; + public abstract void unpack() throws IOException, Pack200Exception; + + public void unpack(InputStream in) throws IOException, Pack200Exception { + read(in); + unpack(); + } + protected Segment segment; protected SegmentHeader header; Index: src/main/java/org/apache/harmony/unpack200/NewAttributeBands.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/NewAttributeBands.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/NewAttributeBands.java (working copy) @@ -64,7 +64,7 @@ * * @see org.apache.harmony.unpack200.BandSet#unpack(java.io.InputStream) */ - public void unpack(InputStream in) throws IOException, Pack200Exception { + public void read(InputStream in) throws IOException, Pack200Exception { // does nothing - use parseAttributes instead } @@ -954,4 +954,9 @@ } } + public void unpack() throws IOException, Pack200Exception { + + + } + } \ No newline at end of file Index: src/main/java/org/apache/harmony/unpack200/FileBands.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/FileBands.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/FileBands.java (working copy) @@ -58,7 +58,7 @@ * * @see org.apache.harmony.unpack200.BandSet#unpack(java.io.InputStream) */ - public void unpack(InputStream in) throws IOException, Pack200Exception { + public void read(InputStream in) throws IOException, Pack200Exception { int numberOfFiles = header.getNumberOfFiles(); SegmentOptions options = header.getOptions(); @@ -99,6 +99,10 @@ } } } + + public void unpack() { + + } public byte[][] getFileBits() { return fileBits; Index: src/main/java/org/apache/harmony/unpack200/AttrDefinitionBands.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/AttrDefinitionBands.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/AttrDefinitionBands.java (working copy) @@ -48,7 +48,7 @@ * * @see org.apache.harmony.unpack200.BandSet#unpack(java.io.InputStream) */ - public void unpack(InputStream in) throws IOException, Pack200Exception { + public void read(InputStream in) throws IOException, Pack200Exception { int attributeDefinitionCount = header.getAttributeDefinitionCount(); attributeDefinitionHeader = decodeBandInt("attr_definition_headers", in, Codec.BYTE1, attributeDefinitionCount); @@ -56,7 +56,7 @@ Codec.UNSIGNED5, attributeDefinitionCount, cpUTF8); attributeDefinitionLayout = parseReferences("attr_definition_layout", in, Codec.UNSIGNED5, attributeDefinitionCount, cpUTF8); - + attributeDefinitionMap = new AttributeLayoutMap(); int overflowIndex = 32; @@ -78,6 +78,10 @@ attributeDefinitionMap.checkMap(); } + public void unpack() throws Pack200Exception, IOException { + + } + public AttributeLayoutMap getAttributeDefinitionMap() { return attributeDefinitionMap; } Index: src/main/java/org/apache/harmony/unpack200/BcBands.java =================================================================== --- src/main/java/org/apache/harmony/unpack200/BcBands.java (revision 677594) +++ src/main/java/org/apache/harmony/unpack200/BcBands.java (working copy) @@ -70,6 +70,8 @@ private int[] bcEscSize; private int[][] bcEscByte; + private List wideByteCodes; + /** * @param segment */ @@ -82,17 +84,12 @@ * * @see org.apache.harmony.unpack200.BandSet#unpack(java.io.InputStream) */ - public void unpack(InputStream in) throws IOException, Pack200Exception { + public void read(InputStream in) throws IOException, Pack200Exception { AttributeLayoutMap attributeDefinitionMap = segment .getAttrDefinitionBands().getAttributeDefinitionMap(); int classCount = header.getClassCount(); long[][] methodFlags = segment.getClassBands().getMethodFlags(); - int[] codeMaxNALocals = segment.getClassBands().getCodeMaxNALocals(); - int[] codeMaxStack = segment.getClassBands().getCodeMaxStack(); - ArrayList[][] methodAttributes = segment.getClassBands() - .getMethodAttributes(); - String[][] methodDescr = segment.getClassBands().getMethodDescr(); int bcCaseCountCount = 0; int bcByteCount = 0; @@ -122,14 +119,12 @@ AttributeLayout nativeModifier = attributeDefinitionMap .getAttributeLayout(AttributeLayout.ACC_NATIVE, AttributeLayout.CONTEXT_METHOD); - AttributeLayout staticModifier = attributeDefinitionMap - .getAttributeLayout(AttributeLayout.ACC_STATIC, - AttributeLayout.CONTEXT_METHOD); + methodByteCodePacked = new byte[classCount][][]; int bcParsed = 0; List switchIsTableSwitch = new ArrayList(); - List wideByteCodes = new ArrayList(); + wideByteCodes = new ArrayList(); for (int c = 0; c < classCount; c++) { int numberOfMethods = methodFlags[c].length; methodByteCodePacked[c] = new byte[numberOfMethods][]; @@ -361,6 +356,31 @@ bcEscSize = decodeBandInt("bc_escsize", in, Codec.UNSIGNED5, bcEscCount); bcEscByte = decodeBandInt("bc_escbyte", in, Codec.BYTE1, bcEscSize); + + } + + public void unpack() throws Pack200Exception { + int classCount = header.getClassCount(); + long[][] methodFlags = segment.getClassBands().getMethodFlags(); + int[] codeMaxNALocals = segment.getClassBands().getCodeMaxNALocals(); + int[] codeMaxStack = segment.getClassBands().getCodeMaxStack(); + ArrayList[][] methodAttributes = segment.getClassBands() + .getMethodAttributes(); + String[][] methodDescr = segment.getClassBands().getMethodDescr(); + + AttributeLayoutMap attributeDefinitionMap = segment + .getAttrDefinitionBands().getAttributeDefinitionMap(); + + AttributeLayout abstractModifier = attributeDefinitionMap + .getAttributeLayout(AttributeLayout.ACC_ABSTRACT, + AttributeLayout.CONTEXT_METHOD); + AttributeLayout nativeModifier = attributeDefinitionMap + .getAttributeLayout(AttributeLayout.ACC_NATIVE, + AttributeLayout.CONTEXT_METHOD); + AttributeLayout staticModifier = attributeDefinitionMap + .getAttributeLayout(AttributeLayout.ACC_STATIC, + AttributeLayout.CONTEXT_METHOD); + int[] wideByteCodeArray = new int[wideByteCodes.size()]; for (int index = 0; index < wideByteCodeArray.length; index++) { wideByteCodeArray[index] = ((Integer) wideByteCodes.get(index)) @@ -402,10 +422,10 @@ maxLocal += SegmentUtils .countInvokeInterfaceArgs(methodDescr[c][m]); String[] cpClass = segment.getCpBands().getCpClass(); - operandManager.setCurrentClass(cpClass[segment.getClassBands() - .getClassThisInts()[c]]); - operandManager.setSuperClass(cpClass[segment.getClassBands() - .getClassSuperInts()[c]]); + operandManager.setCurrentClass(cpClass[segment + .getClassBands().getClassThisInts()[c]]); + operandManager.setSuperClass(cpClass[segment + .getClassBands().getClassSuperInts()[c]]); List exceptionTable = new ArrayList(); if (handlerCount != null) { for (int j = 0; j < handlerCount[i]; j++) { @@ -433,8 +453,9 @@ for (Iterator iterator = methodAttributesList.iterator(); iterator .hasNext();) { Attribute attribute = (Attribute) iterator.next(); - if((attribute instanceof NewAttribute && ((NewAttribute)attribute).getLayoutIndex() < 15)) { - indexForCodeAttr ++; + if ((attribute instanceof NewAttribute && ((NewAttribute) attribute) + .getLayoutIndex() < 15)) { + indexForCodeAttr++; } else { break; } @@ -458,7 +479,7 @@ } } } - + private boolean startsWithIf(int codePacked) { return (codePacked >= 153 && codePacked <= 166) || (codePacked == 198) || (codePacked == 199); Index: src/test/java/org/apache/harmony/unpack200/tests/BandSetTest.java =================================================================== --- src/test/java/org/apache/harmony/unpack200/tests/BandSetTest.java (revision 676138) +++ src/test/java/org/apache/harmony/unpack200/tests/BandSetTest.java (working copy) @@ -39,11 +39,14 @@ } private final BandSet bandSet = new BandSet(new MockSegment()) { - - public void unpack(InputStream inputStream) throws IOException, + + public void read(InputStream inputStream) throws IOException, Pack200Exception { } + public void unpack() throws IOException, Pack200Exception { + } + }; public void testDecodeBandInt() throws IOException, Pack200Exception {