Index: src/main/java/org/apache/harmony/pack200/AttributeLayout.java =================================================================== --- src/main/java/org/apache/harmony/pack200/AttributeLayout.java (revision 591346) +++ src/main/java/org/apache/harmony/pack200/AttributeLayout.java (working copy) @@ -242,6 +242,9 @@ } public int numBackwardsCallables() { + if(layout == "*") { + return 1; // TODO: complicated attributes (shouldn't be *'s at all...) + } int num = 0; String[] split = layout.split("\\("); if(split.length > 0) { Index: src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java =================================================================== --- src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (revision 587112) +++ src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (working copy) @@ -26,7 +26,8 @@ * internationalized, and should not be translated. */ public class AttributeLayoutMap { - // create a whole bunch of AttributeLayouts here + + // Create all the default AttributeLayouts here private static AttributeLayout[] getDefaultAttributeLayouts() throws Pack200Exception { return new AttributeLayout[] { @@ -137,7 +138,7 @@ new AttributeLayout(AttributeLayout.ATTRIBUTE_CONSTANT_VALUE, AttributeLayout.CONTEXT_FIELD, "KQH", 17), new AttributeLayout(AttributeLayout.ATTRIBUTE_CODE, - AttributeLayout.CONTEXT_METHOD, "*", 17), + AttributeLayout.CONTEXT_METHOD, "", 17), new AttributeLayout(AttributeLayout.ATTRIBUTE_ENCLOSING_METHOD, AttributeLayout.CONTEXT_CLASS, "RCHRDNH", 18), new AttributeLayout(AttributeLayout.ATTRIBUTE_EXCEPTIONS, @@ -173,7 +174,7 @@ AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_METHOD, "*", 22), new AttributeLayout(AttributeLayout.ATTRIBUTE_INNER_CLASSES, - AttributeLayout.CONTEXT_CLASS, "*", 23), + AttributeLayout.CONTEXT_CLASS, "", 23), new AttributeLayout( AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, AttributeLayout.CONTEXT_METHOD, "*", 23), @@ -257,4 +258,5 @@ } } } + } Index: src/main/java/org/apache/harmony/pack200/BandSet.java =================================================================== --- src/main/java/org/apache/harmony/pack200/BandSet.java (revision 591346) +++ src/main/java/org/apache/harmony/pack200/BandSet.java (working copy) @@ -21,6 +21,12 @@ import java.io.InputStream; import java.io.OutputStream; +import org.apache.harmony.pack200.bytecode.CPDouble; +import org.apache.harmony.pack200.bytecode.CPFloat; +import org.apache.harmony.pack200.bytecode.CPInteger; +import org.apache.harmony.pack200.bytecode.CPLong; +import org.apache.harmony.pack200.bytecode.CPUTF8; + public abstract class BandSet { public abstract void unpack(InputStream inputStream) throws IOException, Pack200Exception; @@ -380,5 +386,103 @@ segment.debug(message); } + public CPInteger[] parseCPIntReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception { + int[] reference = segment.getCpBands().getCpInt(); + int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1); + CPInteger[] result = new CPInteger[indices.length]; + for (int i1 = 0; i1 < count; i1++) { + int index = indices[i1]; + if (index < 0 || index >= reference.length) + throw new Pack200Exception( + "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length); + result[i1] = new CPInteger(new Integer(reference[index])); + } + return result; + } + + public CPDouble[] parseCPDoubleReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception { + double[] reference = segment.getCpBands().getCpDouble(); + int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1); + CPDouble[] result = new CPDouble[indices.length]; + for (int i1 = 0; i1 < count; i1++) { + int index = indices[i1]; + if (index < 0 || index >= reference.length) + throw new Pack200Exception( + "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length); + result[i1] = new CPDouble(new Double(reference[index])); + } + return result; + } + + public CPFloat[] parseCPFloatReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception { + float[] reference = segment.getCpBands().getCpFloat(); + int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1); + CPFloat[] result = new CPFloat[indices.length]; + for (int i1 = 0; i1 < count; i1++) { + int index = indices[i1]; + if (index < 0 || index >= reference.length) + throw new Pack200Exception( + "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length); + result[i1] = new CPFloat(new Float(reference[index])); + } + return result; + } + + public CPLong[] parseCPLongReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception { + long[] reference = segment.getCpBands().getCpLong(); + int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1); + CPLong[] result = new CPLong[indices.length]; + for (int i1 = 0; i1 < count; i1++) { + int index = indices[i1]; + if (index < 0 || index >= reference.length) + throw new Pack200Exception( + "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length); + result[i1] = new CPLong(new Long(reference[index])); + } + return result; + } + + public CPUTF8[] parseCPUTF8References(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception { + String[] reference = segment.getCpBands().getCpUTF8(); + int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1); + CPUTF8[] result = new CPUTF8[indices.length]; + for (int i1 = 0; i1 < count; i1++) { + int index = indices[i1]; + if (index < 0 || index >= reference.length) + throw new Pack200Exception( + "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length); + result[i1] = new CPUTF8(reference[index]); + } + return result; + } + + + public CPUTF8[][] parseCPUTF8References(String name, InputStream in, BHSDCodec codec, int[] counts) throws IOException, Pack200Exception { + String[] reference = segment.getCpBands().getCpUTF8(); + CPUTF8[][] result = new CPUTF8[counts.length][]; + int sum = 0; + for (int i = 0; i < counts.length; i++) { + result[i] = new CPUTF8[counts[i]]; + sum += counts[i]; + } + CPUTF8[] result1 = new CPUTF8[sum]; + int[] indices = decodeBandInt(name, in, codec, sum, reference.length - 1); + for (int i1 = 0; i1 < sum; i1++) { + int index = indices[i1]; + if (index < 0 || index >= reference.length) + throw new Pack200Exception( + "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length); + result1[i1] = new CPUTF8(reference[index]); + } + CPUTF8[] refs = result1; + int pos = 0; + for (int i = 0; i < counts.length; i++) { + int num = counts[i]; + result[i] = new CPUTF8[num]; + System.arraycopy(refs, pos, result[i], 0, num); + pos += num; + } + return result; + } } Index: src/main/java/org/apache/harmony/pack200/ClassBands.java =================================================================== --- src/main/java/org/apache/harmony/pack200/ClassBands.java (revision 591346) +++ src/main/java/org/apache/harmony/pack200/ClassBands.java (working copy) @@ -20,11 +20,18 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; import org.apache.harmony.pack200.IcBands.ICTuple; import org.apache.harmony.pack200.bytecode.CPClass; +import org.apache.harmony.pack200.bytecode.CPUTF8; import org.apache.harmony.pack200.bytecode.ConstantValueAttribute; import org.apache.harmony.pack200.bytecode.ExceptionsAttribute; +import org.apache.harmony.pack200.bytecode.LineNumberTableAttribute; +import org.apache.harmony.pack200.bytecode.LocalVariableTableAttribute; +import org.apache.harmony.pack200.bytecode.LocalVariableTypeTableAttribute; +import org.apache.harmony.pack200.bytecode.SignatureAttribute; import org.apache.harmony.pack200.bytecode.SourceFileAttribute; /** @@ -43,15 +50,17 @@ private String[] classSuper; private String[] classThis; - + private ArrayList[] classAttributes; - + private int[] classVersionMajor; - + private int[] classVersionMinor; - + private IcBands.ICTuple[][] icLocal; + private ArrayList[] codeAttributes; + private int[] codeHandlerCount; private int[] codeMaxNALocals; @@ -67,7 +76,7 @@ private ArrayList[][] methodAttributes; private String[][] methodDescr; - + private long[][] methodFlags; private AttributeLayoutMap attrMap; @@ -79,7 +88,7 @@ private int classCount; private int[] methodAttrCalls; - + /** * @param segment */ @@ -90,7 +99,7 @@ this.cpBands = segment.getCpBands(); this.classCount = header.getClassCount(); this.options = header.getOptions(); - + } /* @@ -136,42 +145,32 @@ fieldFlags = parseFlags("field_flags", in, classFieldCount, Codec.UNSIGNED5, options.hasFieldFlagsHi()); int fieldAttrCount = SegmentUtils.countBit16(fieldFlags); - int[] fieldAttrCounts = decodeBandInt("field_attr_count", in, Codec.UNSIGNED5, fieldAttrCount); - int[][] fieldAttrIndexes = decodeBandInt("field_attr_indexes", in, Codec.UNSIGNED5, fieldAttrCounts); - int callCount = 0; - for (int i = 0; i < fieldAttrIndexes.length; i++) { - for (int j = 0; j < fieldAttrIndexes[i].length; j++) { - int index = fieldAttrIndexes[i][j]; - AttributeLayout layout = attrMap.getAttributeLayout(index, AttributeLayout.CONTEXT_FIELD); - callCount += layout.numBackwardsCallables(); - } - } - int layoutsUsed = 0; - for (int i = 0; i < fieldFlags.length; i++) { - for (int j = 0; j < fieldFlags[i].length; j++) { - layoutsUsed |= fieldFlags[i][j]; - } - } - for (int i = 0; i < 16; i++) { - if((layoutsUsed & 1< 0) { + if (versionCount > 0) { classVersionMajor = new int[classCount]; classVersionMinor = new int[classCount]; } @@ -384,7 +423,9 @@ } int defaultVersionMajor = header.getDefaultClassMajorVersion(); int defaultVersionMinor = header.getDefaultClassMinorVersion(); - + + // TODO: Parse other attribute bands + // Now process the attribute bands we have parsed int sourceFileIndex = 0; int enclosingMethodIndex = 0; @@ -392,21 +433,21 @@ int innerClassIndex = 0; int innerClassC2NIndex = 0; int versionIndex = 0; - classAttributes = new ArrayList[classCount]; icLocal = new IcBands.ICTuple[classCount][]; for (int i = 0; i < classCount; i++) { - classAttributes[i] = new ArrayList(); long flag = classFlags[i]; - + if (sourceFileLayout.matches(flag)) { long result = classSourceFile[sourceFileIndex]; - String value = (String) sourceFileLayout.getValue(result, cpBands - .getConstantPool()); - if(value == null) { + String value = (String) sourceFileLayout.getValue(result, + cpBands.getConstantPool()); + if (value == null) { // Remove package prefix - String className = classThis[i].substring(classThis[i].lastIndexOf('/') + 1); - className = className.substring(className.lastIndexOf('.') + 1); - + String className = classThis[i].substring(classThis[i] + .lastIndexOf('/') + 1); + className = className + .substring(className.lastIndexOf('.') + 1); + // Remove mangled nested class names char[] chars = className.toCharArray(); int index = -1; @@ -411,12 +452,12 @@ char[] chars = className.toCharArray(); int index = -1; for (int j = 0; j < chars.length; j++) { - if(chars[j] <= 0x2D) { + if (chars[j] <= 0x2D) { index = j; break; - } + } } - if(index > -1) { + if (index > -1) { className = className.substring(0, index); } // Add .java to the end @@ -425,10 +466,10 @@ classAttributes[i].add(new SourceFileAttribute(value)); sourceFileIndex++; } - if(enclosingMethodLayout.matches(flag)) { -// long result = + if (enclosingMethodLayout.matches(flag)) { + // long result = } - if(signatureLayout.matches(flag)) { + if (signatureLayout.matches(flag)) { long result = classSignature[signatureIndex]; Object value = signatureLayout.getValue(result, cpBands .getConstantPool()); @@ -435,7 +476,7 @@ classAttributes[i].add(new ConstantValueAttribute(value)); signatureIndex++; } - if(innerClassLayout.matches(flag)) { + if (innerClassLayout.matches(flag)) { // Just create the tuples for now because the attributes are // decided at the end when creating class constant pools icLocal[i] = new IcBands.ICTuple[classInnerClassesN[innerClassIndex]]; @@ -443,7 +484,7 @@ IcBands.ICTuple icTuple = new IcBands.ICTuple(); icTuple.C = cpClass[classInnerClassesRC[innerClassIndex][j]]; icTuple.F = classInnerClassesF[innerClassIndex][j]; - if(icTuple.F != 0) { + if (icTuple.F != 0) { icTuple.C2 = cpClass[classInnerClassesOuterRCN[innerClassC2NIndex]]; icTuple.N = cpUTF8[classInnerClassesNameRUN[innerClassC2NIndex]]; innerClassC2NIndex++; @@ -452,7 +493,7 @@ IcBands icBands = segment.getIcBands(); ICTuple[] icAll = icBands.getIcTuples(); for (int k = 0; k < icAll.length; k++) { - if(icAll[k].C.equals(icTuple.C)) { + if (icAll[k].C.equals(icTuple.C)) { icTuple.C2 = icAll[k].C2; icTuple.N = icAll[k].N; break; @@ -461,13 +502,13 @@ } icLocal[i][j] = icTuple; } - innerClassIndex++; + innerClassIndex++; } - if(versionLayout.matches(flag)) { + if (versionLayout.matches(flag)) { classVersionMajor[i] = classFileVersionMajorH[versionIndex]; classVersionMinor[i] = classFileVersionMinorH[versionIndex]; versionIndex++; - } else if(classVersionMajor != null) { + } else if (classVersionMajor != null) { // Fill in with defaults classVersionMajor[i] = defaultVersionMajor; classVersionMinor[i] = defaultVersionMinor; @@ -475,7 +516,6 @@ } } - private void parseCodeBands(InputStream in) throws Pack200Exception, IOException { AttributeLayout layout = attrMap.getAttributeLayout( @@ -527,23 +567,37 @@ } int sumCodeHandlerCount = 0; for (int i = 0; i < codeHandlerCount.length; i++) { - sumCodeHandlerCount+= codeHandlerCount[i]; + sumCodeHandlerCount += codeHandlerCount[i]; } - int[] codeHandlerStartP = decodeBandInt("code_handler_start_P", in, Codec.BCI5, sumCodeHandlerCount); - int[] codeHandlerEndPO = decodeBandInt("code_handler_end_PO", in, Codec.BRANCH5, sumCodeHandlerCount); - int[] codeHandlerCatchPO = decodeBandInt("code_handler_catch_PO", in, Codec.BRANCH5, sumCodeHandlerCount); - int[] codeHandlerClassRCN = decodeBandInt("code_handler_class_RCN", in, Codec.UNSIGNED5, sumCodeHandlerCount); - - int codeFlagsCount = segment.getSegmentHeader().getOptions().hasAllCodeFlags() ? - codeCount : codeSpecialHeader; + int[] codeHandlerStartP = decodeBandInt("code_handler_start_P", in, + Codec.BCI5, sumCodeHandlerCount); + int[] codeHandlerEndPO = decodeBandInt("code_handler_end_PO", in, + Codec.BRANCH5, sumCodeHandlerCount); + int[] codeHandlerCatchPO = decodeBandInt("code_handler_catch_PO", in, + Codec.BRANCH5, sumCodeHandlerCount); + int[] codeHandlerClassRCN = decodeBandInt("code_handler_class_RCN", in, + Codec.UNSIGNED5, sumCodeHandlerCount); + + int codeFlagsCount = segment.getSegmentHeader().getOptions() + .hasAllCodeFlags() ? codeCount : codeSpecialHeader; + + codeAttributes = new ArrayList[codeFlagsCount]; + for (int i = 0; i < codeAttributes.length; i++) { + codeAttributes[i] = new ArrayList(); + } parseCodeAttrBands(in, codeFlagsCount); } - private void parseCodeAttrBands(InputStream in, int codeFlagsCount) throws IOException, Pack200Exception { - long[] codeFlags = parseFlags("code_flags", in, codeFlagsCount, Codec.UNSIGNED5, segment.getSegmentHeader().getOptions().hasCodeFlagsHi()); + private void parseCodeAttrBands(InputStream in, int codeFlagsCount) + throws IOException, Pack200Exception { + long[] codeFlags = parseFlags("code_flags", in, codeFlagsCount, + Codec.UNSIGNED5, segment.getSegmentHeader().getOptions() + .hasCodeFlagsHi()); int codeAttrCount = SegmentUtils.countBit16(codeFlags); - int[] codeAttrCounts = decodeBandInt("code_attr_count", in, Codec.UNSIGNED5, codeAttrCount); - int[][] codeAttrIndexes = decodeBandInt("code_attr_indexes", in, Codec.UNSIGNED5, codeAttrCounts); + int[] codeAttrCounts = decodeBandInt("code_attr_count", in, + Codec.UNSIGNED5, codeAttrCount); + int[][] codeAttrIndexes = decodeBandInt("code_attr_indexes", in, + Codec.UNSIGNED5, codeAttrCounts); int callCount = 0; for (int i = 0; i < codeAttrIndexes.length; i++) { for (int j = 0; j < codeAttrIndexes[i].length; j++) { @@ -548,35 +602,139 @@ for (int i = 0; i < codeAttrIndexes.length; i++) { for (int j = 0; j < codeAttrIndexes[i].length; j++) { int index = codeAttrIndexes[i][j]; - AttributeLayout layout = attrMap.getAttributeLayout(index, AttributeLayout.CONTEXT_CODE); + AttributeLayout layout = attrMap.getAttributeLayout(index, + AttributeLayout.CONTEXT_CODE); callCount += layout.numBackwardsCallables(); } } - int[] codeAttrCalls = decodeBandInt("code_attr_calls", in, Codec.UNSIGNED5, callCount); - - int lineNumberTableCount = SegmentUtils.countMatches(codeFlags, attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_LINE_NUMBER_TABLE, AttributeLayout.CONTEXT_CODE)); - int[] lineNumberTableN = decodeBandInt("code_LineNumberTable_N", in, Codec.UNSIGNED5, lineNumberTableCount); - int[][] lineNumberTableBciP = decodeBandInt("code_LineNumberTable_bci_P", in, Codec.BCI5, lineNumberTableN); - int[][] lineNumberTableLine = decodeBandInt("code_LineNumberTable_line", in, Codec.UNSIGNED5, lineNumberTableN); - String[] types = { AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TABLE, AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE }; - for (int i = 0; i < types.length; i++) { - String type = types[i]; - int lengthNBand = SegmentUtils.countMatches(codeFlags, attrMap.getAttributeLayout(type, AttributeLayout.CONTEXT_CODE)); - - int[] nBand = decodeBandInt("code_" + type + "_N", in, Codec.UNSIGNED5, lengthNBand); - int[][] bciP = decodeBandInt("code_" + type + "_bci_P", in, Codec.BCI5, nBand); - int[][] spanO = decodeBandInt("code_" + type + "_span_O", in, Codec.BRANCH5, nBand); - String[][] nameRU = parseReferences("code_" + type + "_name_RU", in, Codec.UNSIGNED5, nBand, cpBands.getCpUTF8()); - String[][] typeRS = parseReferences("code_" + type + "_type_RS", in, Codec.UNSIGNED5, nBand, cpBands.getCpSignature()); - int[][] slot = decodeBandInt("code_" + type + "_slot", in, Codec.UNSIGNED5, nBand); + int[] codeAttrCalls = decodeBandInt("code_attr_calls", in, + Codec.UNSIGNED5, callCount); + + AttributeLayout lineNumberTableLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_LINE_NUMBER_TABLE, + AttributeLayout.CONTEXT_CODE); + int lineNumberTableCount = SegmentUtils.countMatches(codeFlags, + lineNumberTableLayout); + int[] lineNumberTableN = decodeBandInt("code_LineNumberTable_N", in, + Codec.UNSIGNED5, lineNumberTableCount); + int[][] lineNumberTableBciP = decodeBandInt( + "code_LineNumberTable_bci_P", in, Codec.BCI5, lineNumberTableN); + int[][] lineNumberTableLine = decodeBandInt( + "code_LineNumberTable_line", in, Codec.UNSIGNED5, + lineNumberTableN); + + AttributeLayout localVariableTableLayout = attrMap.getAttributeLayout( + AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TABLE, + AttributeLayout.CONTEXT_CODE); + AttributeLayout localVariableTypeTableLayout = attrMap + .getAttributeLayout( + AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE, + AttributeLayout.CONTEXT_CODE); + + int lengthLocalVariableNBand = SegmentUtils.countMatches(codeFlags, + localVariableTableLayout); + int[] localVariableTableN = decodeBandInt("code_LocalVariableTable_N", + in, Codec.UNSIGNED5, lengthLocalVariableNBand); + int[][] localVariableTableBciP = decodeBandInt( + "code_LocalVariableTable_bci_P", in, Codec.BCI5, + localVariableTableN); + int[][] localVariableTableSpanO = decodeBandInt( + "code_LocalVariableTable_span_O", in, Codec.BRANCH5, + localVariableTableN); + CPUTF8[][] localVariableTableNameRU = stringsToCPUTF8(parseReferences( + "code_LocalVariableTable_name_RU", in, Codec.UNSIGNED5, + localVariableTableN, cpBands.getCpUTF8())); + CPUTF8[][] localVariableTableTypeRS = stringsToCPUTF8(parseReferences( + "code_LocalVariableTable_type_RS", in, Codec.UNSIGNED5, + localVariableTableN, cpBands.getCpSignature())); + int[][] localVariableTableSlot = decodeBandInt( + "code_LocalVariableTable_slot", in, Codec.UNSIGNED5, + localVariableTableN); + + int lengthLocalVariableTypeTableNBand = SegmentUtils.countMatches( + codeFlags, localVariableTypeTableLayout); + int[] localVariableTypeTableN = decodeBandInt( + "code_LocalVariableTypeTable_N", in, Codec.UNSIGNED5, + lengthLocalVariableTypeTableNBand); + int[][] localVariableTypeTableBciP = decodeBandInt( + "code_LocalVariableTypeTable_bci_P", in, Codec.BCI5, + localVariableTypeTableN); + int[][] localVariableTypeTableSpanO = decodeBandInt( + "code_LocalVariableTypeTable_span_O", in, Codec.BRANCH5, + localVariableTypeTableN); + CPUTF8[][] localVariableTypeTableNameRU = stringsToCPUTF8(parseReferences( + "code_LocalVariableTypeTable_name_RU", in, Codec.UNSIGNED5, + localVariableTypeTableN, cpBands.getCpUTF8())); + CPUTF8[][] localVariableTypeTableTypeRS = stringsToCPUTF8(parseReferences( + "code_LocalVariableTypeTable_type_RS", in, Codec.UNSIGNED5, + localVariableTypeTableN, cpBands.getCpSignature())); + int[][] localVariableTypeTableSlot = decodeBandInt( + "code_LocalVariableTypeTable_slot", in, Codec.UNSIGNED5, + localVariableTypeTableN); + + int lineNumberIndex = 0; + int lvtIndex = 0; + int lvttIndex = 0; + for (int i = 0; i < codeFlagsCount; i++) { + if (lineNumberTableLayout.matches(codeFlags[i])) { + LineNumberTableAttribute lnta = new LineNumberTableAttribute( + lineNumberTableN[lineNumberIndex], + lineNumberTableBciP[lineNumberIndex], + lineNumberTableLine[lineNumberIndex]); + lineNumberIndex++; + codeAttributes[i].add(lnta); + } + if (localVariableTableLayout.matches(codeFlags[i])) { + LocalVariableTableAttribute lvta = new LocalVariableTableAttribute( + localVariableTableN[lvtIndex], + localVariableTableBciP[lvtIndex], + localVariableTableSpanO[lvtIndex], + localVariableTableNameRU[lvtIndex], + localVariableTableTypeRS[lvtIndex], + localVariableTableSlot[lvtIndex]); + lvtIndex++; + codeAttributes[i].add(lvta); + } + if (localVariableTypeTableLayout.matches(codeFlags[i])) { + LocalVariableTypeTableAttribute lvtta = new LocalVariableTypeTableAttribute( + localVariableTypeTableN[lvttIndex], + localVariableTypeTableBciP[lvttIndex], + localVariableTypeTableSpanO[lvttIndex], + localVariableTypeTableNameRU[lvttIndex], + localVariableTypeTableTypeRS[lvttIndex], + localVariableTypeTableSlot[lvttIndex]); + lvttIndex++; + codeAttributes[i].add(lvtta); + } } + // TODO: Parse other attribute bands } + private CPUTF8[][] stringsToCPUTF8(String[][] strings) { + CPUTF8[][] cpUTF8s = new CPUTF8[strings.length][]; + for (int i = 0; i < strings.length; i++) { + cpUTF8s[i] = new CPUTF8[strings[i].length]; + for (int j = 0; j < strings[i].length; j++) { + cpUTF8s[i][j] = new CPUTF8(strings[i][j]); + } + } + return cpUTF8s; + } + - private void parseFieldMetadataBands() throws Pack200Exception { + private CPUTF8[] stringsToCPUTF8(String[] strings) { + CPUTF8[] cpUTF8s = new CPUTF8[strings.length]; + for (int i = 0; i < strings.length; i++) { + cpUTF8s[i] = new CPUTF8(strings[i]); + } + return cpUTF8s; + } + + private void parseFieldMetadataBands(InputStream in, int[] fieldAttrCalls) + throws Pack200Exception, IOException { String[] RxA = new String[] { "RVA", "RIA" }; - + AttributeLayout rvaLayout = attrMap.getAttributeLayout( AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_FIELD); @@ -586,45 +744,143 @@ int rvaCount = SegmentUtils.countMatches(fieldFlags, rvaLayout); int riaCount = SegmentUtils.countMatches(fieldFlags, riaLayout); - if (rvaCount > 0 || riaCount > 0) { - throw new Error("Field metadata not handled"); + int[] RxACount = new int[] { rvaCount, riaCount }; + int[] backwardsCalls = new int[] {0, 0}; + if(rvaCount > 0) { + backwardsCalls[0] = fieldAttrCalls[0]; + if(riaCount > 0) { + backwardsCalls[1] = fieldAttrCalls[1]; + } + } else if (riaCount > 0) { + backwardsCalls[1] = fieldAttrCalls[0]; } + MetadataBandGroup[] mb = parseMetadata(in, RxA, RxACount, backwardsCalls, "field"); + Iterator rvaAttributesIterator = mb[0].getAttributes().iterator(); + Iterator riaAttributesIterator = mb[1].getAttributes().iterator(); + for (int i = 0; i < fieldFlags.length; i++) { + for (int j = 0; j < fieldFlags[i].length; j++) { + if(rvaLayout.matches(fieldFlags[i][j])) { + fieldAttributes[i][j].add(rvaAttributesIterator.next()); + } + if(riaLayout.matches(fieldFlags[i][j])) { + fieldAttributes[i][j].add(riaAttributesIterator.next()); + } + } + } + } - // AttributeLayout layout = - // map.get(RuntimeVisibleAnnotations,class/field/method as int) - // foreachheader ... - // if layout.matches(header[n] or whatever) - String contextName = "field"; + private MetadataBandGroup[] parseMetadata(InputStream in, String[] RxA, int[] RxACount, + int[] backwardsCallCounts, String contextName) throws IOException, Pack200Exception { + MetadataBandGroup[] mbg = new MetadataBandGroup[RxA.length]; for (int i = 0; i < RxA.length; i++) { + mbg[i] = new MetadataBandGroup(RxA[i]); String rxa = RxA[i]; if (rxa.indexOf("P") >= 0) { - debug("unimplemented " + contextName + "_" + rxa + "_param_NB"); + mbg[i].param_NB = decodeBandInt(contextName + "_" + rxa + + "_param_NB", in, Codec.BYTE1, RxACount[i]); } + int pairCount = 0; if (!rxa.equals("AD")) { - debug("unimplemented " + contextName + "_" + rxa + "_anno_N"); - debug("unimplemented " + contextName + "_" + rxa + "_type_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_pair_N"); - debug("unimplemented " + contextName + "_" + rxa + "_name_RU"); + mbg[i].anno_N = decodeBandInt(contextName + "_" + rxa + + "_anno_N", in, Codec.UNSIGNED5, RxACount[i]); + mbg[i].type_RS = stringsToCPUTF8(parseReferences(contextName + "_" + rxa + + "_type_RS", in, Codec.UNSIGNED5, mbg[i].anno_N, cpBands.getCpSignature())); + mbg[i].pair_N = decodeBandInt(contextName + "_" + rxa + + "_pair_N", in, Codec.UNSIGNED5, mbg[i].anno_N); + for (int j = 0; j < mbg[i].pair_N.length; j++) { + for (int k = 0; k < mbg[i].pair_N[j].length; k++) { + pairCount += mbg[i].pair_N[j][k]; + } + } + + mbg[i].name_RU = stringsToCPUTF8(parseReferences(contextName + "_" + rxa + + "_name_RU", in, Codec.UNSIGNED5, pairCount, cpBands.getCpUTF8())); } - debug("unimplemented " + contextName + "_" + rxa + "_T"); - debug("unimplemented " + contextName + "_" + rxa + "_caseI_KI"); - debug("unimplemented " + contextName + "_" + rxa + "_caseD_KD"); - debug("unimplemented " + contextName + "_" + rxa + "_caseF_KF"); - debug("unimplemented " + contextName + "_" + rxa + "_caseJ_KJ"); - debug("unimplemented " + contextName + "_" + rxa + "_casec_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_caseet_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_caseec_RU"); - debug("unimplemented " + contextName + "_" + rxa + "_cases_RU"); - debug("unimplemented " + contextName + "_" + rxa + "_casearray_N"); - debug("unimplemented " + contextName + "_" + rxa + "_nesttype_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_nestpair_N"); - debug("unimplemented " + contextName + "_" + rxa + "_nestname_RU"); + mbg[i].T = decodeBandInt(contextName + "_" + rxa + "_T", in, + Codec.BYTE1, pairCount + backwardsCallCounts[i]); + int ICount = 0, DCount = 0, FCount = 0, JCount = 0, cCount = 0, eCount = 0, sCount = 0, arrayCount = 0, atCount = 0; + for (int j = 0; j < mbg[i].T.length; j++) { + char c = (char) mbg[i].T[j]; + switch (c) { + case 'B': + case 'C': + case 'I': + case 'S': + case 'Z': + ICount++; + break; + case 'D': + DCount++; + break; + case 'F': + FCount++; + break; + case 'J': + JCount++; + break; + case 'c': + cCount++; + break; + case 'e': + eCount++; + break; + case 's': + sCount++; + break; + case '[': + arrayCount++; + break; + case '@': + atCount++; + break; + } + } + mbg[i].caseI_KI = parseCPIntReferences(contextName + "_" + rxa + + "_caseI_KI", in, Codec.UNSIGNED5, ICount); + mbg[i].caseD_KD = parseCPDoubleReferences(contextName + "_" + rxa + + "_caseD_KD", in, Codec.UNSIGNED5, DCount); + mbg[i].caseF_KF = parseCPFloatReferences(contextName + "_" + rxa + + "_caseF_KF", in, Codec.UNSIGNED5, FCount); + mbg[i].caseJ_KJ = parseCPLongReferences(contextName + "_" + rxa + + "_caseJ_KJ", in, Codec.UNSIGNED5, JCount); + mbg[i].casec_RS = parseCPUTF8References(contextName + "_" + rxa + + "_casec_RS", in, Codec.UNSIGNED5, cCount); + mbg[i].caseet_RS = parseReferences(contextName + "_" + rxa + + "_caseet_RS", in, Codec.UNSIGNED5, eCount, cpBands.getCpSignature()); + mbg[i].caseec_RU = parseReferences(contextName + "_" + rxa + + "_caseec_RU", in, Codec.UNSIGNED5, eCount, cpBands.getCpUTF8()); + mbg[i].cases_RU = parseCPUTF8References(contextName + "_" + rxa + + "_cases_RU", in, Codec.UNSIGNED5, sCount); + mbg[i].casearray_N = decodeBandInt(contextName + "_" + rxa + + "_casearray_N", in, Codec.UNSIGNED5, arrayCount); + mbg[i].nesttype_RS = parseCPUTF8References(contextName + "_" + rxa + + "_nesttype_RS", in, Codec.UNSIGNED5, atCount); + mbg[i].nestpair_N = decodeBandInt(contextName + "_" + rxa + + "_nestpair_N", in, Codec.UNSIGNED5, atCount); + int nestPairCount = 0; + for (int j = 0; j < mbg[i].nestpair_N.length; j++) { + nestPairCount += mbg[i].nestpair_N[j]; + } + mbg[i].nestname_RU = parseCPUTF8References(contextName + "_" + rxa + + "_nestname_RU", in, Codec.UNSIGNED5, nestPairCount); } + return mbg; } - private void parseMethodMetadataBands() throws Pack200Exception { + private void parseMethodMetadataBands(InputStream in, int[] methodAttrCalls) + throws Pack200Exception, IOException { String[] RxA = new String[] { "RVA", "RIA", "RVPA", "RIPA", "AD" }; int[] rxaCounts = new int[] { 0, 0, 0, 0, 0 }; + int[] backwardsCalls = new int[5]; + int methodAttrIndex = 0; + for (int i = 0; i < backwardsCalls.length; i++) { + if(rxaCounts[i] > 0) { + backwardsCalls[i] = methodAttrCalls[methodAttrIndex]; + methodAttrIndex++; + } else { + backwardsCalls[i] = 0; + } + } AttributeLayout rvaLayout = attrMap.getAttributeLayout( AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, AttributeLayout.CONTEXT_METHOD); @@ -646,45 +902,26 @@ riaLayout, rvpaLayout, ripaLayout, adLayout }; for (int i = 0; i < rxaLayouts.length; i++) { - rxaCounts[i] = SegmentUtils.countMatches(methodFlags, rxaLayouts[i]); - if (rxaCounts[i] > 0) { - throw new Error("Found method metadata"); - } + rxaCounts[i] = SegmentUtils + .countMatches(methodFlags, rxaLayouts[i]); } - - // AttributeLayout layout = - // map.get(RuntimeVisibleAnnotations,class/field/method as int) - // foreachheader ... - // if layout.matches(header[n] or whatever) - String contextName = "method"; - for (int i = 0; i < RxA.length; i++) { - String rxa = RxA[i]; - if (rxa.indexOf("P") >= 0) { - debug("unimplemented " + contextName + "_" + rxa + "_param_NB"); - } - if (!rxa.equals("AD")) { - debug("unimplemented " + contextName + "_" + rxa + "_anno_N"); - debug("unimplemented " + contextName + "_" + rxa + "_type_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_pair_N"); - debug("unimplemented " + contextName + "_" + rxa + "_name_RU"); + MetadataBandGroup[] mbgs = parseMetadata(in, RxA, rxaCounts, backwardsCalls, "method"); + Iterator[] attributeIterators = new Iterator[RxA.length]; + for (int i = 0; i < mbgs.length; i++) { + attributeIterators[i] = mbgs[i].getAttributes().iterator(); + } + for (int i = 0; i < methodFlags.length; i++) { + for (int j = 0; j < methodFlags[i].length; j++) { + for (int k = 0; k < rxaLayouts.length; k++) { + if(rxaLayouts[k].matches(methodFlags[i][j])) { + methodAttributes[i][j].add(attributeIterators[k].next()); + } + } } - debug("unimplemented " + contextName + "_" + rxa + "_T"); - debug("unimplemented " + contextName + "_" + rxa + "_caseI_KI"); - debug("unimplemented " + contextName + "_" + rxa + "_caseD_KD"); - debug("unimplemented " + contextName + "_" + rxa + "_caseF_KF"); - debug("unimplemented " + contextName + "_" + rxa + "_caseJ_KJ"); - debug("unimplemented " + contextName + "_" + rxa + "_casec_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_caseet_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_caseec_RU"); - debug("unimplemented " + contextName + "_" + rxa + "_cases_RU"); - debug("unimplemented " + contextName + "_" + rxa + "_casearray_N"); - debug("unimplemented " + contextName + "_" + rxa + "_nesttype_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_nestpair_N"); - debug("unimplemented " + contextName + "_" + rxa + "_nestname_RU"); } } - private void parseClassMetadataBands() throws Pack200Exception { + private void parseClassMetadataBands(InputStream in, int[] classAttrCalls) throws Pack200Exception, IOException { String[] RxA = new String[] { "RVA", "RIA" }; AttributeLayout rvaLayout = attrMap.getAttributeLayout( @@ -695,38 +932,26 @@ AttributeLayout.CONTEXT_CLASS); int rvaCount = SegmentUtils.countMatches(classFlags, rvaLayout); int riaCount = SegmentUtils.countMatches(classFlags, riaLayout); - if (rvaCount > 0 || riaCount > 0) { - throw new Error("Class metadata not handled"); + int[] RxACount = new int[] { rvaCount, riaCount }; + int[] backwardsCalls = new int[] {0, 0}; + if(rvaCount > 0) { + backwardsCalls[0] = classAttrCalls[0]; + if(riaCount > 0) { + backwardsCalls[1] = classAttrCalls[1]; + } + } else if (riaCount > 0) { + backwardsCalls[1] = classAttrCalls[0]; } - // AttributeLayout layout = - // map.get(RuntimeVisibleAnnotations,class/field/method as int) - // foreachheader ... - // if layout.matches(header[n] or whatever) - String contextName = "class"; - for (int i = 0; i < RxA.length; i++) { - String rxa = RxA[i]; - if (rxa.indexOf("P") >= 0) { - debug("unimplemented " + contextName + "_" + rxa + "_param_NB"); + MetadataBandGroup[] mbgs = parseMetadata(in, RxA, RxACount, backwardsCalls, "class"); + Iterator rvaAttributesIterator = mbgs[0].getAttributes().iterator(); + Iterator riaAttributesIterator = mbgs[1].getAttributes().iterator(); + for (int i = 0; i < classFlags.length; i++) { + if(rvaLayout.matches(classFlags[i])) { + classAttributes[i].add(rvaAttributesIterator.next()); } - if (!rxa.equals("AD")) { - debug("unimplemented " + contextName + "_" + rxa + "_anno_N"); - debug("unimplemented " + contextName + "_" + rxa + "_type_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_pair_N"); - debug("unimplemented " + contextName + "_" + rxa + "_name_RU"); + if(riaLayout.matches(classFlags[i])) { + classAttributes[i].add(riaAttributesIterator.next()); } - debug("unimplemented " + contextName + "_" + rxa + "_T"); - debug("unimplemented " + contextName + "_" + rxa + "_caseI_KI"); - debug("unimplemented " + contextName + "_" + rxa + "_caseD_KD"); - debug("unimplemented " + contextName + "_" + rxa + "_caseF_KF"); - debug("unimplemented " + contextName + "_" + rxa + "_caseJ_KJ"); - debug("unimplemented " + contextName + "_" + rxa + "_casec_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_caseet_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_caseec_RU"); - debug("unimplemented " + contextName + "_" + rxa + "_cases_RU"); - debug("unimplemented " + contextName + "_" + rxa + "_casearray_N"); - debug("unimplemented " + contextName + "_" + rxa + "_nesttype_RS"); - debug("unimplemented " + contextName + "_" + rxa + "_nestpair_N"); - debug("unimplemented " + contextName + "_" + rxa + "_nestname_RU"); } } Index: src/main/java/org/apache/harmony/pack200/bytecode/ExceptionTableEntry.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/ExceptionTableEntry.java (revision 565676) +++ src/main/java/org/apache/harmony/pack200/bytecode/ExceptionTableEntry.java (working copy) @@ -20,6 +20,7 @@ import java.io.IOException; public class ExceptionTableEntry { + public int catchType; public int endPC; public int handlerPC; Index: src/main/java/org/apache/harmony/pack200/bytecode/AnnotationDefaultAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/AnnotationDefaultAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/AnnotationDefaultAttribute.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * AnnotationDefault attribute + */ +public class AnnotationDefaultAttribute extends AnnotationsAttribute { + + private ElementValue element_value; + + public AnnotationDefaultAttribute(ElementValue element_value) { + super("AnnotationDefault"); + this.element_value = element_value; + } + + protected int getLength() { + return element_value.getLength(); + } + + protected void writeBody(DataOutputStream dos) throws IOException { + element_value.writeBody(dos); + } + + protected void resolve(ClassConstantPool pool) { + super.resolve(pool); + element_value.resolve(pool); + } + + public String toString() { + return "AnnotationDefault: " + element_value; + } + +} Index: src/main/java/org/apache/harmony/pack200/bytecode/AnnotationsAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/AnnotationsAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/AnnotationsAttribute.java @@ -0,0 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +/** + * Abstract superclass for Annotations attributes + */ +public abstract class AnnotationsAttribute extends Attribute { + + + /** + * Class to represent the annotation structure for class file attributes + */ + public static class Annotation { + + private int num_pairs; + private CPUTF8[] element_names; + private ElementValue[] element_values; + private CPUTF8 type; + + // Resolved values + private int type_index; + private int[] name_indexes; + + + public Annotation(int num_pairs, CPUTF8 type, CPUTF8[] element_names, ElementValue[] element_values) { + this.num_pairs = num_pairs; + this.type = type; + this.element_names = element_names; + this.element_values = element_values; + } + + public int getLength() { + int length = 4; + for (int i = 0; i < num_pairs; i++) { + length += 2; + length += element_values[i].getLength(); + } + return length; + } + + public void resolve(ClassConstantPool pool) { + type.resolve(pool); + type_index = pool.indexOf(type); + name_indexes = new int[num_pairs]; + for (int i = 0; i < element_names.length; i++) { + element_names[i].resolve(pool); + name_indexes[i] = pool.indexOf(element_names[i]); + element_values[i].resolve(pool); + } + } + + public void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(type_index); + dos.writeShort(num_pairs); + for (int i = 0; i < num_pairs; i++) { + dos.writeShort(name_indexes[i]); + element_values[i].writeBody(dos); + } + } + + } + + public static class ElementValue { + + private Object value; + private int tag; + + // resolved value index if it's a constant + private int constant_value_index = -1; + + public ElementValue(int tag, Object value) { + this.tag = tag; + this.value = value; + } + + public void resolve(ClassConstantPool pool) { + if(value instanceof CPConstant) { + ((CPConstant)value).resolve(pool); + constant_value_index = pool.indexOf((CPConstant)value); + } else if (value instanceof CPClass) { + ((CPClass)value).resolve(pool); + constant_value_index = pool.indexOf((CPClass)value); + } else if (value instanceof CPNameAndType) { + ((CPNameAndType)value).resolve(pool); + } else if (value instanceof Annotation) { + ((Annotation)value).resolve(pool); + } else if (value instanceof ElementValue[]) { + ElementValue[] nestedValues = (ElementValue[])value; + for (int i = 0; i < nestedValues.length; i++) { + nestedValues[i].resolve(pool); + } + } + } + + public void writeBody(DataOutputStream dos) throws IOException { + dos.writeByte(tag); + if(constant_value_index != -1) { + dos.writeShort(constant_value_index); + } else if (value instanceof CPNameAndType) { + ((CPNameAndType)value).writeBody(dos); + } else if (value instanceof Annotation) { + ((Annotation)value).writeBody(dos); + } else if (value instanceof ElementValue[]) { + ElementValue[] nestedValues = (ElementValue[])value; + for (int i = 0; i < nestedValues.length; i++) { + nestedValues[i].writeBody(dos); + } + } + } + + public int getLength() { + switch(tag) { + case 'B': + case 'C': + case 'D': + case 'F': + case 'I': + case 'J': + case 'S': + case 'Z': + case 'c': + return 3; + case 'e': + return 5; + case '[': + int length = 3; + ElementValue[] nestedValues = (ElementValue[])value; + for (int i = 0; i < nestedValues.length; i++) { + length += nestedValues[i].getLength(); + } + return length; + case '@': + return (1 + ((Annotation)value).getLength()); + } + return 0; + } + } + + public AnnotationsAttribute(String attributeName) { + super(attributeName); + } + + + +} Index: src/main/java/org/apache/harmony/pack200/bytecode/EnclosingMethodAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/EnclosingMethodAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/EnclosingMethodAttribute.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class EnclosingMethodAttribute extends Attribute { + + private int class_index; + private int method_index; + private CPClass cpClass; + private CPMethod cpMethod; + + public EnclosingMethodAttribute(CPClass cpClass, CPMethod cpMethod) { + super("EnclosingMethod"); + this.cpClass = cpClass; + this.cpMethod = cpMethod; + } + + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.Attribute#getLength() + */ + protected int getLength() { + return 4; + } + + protected void resolve(ClassConstantPool pool) { + super.resolve(pool); + cpClass.resolve(pool); + class_index = pool.indexOf(cpClass); + cpMethod.resolve(pool); + method_index = pool.indexOf(cpMethod); + } + + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.Attribute#writeBody(java.io.DataOutputStream) + */ + protected void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(class_index); + dos.writeShort(method_index); + } + + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.ClassFileEntry#toString() + */ + public String toString() { + return "EnclosingMethod"; + } + +} Index: src/main/java/org/apache/harmony/pack200/bytecode/LineNumberTableAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/LineNumberTableAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/LineNumberTableAttribute.java @@ -0,0 +1,51 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class LineNumberTableAttribute extends Attribute { + + private int line_number_table_length; + private int[] start_pcs; + private int[] line_numbers; + + public LineNumberTableAttribute(int line_number_table_length, int[] start_pcs, int[] line_numbers) { + super("LineNumberTable"); + this.line_number_table_length = line_number_table_length; + this.start_pcs = start_pcs; + this.line_numbers = line_numbers; + } + + protected int getLength() { + return 2 + (4 * line_number_table_length); + } + + protected void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(line_number_table_length); + for (int i = 0; i < line_number_table_length; i++) { + dos.writeShort(start_pcs[i]); + dos.writeShort(line_numbers[i]); + } + } + + public String toString() { + return "LineNumberTable: " + line_number_table_length + " lines"; + } + +} Index: src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTableAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTableAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTableAttribute.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class LocalVariableTableAttribute extends Attribute { + + + private int local_variable_table_length; + private int[] start_pcs; + private int[] lengths; + private int[] name_indexes; + private int[] descriptor_indexes; + private int[] indexes; + private CPUTF8[] names; + private CPUTF8[] descriptors; + + public LocalVariableTableAttribute(int local_variable_table_length, + int[] start_pcs, int[] lengths, CPUTF8[] names, + CPUTF8[] descriptors, int[] indexes) { + super("LocalVariableTable"); + this.local_variable_table_length = local_variable_table_length; + this.start_pcs = start_pcs; + this.lengths = lengths; + this.names = names; + this.descriptors = descriptors; + this.indexes = indexes; + } + + protected int getLength() { + return 2 + (10 * local_variable_table_length); + } + + protected void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(local_variable_table_length); + for (int i = 0; i < local_variable_table_length; i++) { + dos.writeShort(start_pcs[i]); + dos.writeShort(lengths[i]); + dos.writeShort(name_indexes[i]); + dos.writeShort(descriptor_indexes[i]); + dos.writeShort(indexes[i]); + } + } + + protected void resolve(ClassConstantPool pool) { + super.resolve(pool); + name_indexes = new int[local_variable_table_length]; + descriptor_indexes = new int[local_variable_table_length]; + for (int i = 0; i < local_variable_table_length; i++) { + names[i].resolve(pool); + descriptors[i].resolve(pool); + name_indexes[i] = pool.indexOf(names[i]); + descriptor_indexes[i] = pool.indexOf(descriptors[i]); + } + } + + public String toString() { + return "LocalVariableTable: " + + local_variable_table_length + " varaibles"; + } + +} Index: src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTypeTableAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTypeTableAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/LocalVariableTypeTableAttribute.java @@ -0,0 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class LocalVariableTypeTableAttribute extends Attribute { + + + private int local_variable_type_table_length; + private int[] start_pcs; + private int[] lengths; + private int[] name_indexes; + private int[] signature_indexes; + private int[] indexes; + private CPUTF8[] names; + private CPUTF8[] signatures; + + public LocalVariableTypeTableAttribute(int local_variable_type_table_length, + int[] start_pcs, int[] lengths, CPUTF8[] names, + CPUTF8[] signatures, int[] indexes) { + super("LocalVariableTypeTable"); + this.local_variable_type_table_length = local_variable_type_table_length; + this.start_pcs = start_pcs; + this.lengths = lengths; + this.names = names; + this.signatures = signatures; + this.indexes = indexes; + } + + protected int getLength() { + return 2 + (10 * local_variable_type_table_length); + } + + protected void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(local_variable_type_table_length); + for (int i = 0; i < local_variable_type_table_length; i++) { + dos.writeShort(start_pcs[i]); + dos.writeShort(lengths[i]); + dos.writeShort(name_indexes[i]); + dos.writeShort(signature_indexes[i]); + dos.writeShort(indexes[i]); + } + } + + protected void resolve(ClassConstantPool pool) { + super.resolve(pool); + name_indexes = new int[local_variable_type_table_length]; + signature_indexes = new int[local_variable_type_table_length]; + for (int i = 0; i < local_variable_type_table_length; i++) { + names[i].resolve(pool); + signatures[i].resolve(pool); + name_indexes[i] = pool.indexOf(names[i]); + signature_indexes[i] = pool.indexOf(signatures[i]); + } + } + + public String toString() { + return "LocalVariableTypeTable: " + + local_variable_type_table_length + " varaibles"; + } + +} Index: src/main/java/org/apache/harmony/pack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class RuntimeVisibleorInvisibleAnnotationsAttribute extends AnnotationsAttribute { + + private int num_annotations; + private Annotation[] annotations; + private String name; + + public RuntimeVisibleorInvisibleAnnotationsAttribute(String name, Annotation[] annotations) { + super(name); + this.name = name; + this.num_annotations = annotations.length; + this.annotations = annotations; + } + + protected int getLength() { + int length = 2; + for (int i = 0; i < num_annotations; i++) { + length += annotations[i].getLength(); + } + return length; + } + + protected void resolve(ClassConstantPool pool) { + super.resolve(pool); + for (int i = 0; i < annotations.length; i++) { + annotations[i].resolve(pool); + } + } + + protected void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(num_annotations); + for (int i = 0; i < num_annotations; i++) { + annotations[i].writeBody(dos); + } + } + + public String toString() { + return name + ": " + num_annotations + " annotations"; + } + +} Index: src/main/java/org/apache/harmony/pack200/bytecode/RuntimeVisibleorInvisibleParameterAnnotationsAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/RuntimeVisibleorInvisibleParameterAnnotationsAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/RuntimeVisibleorInvisibleParameterAnnotationsAttribute.java @@ -0,0 +1,95 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class RuntimeVisibleorInvisibleParameterAnnotationsAttribute extends AnnotationsAttribute { + + private int num_parameters; + private ParameterAnnotation[] parameter_annotations; + private String name; + + public RuntimeVisibleorInvisibleParameterAnnotationsAttribute(String name, ParameterAnnotation[] parameter_annotations) { + super(name); + this.name = name; + this.num_parameters = parameter_annotations.length; + this.parameter_annotations = parameter_annotations; + } + + protected int getLength() { + int length = 1; + for (int i = 0; i < num_parameters; i++) { + length += parameter_annotations[i].getLength(); + } + return length; + } + + protected void resolve(ClassConstantPool pool) { + super.resolve(pool); + for (int i = 0; i < parameter_annotations.length; i++) { + parameter_annotations[i].resolve(pool); + } + } + + protected void writeBody(DataOutputStream dos) throws IOException { + dos.writeByte(num_parameters); + for (int i = 0; i < num_parameters; i++) { + parameter_annotations[i].writeBody(dos); + } + } + + public String toString() { + return name + ": " + num_parameters + " parameter annotations"; + } + + + public static class ParameterAnnotation { + + private Annotation[] annotations; + private int num_annotations; + + public ParameterAnnotation(Annotation[] annotations) { + this.num_annotations = annotations.length; + this.annotations = annotations; + } + + public void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(num_annotations); + for (int i = 0; i < annotations.length; i++) { + annotations[i].writeBody(dos); + } + } + + public void resolve(ClassConstantPool pool) { + for (int i = 0; i < annotations.length; i++) { + annotations[i].resolve(pool); + } + } + + public int getLength() { + int length = 2; + for (int i = 0; i < annotations.length; i++) { + length += annotations[i].getLength(); + } + return length; + } + + } + +} Index: src/main/java/org/apache/harmony/pack200/bytecode/SignatureAttribute.java =================================================================== --- src/main/java/org/apache/harmony/pack200/bytecode/SignatureAttribute.java +++ src/main/java/org/apache/harmony/pack200/bytecode/SignatureAttribute.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.bytecode; + +import java.io.DataOutputStream; +import java.io.IOException; + +public class SignatureAttribute extends Attribute { + + private int signature_index; + private CPUTF8 signature; + + public SignatureAttribute(CPUTF8 value) { + super("Signature"); + this.signature = value; + } + + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.Attribute#getLength() + */ + protected int getLength() { + return 2; + } + + protected void resolve(ClassConstantPool pool) { + super.resolve(pool); + signature.resolve(pool); + signature_index = pool.indexOf(signature); + } + + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.Attribute#writeBody(java.io.DataOutputStream) + */ + protected void writeBody(DataOutputStream dos) throws IOException { + dos.writeShort(signature_index); + } + + /* (non-Javadoc) + * @see org.apache.harmony.pack200.bytecode.ClassFileEntry#toString() + */ + public String toString() { + // TODO Auto-generated method stub + return "Signature: " + signature; + } + +} Index: src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java =================================================================== --- src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java +++ src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java @@ -0,0 +1,232 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +import org.apache.harmony.pack200.bytecode.AnnotationDefaultAttribute; +import org.apache.harmony.pack200.bytecode.Attribute; +import org.apache.harmony.pack200.bytecode.CPDouble; +import org.apache.harmony.pack200.bytecode.CPFloat; +import org.apache.harmony.pack200.bytecode.CPInteger; +import org.apache.harmony.pack200.bytecode.CPLong; +import org.apache.harmony.pack200.bytecode.CPNameAndType; +import org.apache.harmony.pack200.bytecode.CPUTF8; +import org.apache.harmony.pack200.bytecode.RuntimeVisibleorInvisibleAnnotationsAttribute; +import org.apache.harmony.pack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute; +import org.apache.harmony.pack200.bytecode.AnnotationsAttribute.Annotation; +import org.apache.harmony.pack200.bytecode.AnnotationsAttribute.ElementValue; +import org.apache.harmony.pack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute.ParameterAnnotation; + +/** + * Group of metadata bands, e.g. class_RVA_bands, method_AD_bands etc + */ +public class MetadataBandGroup { + + private String type; + + public MetadataBandGroup(String type) { + this.type = type; + } + + private List attributes; + + public int[] param_NB; + public int[] anno_N; + public CPUTF8[][] type_RS; + public int[][] pair_N; + public CPUTF8[] name_RU; + public int[] T; + public CPInteger[] caseI_KI; + public CPDouble[] caseD_KD; + public CPFloat[] caseF_KF; + public CPLong[] caseJ_KJ; + public CPUTF8[] casec_RS; + public String[] caseet_RS; + public String[] caseec_RU; + public CPUTF8[] cases_RU; + public int[] casearray_N; + public CPUTF8[] nesttype_RS; + public int[] nestpair_N; + public CPUTF8[] nestname_RU; + + private Iterator caseI_Iterator; + + private Iterator caseD_Iterator; + + private Iterator caseF_Iterator; + + private Iterator caseJ_Iterator; + + private Iterator casec_Iterator; + + private Iterator caseet_Iterator; + + private Iterator caseec_Iterator; + + private Iterator cases_Iterator; + + private Iterator casearray_Iterator; + + private Iterator T_iterator; + + private Iterator nesttype_RS_Iterator; + + private Iterator nestpair_N_Iterator; + + private Iterator nestname_RU_Iterator; + + private Iterator anno_N_Iterator; + + private Iterator type_RS_Iterator; + + private Iterator pair_N_Iterator; + + + public List getAttributes() { + if(attributes == null) { + attributes = new ArrayList(); + if(name_RU != null) { + Iterator name_RU_Iterator = Arrays.asList(name_RU).iterator(); + if(!type.equals("AD")) { + T_iterator = Arrays.asList(boxArray(T)).iterator(); + } + caseI_Iterator = Arrays.asList(caseI_KI).iterator(); + caseD_Iterator = Arrays.asList(caseD_KD).iterator(); + caseF_Iterator = Arrays.asList(caseF_KF).iterator(); + caseJ_Iterator = Arrays.asList(caseJ_KJ).iterator(); + casec_Iterator = Arrays.asList(casec_RS).iterator(); + caseet_Iterator = Arrays.asList(caseet_RS).iterator(); + caseec_Iterator = Arrays.asList(caseec_RU).iterator(); + cases_Iterator = Arrays.asList(cases_RU).iterator(); + casearray_Iterator = Arrays.asList(boxArray(casearray_N)).iterator(); + nesttype_RS_Iterator = Arrays.asList(nesttype_RS).iterator(); + nestpair_N_Iterator = Arrays.asList(boxArray(nestpair_N)).iterator(); + nestname_RU_Iterator = Arrays.asList(nestname_RU).iterator(); + if (type.equals("RVA") || type.equals("RIA")) { + for (int i = 0; i < anno_N.length; i++) { + attributes.add(getAttribute(anno_N[i], type_RS[i], pair_N[i], name_RU_Iterator)); + } + } else if (type.equals("RVPA") || type.equals("RIPA")) { + anno_N_Iterator = Arrays.asList(boxArray(anno_N)).iterator(); + type_RS_Iterator = Arrays.asList(type_RS).iterator(); + pair_N_Iterator = Arrays.asList(pair_N).iterator(); + for (int i = 0; i < param_NB.length; i++) { + attributes.add(getParameterAttribute(param_NB[i], name_RU_Iterator)); + } + } else { // type.equals("AD") + for (int i = 0; i < T.length; i++) { + attributes.add(new AnnotationDefaultAttribute(new ElementValue(T[i], getNextValue(T[i])))); + } + } + } + } + return attributes; + } + + + private Attribute getAttribute(int numAnnotations, CPUTF8[] types, int[] pairCounts, Iterator namesIterator) { + Annotation[] annotations = new Annotation[numAnnotations]; + for (int i = 0; i < numAnnotations; i++) { + annotations[i] = getAnnotation(types[i], pairCounts[i], namesIterator); + } + return new RuntimeVisibleorInvisibleAnnotationsAttribute(type + .equals("RVA") ? "RuntimeVisibleAnnotations" + : "RuntimeInvisibleAnnotations", + annotations); + } + + private Attribute getParameterAttribute(int numParameters, Iterator namesIterator ) { + ParameterAnnotation[] parameter_annotations = new ParameterAnnotation[numParameters]; + for (int i = 0; i < numParameters; i++) { + int numAnnotations = ((Integer)anno_N_Iterator.next()).intValue(); + int[] pairCounts = (int[])pair_N_Iterator.next(); + Annotation[] annotations = new Annotation[numAnnotations]; + for (int j = 0; j < annotations.length; j++) { + annotations[j] = getAnnotation((CPUTF8)type_RS_Iterator.next(), pairCounts[j], namesIterator); + } + parameter_annotations[i] = new ParameterAnnotation(annotations); + } + return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute(type + .equals("RVA") ? "RuntimeVisibleParameterAnnotations" + : "RuntimeInvisibleParameterAnnotations", + parameter_annotations); + } + + + private Annotation getAnnotation(CPUTF8 type, int pairCount, Iterator namesIterator) { + CPUTF8[] elementNames = new CPUTF8[pairCount]; + ElementValue[] elementValues = new ElementValue[pairCount]; + for (int j = 0; j < elementNames.length; j++) { + elementNames[j] = (CPUTF8) namesIterator.next(); + int t = ((Integer)T_iterator.next()).intValue(); + elementValues[j] = new ElementValue(t, getNextValue(t)); + } + return new Annotation(pairCount, type, elementNames, elementValues); + } + + private Object getNextValue(int t) { + switch (t) { + case 'B': + case 'C': + case 'I': + case 'S': + case 'Z': + return caseI_Iterator.next(); + case 'D': + return caseD_Iterator.next(); + case 'F': + return caseF_Iterator.next(); + case 'J': + return caseJ_Iterator.next(); + case 'c': + return casec_Iterator.next(); + case 'e': + // TODO: check this - it may not work if the first string already has a colon in it + String enumString = caseet_Iterator.next() + ":" + caseec_Iterator.next(); + return new CPNameAndType(enumString); + case 's': + return cases_Iterator.next(); + case '[': + int arraySize = ((Integer)casearray_Iterator.next()).intValue(); + ElementValue[] nestedArray = new ElementValue[arraySize]; + for (int i = 0; i < arraySize; i++) { + int nextT = ((Integer)T_iterator.next()).intValue(); + nestedArray[i] = new ElementValue(nextT, getNextValue(nextT)); + } + return nestedArray; + case '@': + CPUTF8 type = (CPUTF8) nesttype_RS_Iterator.next(); + int numPairs = ((Integer)nestpair_N_Iterator.next()).intValue(); + + return getAnnotation(type, numPairs, nestname_RU_Iterator); + } + return null; + } + + private Integer[] boxArray(int[] unboxed) { + Integer[] boxed = new Integer[unboxed.length]; + for (int i = 0; i < boxed.length; i++) { + boxed[i] = new Integer(unboxed[i]); + } + return boxed; + } + +} \ No newline at end of file Index: src/test/java/org/apache/harmony/pack200/tests/ClassBandsTest.java =================================================================== --- src/test/java/org/apache/harmony/pack200/tests/ClassBandsTest.java (revision 588229) +++ src/test/java/org/apache/harmony/pack200/tests/ClassBandsTest.java (working copy) @@ -32,6 +32,7 @@ private String[] cpClasses; private String[] cpDescriptor; + private String[] cpUTF8; public class MockCpBands extends CpBands { @@ -46,7 +47,30 @@ public String[] getCpDescriptor() { return cpDescriptor; } - + + public String[] getCpUTF8() { + return cpUTF8; + } + + public int[] getCpInt() { + return new int[0]; + } + + public double[] getCpDouble() { + return new double[0]; + } + + public long[] getCpLong() { + return new long[0]; + } + + public float[] getCpFloat() { + return new float[0]; + } + + public String[] getCpSignature() { + return new String[0]; + } } public class MockSegment extends AbstractBandsTestCase.MockSegment { @@ -52,8 +76,7 @@ public class MockSegment extends AbstractBandsTestCase.MockSegment { protected CpBands getCpBands() { return new MockCpBands(this); - } - + } } @@ -63,6 +86,7 @@ public void testSimple() throws IOException, Pack200Exception { cpClasses = new String[] { "Class1", "Class2", "Class3", "Interface1", "Interface2" }; cpDescriptor = new String[0]; + cpUTF8 = new String[0]; byte[] classThis = Codec.DELTA5.encode(1, 0); byte[] classSuper = Codec.DELTA5.encode(2, 0); byte[] classInterfaceCount = Codec.DELTA5.encode(2, 0); @@ -99,6 +123,7 @@ public void testWithMethods() throws Pack200Exception, IOException { cpClasses = new String[] { "Class1", "Class2", "Class3" }; cpDescriptor = new String[] {"method1", "method2", "method3"}; + cpUTF8 = new String[0]; byte[] classThis = Codec.DELTA5.encode(1, 0); byte[] classSuper = Codec.DELTA5.encode(2, 0); byte[] classInterfaceCount = Codec.DELTA5.encode(0, 0); Index: src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java =================================================================== --- src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java (revision 588229) +++ src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java (working copy) @@ -31,8 +31,11 @@ public class SegmentTest extends TestCase { public void testHelloWorld() throws Exception { - assertNotNull(Segment.parse(Segment.class - .getResourceAsStream("/org/apache/harmony/pack200/tests/HelloWorld.pack"))); + InputStream in = Segment.class + .getResourceAsStream("/org/apache/harmony/pack200/tests/HelloWorld.pack"); + Segment segment = Segment.parse(in); + assertNotNull(segment); + segment.writeJar(new JarOutputStream(new FileOutputStream(File.createTempFile("Hello", "World.jar"))), in); } public void testJustResources() throws Exception { @@ -80,6 +83,22 @@ .getResourceAsStream("/org/apache/harmony/pack200/tests/pack200.pack.gz"))); } + + // Test with an archive containing Harmony's JNDI module + public void testWithJNDIE1() throws Exception { + assertNotNull(Segment + .parse(Segment.class + .getResourceAsStream("/org/apache/harmony/pack200/tests/jndi-e1.pack.gz"))); + + } + + // Test with an archive containing Annotations + public void testWithAnnotations() throws Exception { + assertNotNull(Segment + .parse(Segment.class + .getResourceAsStream("/org/apache/harmony/pack200/tests/annotations.pack.gz"))); + + } public void testInterfaceOnly() throws Exception { assertNotNull(Segment