Index: src/main/java/org/apache/harmony/pack200/AttributeLayout.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/AttributeLayout.java (revision 576831)
+++ src/main/java/org/apache/harmony/pack200/AttributeLayout.java (working copy)
@@ -248,5 +248,18 @@
public String getName() {
return name;
}
+
+ public int numBackwardsCallables() {
+ int num = 0;
+ String[] split = layout.split("\\(");
+ if(split.length > 0) {
+ for (int i = 1; i < split.length; i++) {
+ if(split[i].startsWith("-") || split[i].startsWith("0")) {
+ num++;
+ }
+ }
+ }
+ return num;
+ }
}
Index: src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (revision 583385)
+++ src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (working copy)
@@ -16,10 +16,6 @@
*/
package org.apache.harmony.pack200;
-// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-// NOTE: Do not extract strings as messages; this code is still a
-// work-in-progress
-// NOTE: Also, don't get rid of 'else' statements for the hell of it ...
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
@@ -224,6 +220,12 @@
return null;
}
+ public AttributeLayout getAttributeLayout(int index, int context)
+ throws Pack200Exception {
+ Map map = layouts[context];
+ return (AttributeLayout) map.get(new Integer(index));
+ }
+
/**
* The map should not contain the same layout and name combination more than
* once for each context.
Index: src/main/java/org/apache/harmony/pack200/BHSDCodec.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/BHSDCodec.java (revision 576831)
+++ src/main/java/org/apache/harmony/pack200/BHSDCodec.java (working copy)
@@ -15,12 +15,12 @@
* limitations under the License.
*/
package org.apache.harmony.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
/**
* TODO Comment -- quite a lot can be nicked from Codec, since this was created
@@ -25,9 +25,7 @@
/**
* TODO Comment -- quite a lot can be nicked from Codec, since this was created
* from it
- *
- * @author Alex Blewitt
- *
+ *
*/
public final class BHSDCodec extends Codec {
@@ -155,13 +153,23 @@
x = in.read();
if (x == -1)
throw new EOFException("End of stream reached whilst decoding");
- z += x * Math.pow(h, n);
+ z += x * Math.pow(h, n);
n++;
} while (n < b & isHigh(x));
- long u = z;
- long twoPowS = (long)Math.pow(2, s);
- double twoPowSMinusOne = twoPowS-1;
+
+// TODO: Decide whether to use this algorithm instead (neater, possibly quicker but less easy to understand)
+// if (isSigned()) {
+// int u = ((1 << s) - 1);
+// if ((z & u) == u) {
+// z = z >>> s ^ -1L;
+// } else {
+// z = z - (z >>> s);
+// }
+// }
if(isSigned()) {
+ long u = z;
+ long twoPowS = (long)Math.pow(2, s);
+ double twoPowSMinusOne = twoPowS-1;
if(u % twoPowS < twoPowSMinusOne) {
if(cardinality < Math.pow(2, 32)) {
z = (long) (u - (Math.floor(u/ twoPowS)));
@@ -172,8 +180,8 @@
z = (long) (-Math.floor(u/ twoPowS) - 1);
}
}
- if (isDelta())
- z += last;
+ if (isDelta())
+ z += last;
return z;
}
@@ -196,6 +204,50 @@
public boolean encodes(long value) {
return (value >= smallest() && value <= largest());
}
+
+ public byte[] encode(long value, long last) throws Pack200Exception {
+ if (isDelta()) {
+ value -= last;
+ }
+ if (!encodes(value)) {
+ throw new Pack200Exception("The codec " + toString()
+ + " does not encode the value " + value);
+ }
+ long z = value;
+ if (isSigned()) {
+ if (z < 0) {
+ z = (-z << s) - 1;
+ } else {
+ if (s == 1) {
+ z = z << s;
+ } else {
+ z += (z - z % 3) / 3;
+ }
+ }
+ }
+ List byteList = new ArrayList();
+ for (int n = 0; n < b; n++) {
+ long byteN;
+ if (z < l) {
+ byteN = z;
+ } else {
+ byteN = z % h;
+ while (byteN < l)
+ byteN += h;
+ }
+ byteList.add(new Byte((byte) byteN));
+ if (byteN < l) {
+ break;
+ }
+ z -= byteN;
+ z /= h;
+ }
+ byte[] bytes = new byte[byteList.size()];
+ for (int i = 0; i < bytes.length; i++) {
+ bytes[i] = ((Byte) byteList.get(i)).byteValue();
+ }
+ return bytes;
+ }
/**
* Returns true if this codec is a delta codec
@@ -220,19 +272,15 @@
*/
public long largest() {
long result;
- if (isDelta()) {
- result = Long.MAX_VALUE;
+ // TODO This can probably be optimized into a better mathematical statement
+ if (s == 0) {
+ result = cardinality() - 1;
+ } else if (s == 1) {
+ result = cardinality() / 2 - 1;
+ } else if (s == 2) {
+ result = (3L * cardinality()) / 4 - 1;
} else {
- // TODO This can probably be optimized into a better mathematical statement
- if (s == 0) {
- result = cardinality() - 1;
- } else if (s == 1) {
- result = cardinality() / 2 - 1;
- } else if (s == 2) {
- result = (3L * cardinality()) / 4 - 1;
- } else {
- throw new Error("Unknown s value");
- }
+ throw new Error("Unknown s value");
}
return Math.min((s == 0 ? ((long) Integer.MAX_VALUE) << 1
: Integer.MAX_VALUE) - 1, result);
@@ -244,14 +292,10 @@
*/
public long smallest() {
long result;
- if (isDelta()) {
- result = Integer.MIN_VALUE;
+ if (isSigned()) {
+ result = -cardinality() / (1 << s);
} else {
- if (isSigned()) {
- result = -cardinality() / (1 << s);
- } else {
- result = 0;
- }
+ result = 0;
}
return Math.max(Integer.MIN_VALUE, result);
}
Index: src/main/java/org/apache/harmony/pack200/BandSet.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/BandSet.java (revision 583385)
+++ src/main/java/org/apache/harmony/pack200/BandSet.java (working copy)
@@ -16,6 +16,7 @@
*/
package org.apache.harmony.pack200;
+import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -36,7 +37,7 @@
}
/**
- * Decode a band and return an array of int[] values
+ * Decode a band and return an array of int values
*
* @param name
* the name of the band (primarily for logging/debugging
@@ -47,7 +48,7 @@
* the default codec for this band
* @param count
* the number of elements to read
- * @return an array of decoded int[] values
+ * @return an array of decoded int values
* @throws IOException
* if there is a problem reading from the underlying input
* stream
@@ -60,10 +61,6 @@
Pack200Exception {
// TODO Might be able to improve this directly.
int[] result = new int[count];
-
- // TODO We need to muck around in the scenario where the first value
- // read indicates
- // an uber-codec
long[] longResult = decodeBandLong(name, in, defaultCodec, count);
for (int i = 0; i < count; i++) {
result[i] = (int) longResult[i];
@@ -70,7 +67,28 @@
}
return result;
}
-
+
+ /**
+ * Decode a band and return an array of int[] values
+ *
+ * @param name
+ * the name of the band (primarily for logging/debugging
+ * purposes)
+ * @param in
+ * the InputStream to decode from
+ * @param defaultCodec
+ * the default codec for this band
+ * @param counts
+ * the numbers of elements to read for each int array within the
+ * array to be returned
+ * @return an array of decoded int[] values
+ * @throws IOException
+ * if there is a problem reading from the underlying input
+ * stream
+ * @throws Pack200Exception
+ * if there is a problem decoding the value or that the value is
+ * invalid
+ */
public int[][] decodeBandInt(String name, InputStream in, BHSDCodec defaultCodec, int[] counts) throws IOException, Pack200Exception {
int[][] result = new int[counts.length][];
int totalCount = 0;
@@ -90,7 +108,7 @@
}
/**
- * Decode a band and return an array of long[] values
+ * Decode a band and return an array of long values
*
* @param name
* the name of the band (primarily for logging/debugging
@@ -101,7 +119,7 @@
* the default codec for this band
* @param count
* the number of elements to read
- * @return an array of decoded long[] values
+ * @return an array of decoded long values
* @throws IOException
* if there is a problem reading from the underlying input
* stream
@@ -135,24 +153,39 @@
return codec.decode(count - 1, in, first);
}
}
+
+ public byte[] encodeBandLong(long[] data, BHSDCodec codec) throws IOException, Pack200Exception {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ for (int i = 0; i < data.length; i++) {
+ baos.write(codec.encode(data[i], i == 0 ? 0 : data[i-1]));
+ }
+ return baos.toByteArray();
+ }
public long[] parseFlags(String name, InputStream in, int count,
- BHSDCodec codec, boolean hasHi) throws IOException, Pack200Exception {
- return parseFlags(name, in, 1, new int[] { count }, (hasHi ? codec
- : null), codec)[0];
+ BHSDCodec codec, boolean hasHi) throws IOException,
+ Pack200Exception {
+ return parseFlags(name, in, new int[] { count },
+ (hasHi ? codec : null), codec)[0];
+ }
+
+ public long[][] parseFlags(String name, InputStream in, int counts[],
+ BHSDCodec codec, boolean hasHi) throws IOException,
+ Pack200Exception {
+ return parseFlags(name, in, counts, (hasHi ? codec : null), codec);
}
- public long[][] parseFlags(String name, InputStream in, int count,
- int counts[], BHSDCodec codec, boolean hasHi) throws IOException,
+ public long[] parseFlags(String name, InputStream in, int count,
+ BHSDCodec hiCodec, BHSDCodec loCodec) throws IOException,
Pack200Exception {
- return parseFlags(name, in, count, counts, (hasHi ? codec : null),
- codec);
+ return parseFlags(name, in, new int[] { count }, hiCodec, loCodec)[0];
}
- public long[][] parseFlags(String name, InputStream in, int count,
- int counts[], BHSDCodec hiCodec, BHSDCodec loCodec) throws IOException,
+ public long[][] parseFlags(String name, InputStream in, int counts[],
+ BHSDCodec hiCodec, BHSDCodec loCodec) throws IOException,
Pack200Exception {
// TODO Move away from decoding into a parseBand type structure
+ int count = counts.length;
if (count == 0) {
return new long[][] { {} };
}
@@ -182,7 +215,7 @@
* [0..reference.length-1].
*
* @param name
- * TODO
+ * the band name
* @param in
* the input stream to read from
* @param codec
@@ -247,12 +280,12 @@
}
// TODO Merge the decode and parsing of a multiple structure into one
String[] result1 = new String[sum];
- int[] decode = decodeBandInt(name, in, codec, sum);
+ int[] indices = decodeBandInt(name, in, codec, sum);
for (int i1 = 0; i1 < sum; i1++) {
- int index = decode[i1];
+ int index = indices[i1];
if (index < 0 || index >= reference.length)
throw new Pack200Exception(
- "Something has gone wrong during parsing references");
+ "Something has gone wrong during parsing references, index = " + index + ", array size = " + reference.length);
result1[i1] = reference[index];
}
String[] refs = result1;
Index: src/main/java/org/apache/harmony/pack200/BcBands.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/BcBands.java (revision 583385)
+++ src/main/java/org/apache/harmony/pack200/BcBands.java (working copy)
@@ -21,7 +21,6 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
-import java.util.Arrays;
import org.apache.harmony.pack200.bytecode.ByteCode;
import org.apache.harmony.pack200.bytecode.CodeAttribute;
@@ -31,8 +30,11 @@
*/
public class BcBands extends BandSet {
- // the bytecodes for each method in each class as they come (i.e. in their packed format)
+ // The bytecodes for each method in each class as they come (i.e. in their packed format)
private byte[][][] methodByteCodePacked;
+
+ // The bands
+ // TODO: Haven't resolved references yet. Do we want to?
private int[] bcCaseCount;
private int[][] bcCaseValue;
private int[] bcByte;
@@ -137,7 +139,6 @@
for (int i = 0; i < codes.length; i++) {
codes[i] = methodByteCodePacked[c][m][i] & 0xff;
}
- debug(Arrays.toString(codes));
for (int i = 0; i < methodByteCodePacked[c][m].length; i++) {
int codePacked = 0xff & methodByteCodePacked[c][m][i];
// TODO a lot of this needs to be encapsulated in the
@@ -467,6 +468,5 @@
public int[][] getBcEscByte() {
return bcEscByte;
- }
-
+ }
}
Index: src/main/java/org/apache/harmony/pack200/ClassBands.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/ClassBands.java (revision 583385)
+++ src/main/java/org/apache/harmony/pack200/ClassBands.java (working copy)
@@ -20,8 +20,6 @@
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.bytecode.CPClass;
import org.apache.harmony.pack200.bytecode.ConstantValueAttribute;
@@ -32,8 +30,6 @@
*/
public class ClassBands extends BandSet {
- private int classAttrCount;
-
private int[] classFieldCount;
private long[] classFlags;
@@ -45,6 +41,8 @@
private String[] classSuper;
private String[] classThis;
+
+ private ArrayList[] classAttributes;
private int[] codeHandlerCount;
@@ -67,7 +65,7 @@
private String[][] methodDescr;
private ExceptionsAttribute[][] methodExceptions;
-
+
private long[][] methodFlags;
private AttributeLayoutMap attrMap;
@@ -74,10 +72,14 @@
private CpBands cpBands;
- private int codeAttrCount;
+ private SegmentOptions options;
+
+ private int classCount;
+ private int[] methodAttrCalls;
+
/**
- * @param header
+ * @param segment
*/
public ClassBands(Segment segment) {
super(segment);
@@ -84,6 +86,9 @@
this.attrMap = segment.getAttrDefinitionBands()
.getAttributeDefinitionMap();
this.cpBands = segment.getCpBands();
+ this.classCount = header.getClassCount();
+ this.options = header.getOptions();
+
}
/*
@@ -107,13 +112,10 @@
cpBands.getCpClass());
classSuper = parseReferences("class_super", in, Codec.DELTA5,
classCount, cpBands.getCpClass());
- classInterfaces = new String[classCount][];
int[] classInterfaceLengths = decodeBandInt("class_interface_count",
in, Codec.DELTA5, classCount);
- // for (int i = 0; i < classCount; i++) {
classInterfaces = parseReferences("class_interface", in, Codec.DELTA5,
classInterfaceLengths, cpBands.getCpClass());
- // }
classFieldCount = decodeBandInt("class_field_count", in, Codec.DELTA5,
classCount);
classMethodCount = decodeBandInt("class_method_count", in,
@@ -127,13 +129,11 @@
private void parseFieldBands(InputStream in) throws IOException,
Pack200Exception {
- int classCount = header.getClassCount();
- SegmentOptions options = header.getOptions();
fieldDescr = parseReferences("field_descr", in, Codec.DELTA5,
classFieldCount, cpBands.getCpDescriptor());
- fieldFlags = parseFlags("field_flags", in, classCount, classFieldCount,
+ fieldFlags = parseFlags("field_flags", in, classFieldCount,
Codec.UNSIGNED5, options.hasFieldFlagsHi());
- for (int i = 0; i < classCount; i++) {
+ for (int i = 0; i < fieldFlags.length; i++) {
for (int j = 0; j < fieldFlags[i].length; j++) {
long flag = fieldFlags[i][j];
if ((flag & (1 << 16)) != 0)
@@ -140,36 +140,47 @@
fieldAttrCount++;
}
}
- if (fieldAttrCount > 0)
- throw new Error(
- "There are attribute flags, and I don't know what to do with them");
- debug("unimplemented field_attr_indexes");
- debug("unimplemented field_attr_calls");
+ 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[] fieldAttrCalls = decodeBandInt("field_attr_calls", in, Codec.UNSIGNED5, callCount);
AttributeLayout layout = attrMap.getAttributeLayout("ConstantValue",
AttributeLayout.CONTEXT_FIELD);
- Codec codec = layout.getCodec();
- fieldAttributes = new ArrayList[classCount][];
- for (int i = 0; i < classCount; i++) {
- fieldAttributes[i] = new ArrayList[fieldFlags[i].length];
- for (int j = 0; j < fieldFlags[i].length; j++) {
- fieldAttributes[i][j] = new ArrayList();
- long flag = fieldFlags[i][j];
- if (layout.matches(flag)) {
- // we've got a value to read
- long result = codec.decode(in);
- String desc = fieldDescr[i][j];
- int colon = desc.indexOf(':');
- // String name = desc.substring(0, colon);
- String type = desc.substring(colon + 1);
- // TODO Got to get better at this ... in any case, it should
- // be e.g. KIB or KIH
- if (type.equals("B") || type.equals("H"))
- type = "I";
- Object value = layout.getValue(result, type, cpBands
- .getConstantPool());
- fieldAttributes[i][j]
- .add(new ConstantValueAttribute(value));
- debug("Processed value " + value + " for ConstantValue");
+ int constantCount = SegmentUtils.countMatches(fieldFlags, layout);
+ if(constantCount > 0) {
+ int[] field_constantValue_KQ = decodeBandInt("field_ConstantValue_KQ", in, Codec.UNSIGNED5, constantCount);
+ int index = 0;
+ fieldAttributes = new ArrayList[classCount][];
+ for (int i = 0; i < classCount; i++) {
+ fieldAttributes[i] = new ArrayList[fieldFlags[i].length];
+ for (int j = 0; j < fieldFlags[i].length; j++) {
+ fieldAttributes[i][j] = new ArrayList();
+ long flag = fieldFlags[i][j];
+ if (layout.matches(flag)) {
+ // we've got a value to read
+ long result = field_constantValue_KQ[index];
+ String desc = fieldDescr[i][j];
+ int colon = desc.indexOf(':');
+ // String name = desc.substring(0, colon);
+ String type = desc.substring(colon + 1);
+ // TODO Got to get better at this ... in any case, it should
+ // be e.g. KIB or KIH
+ if (type.equals("B") || type.equals("H"))
+ type = "I";
+ Object value = layout.getValue(result, type, cpBands
+ .getConstantPool());
+ fieldAttributes[i][j]
+ .add(new ConstantValueAttribute(value));
+ debug("Processed value " + value + " for ConstantValue");
+ index++;
+ }
}
}
}
@@ -176,33 +187,37 @@
layout = attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE,
AttributeLayout.CONTEXT_FIELD);
- codec = layout.getCodec();
-// fieldAttributes = new ArrayList[classCount][];
- for (int i = 0; i < classCount; i++) {
-// fieldAttributes[i] = new ArrayList[fieldFlags[i].length];
- for (int j = 0; j < fieldFlags[i].length; j++) {
-// fieldAttributes[i][j] = new ArrayList();
- long flag = fieldFlags[i][j];
- if (layout.matches(flag)) {
- // we've got a value to read
- long result = codec.decode(in);
-// String desc = fieldDescr[i][j];
-// int colon = desc.indexOf(':');
-// // String name = desc.substring(0, colon);
-// String type = desc.substring(colon + 1);
-// // TODO Got to get better at this ... in any case, it should
-// // be e.g. KIB or KIH
-// if (type.equals("B") || type.equals("H"))
-// type = "I";
-// Object value = layout.getValue(result, type, cpBands
-// .getConstantPool());
-// fieldAttributes[i][j]
-// .add(new ConstantValueAttribute(value));
- debug("Found a signature attribute: " + result);
+ int signatureCount = SegmentUtils.countMatches(fieldFlags, layout);
+ if (signatureCount > 0) {
+ int[] fieldSignatureRS = decodeBandInt("field_Signature_RS", in, Codec.UNSIGNED5, signatureCount);
+ int index = 0;
+ fieldAttributes = new ArrayList[classCount][];
+ for (int i = 0; i < classCount; i++) {
+ fieldAttributes[i] = new ArrayList[fieldFlags[i].length];
+ for (int j = 0; j < fieldFlags[i].length; j++) {
+ fieldAttributes[i][j] = new ArrayList();
+ long flag = fieldFlags[i][j];
+ if (layout.matches(flag)) {
+ // we've got a signature attribute
+ long result = fieldSignatureRS[index];
+ String desc = fieldDescr[i][j];
+ int colon = desc.indexOf(':');
+ // String name = desc.substring(0, colon);
+ String type = desc.substring(colon + 1);
+ // TODO Got to get better at this ... in any case, it should
+ // be e.g. KIB or KIH
+ if (type.equals("B") || type.equals("H"))
+ type = "I";
+ Object value = layout.getValue(result, type, cpBands
+ .getConstantPool());
+ fieldAttributes[i][j]
+ .add(new ConstantValueAttribute(value));
+ index++;
+ debug("Found a signature attribute: " + result);
+ }
}
}
}
-// debug("unimplemented field_Signature_RS");
parseFieldMetadataBands();
}
@@ -208,12 +223,10 @@
private void parseMethodBands(InputStream in) throws IOException,
Pack200Exception {
- int classCount = header.getClassCount();
- SegmentOptions options = header.getOptions();
methodDescr = parseReferences("method_descr", in, Codec.MDELTA5,
classMethodCount, cpBands.getCpDescriptor());
- methodFlags = parseFlags("method_flags", in, classCount,
- classMethodCount, Codec.UNSIGNED5, options.hasMethodFlagsHi());
+ methodFlags = parseFlags("method_flags", in, classMethodCount,
+ Codec.UNSIGNED5, options.hasMethodFlagsHi());
for (int i = 0; i < classCount; i++) {
for (int j = 0; j < methodFlags[i].length; j++) {
long flag = methodFlags[i][j];
@@ -220,13 +233,18 @@
if ((flag & (1 << 16)) != 0)
methodAttrCount++;
}
+ }
+ int[] methodAttrCounts = decodeBandInt("method_attr_count", in, Codec.UNSIGNED5, methodAttrCount);
+ int[][] methodAttrIndexes = decodeBandInt("method_attr_indexes", in, Codec.UNSIGNED5, methodAttrCounts);
+ int callCount = 0;
+ for (int i = 0; i < methodAttrIndexes.length; i++) {
+ for (int j = 0; j < methodAttrIndexes[i].length; j++) {
+ int index = methodAttrIndexes[i][j];
+ AttributeLayout layout = attrMap.getAttributeLayout(index, AttributeLayout.CONTEXT_METHOD);
+ callCount += layout.numBackwardsCallables();
+ }
}
- if (methodAttrCount > 0)
- throw new Error(
- "There are method attribute flags, and I don't know what to do with them");
- debug("unimplemented method_attr_count");
- debug("unimplemented method_attr_indexes");
- debug("unimplemented method_attr_calls");
+ methodAttrCalls = decodeBandInt("code_attr_calls", in, Codec.UNSIGNED5, callCount);
// assign empty method attributes
methodAttributes = new ArrayList[classCount][];
for (int i = 0; i < classCount; i++) {
@@ -236,10 +254,41 @@
}
}
parseAttributeMethodExceptions(in);
- parseAttributeMethodSignature(in);
+ parseAttributeMethodSigntaure(in);
parseMethodMetadataBands();
}
+ private void parseAttributeMethodSigntaure(InputStream in) throws IOException, Pack200Exception {
+ AttributeLayout layout = attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE,
+ AttributeLayout.CONTEXT_METHOD);
+ int count = SegmentUtils.countMatches(methodFlags, layout);
+ long[] methodSignatureRS = decodeBandLong("method_signature_RS", in, Codec.UNSIGNED5, count);
+ int index = 0;
+ for (int i = 0; i < methodAttributes.length; i++) {
+ for (int j = 0; j < methodAttributes[i].length; j++) {
+ long flag = methodFlags[i][j];
+ if (layout.matches(flag)) {
+ // we've got a signature attribute
+ long result = methodSignatureRS[index];
+ String desc = methodDescr[i][j];
+ int colon = desc.indexOf(':');
+ // String name = desc.substring(0, colon);
+ String type = desc.substring(colon + 1);
+ // TODO Got to get better at this ... in any case, it should
+ // be e.g. KIB or KIH
+ if (type.equals("B") || type.equals("H"))
+ type = "I";
+ Object value = layout.getValue(result, type, cpBands
+ .getConstantPool());
+ methodAttributes[i][j]
+ .add(new ConstantValueAttribute(value));
+ index++;
+ debug("Found a signature attribute: " + result);
+ }
+ }
+ }
+ }
+
/**
* @param in
* @throws Pack200Exception
@@ -247,22 +296,13 @@
*/
private void parseAttributeMethodExceptions(InputStream in)
throws Pack200Exception, IOException {
- // TODO Should refactor this stuff into the layout somehow
- int classCount = header.getClassCount();
AttributeLayout layout = attrMap.getAttributeLayout("Exceptions",
AttributeLayout.CONTEXT_METHOD);
- Codec codec = layout.getCodec();
methodExceptions = new ExceptionsAttribute[classCount][];
- int[][] numExceptions = new int[classCount][];
- for (int i = 0; i < classCount; i++) {
- numExceptions[i] = new int[methodFlags[i].length];
- for (int j = 0; j < methodFlags[i].length; j++) {
- long flag = methodFlags[i][j];
- if (layout.matches(flag)) {
- numExceptions[i][j] = (int) codec.decode(in);
- }
- }
- }
+ int count = SegmentUtils.countMatches(methodFlags, layout);
+ int[] numExceptions = decodeBandInt("method_Exceptions_n", in, Codec.UNSIGNED5, count);
+ String[][] methodExceptionsRS = parseReferences("method_Exceptions_RC", in, Codec.UNSIGNED5, numExceptions, cpBands.getCpClass());
+ int index = 0;
for (int i = 0; i < classCount; i++) {
methodExceptions[i] = new ExceptionsAttribute[methodFlags[i].length];
for (int j = 0; j < methodFlags[i].length; j++) {
@@ -267,18 +307,16 @@
methodExceptions[i] = new ExceptionsAttribute[methodFlags[i].length];
for (int j = 0; j < methodFlags[i].length; j++) {
long flag = methodFlags[i][j];
- int n = numExceptions[i][j];
- if (n > 0) {
- CPClass[] exceptions = new CPClass[n];
- if (layout.matches(flag)) {
- for (int k = 0; k < n; k++) {
- long result = codec.decode(in);
- exceptions[k] = new CPClass(
- cpBands.getCpClass()[(int) result]);
- }
+ if(layout.matches(flag)) {
+ int n = numExceptions[index];
+ String[] exceptions = methodExceptionsRS[index];
+ CPClass[] exceptionClasses = new CPClass[n];
+ for (int k = 0; k < n; k++) {
+ exceptionClasses[k] = new CPClass(exceptions[k]);
}
- methodExceptions[i][j] = new ExceptionsAttribute(exceptions);
+ methodExceptions[i][j] = new ExceptionsAttribute(exceptionClasses);
methodAttributes[i][j].add(methodExceptions[i][j]);
+ index ++;
}
}
}
@@ -284,38 +322,12 @@
}
}
- /**
- * @param name
- * @param flags
- * @throws Pack200Exception
- */
- private void parseAttributeUnknown(String name, int context, long[][] flags)
- throws Pack200Exception {
- debug("Parsing unknown attributes for " + name);
- AttributeLayout layout = attrMap.getAttributeLayout(name, context);
- int count = SegmentUtils.countMatches(flags, layout);
- if (count > 0)
- throw new Error("We've got data for " + name
- + " and we don't know what to do with it (yet)");
- }
-
- /**
- * @param in
- *
- */
- private void parseAttributeMethodSignature(InputStream in)
- throws Pack200Exception, IOException {
- parseAttributeUnknown(AttributeLayout.ATTRIBUTE_SIGNATURE,
- AttributeLayout.CONTEXT_METHOD, methodFlags);
- }
-
private void parseClassAttrBands(InputStream in) throws IOException,
Pack200Exception {
- int classCount = header.getClassCount();
- SegmentOptions options = header.getOptions();
classFlags = parseFlags("class_flags", in, classCount, Codec.UNSIGNED5,
options.hasClassFlagsHi());
- for (int i = 0; i < classCount; i++) {
+ int classAttrCount = 0;
+ for (int i = 0; i < classFlags.length; i++) {
long flag = classFlags[i];
if ((flag & (1 << 16)) != 0)
classAttrCount++;
@@ -320,40 +332,113 @@
if ((flag & (1 << 16)) != 0)
classAttrCount++;
}
- if (classAttrCount > 0)
- throw new Error(
- "There are attribute flags, and I don't know what to do with them");
- debug("unimplemented class_attr_count");
- debug("unimplemented class_attr_indexes");
- debug("unimplemented class_attr_calls");
- AttributeLayout layout = attrMap.getAttributeLayout(
+ int[] classAttrCounts = decodeBandInt("class_attr_count", in, Codec.UNSIGNED5, classAttrCount);
+ int[][] classAttrIndexes = decodeBandInt("class_attr_indexes", in, Codec.UNSIGNED5, classAttrCounts);
+ int callCount = 0;
+ for (int i = 0; i < classAttrIndexes.length; i++) {
+ for (int j = 0; j < classAttrIndexes[i].length; j++) {
+ int index = classAttrIndexes[i][j];
+ AttributeLayout layout = attrMap.getAttributeLayout(index, AttributeLayout.CONTEXT_CLASS);
+ callCount += layout.numBackwardsCallables();
+ }
+ }
+ int[] classAttrCalls = decodeBandInt("class_attr_calls", in, Codec.UNSIGNED5, callCount);
+
+ AttributeLayout sourceFileLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_SOURCE_FILE,
AttributeLayout.CONTEXT_CLASS);
+ int sourceFileCount = SegmentUtils.countMatches(classFlags,
+ sourceFileLayout);
+ int[] classSourceFile = decodeBandInt("class_SourceFile_RUN", in,
+ Codec.UNSIGNED5, sourceFileCount);
+
+ AttributeLayout enclosingMethodLayout = attrMap.getAttributeLayout(
+ AttributeLayout.ATTRIBUTE_ENCLOSING_METHOD,
+ AttributeLayout.CONTEXT_CLASS);
+ int enclosingMethodCount = SegmentUtils.countMatches(classFlags,
+ enclosingMethodLayout);
+ int[] enclosingMethodRC = decodeBandInt("class_EnclosingMethod_RC", in,
+ Codec.UNSIGNED5, enclosingMethodCount);
+ int[] enclosingMethodRDN = decodeBandInt("class_EnclosingMethod_RDN", in,
+ Codec.UNSIGNED5, enclosingMethodCount);
+
+ AttributeLayout signatureLayout = attrMap.getAttributeLayout(
+ AttributeLayout.ATTRIBUTE_SIGNATURE,
+ AttributeLayout.CONTEXT_CLASS);
+ int signatureCount = SegmentUtils.countMatches(classFlags,
+ signatureLayout);
+ int[] classSignature = decodeBandInt("class_Signature_RS", in,
+ Codec.UNSIGNED5, signatureCount);
+
+ parseClassMetadataBands();
+
+ AttributeLayout innerClassLayout = attrMap.getAttributeLayout(
+ AttributeLayout.ATTRIBUTE_INNER_CLASSES,
+ AttributeLayout.CONTEXT_CLASS);
+ int innerClassCount = SegmentUtils.countMatches(classFlags,
+ innerClassLayout);
+ int[] classInnerClassesN = decodeBandInt("class_InnerClasses_N", in,
+ Codec.UNSIGNED5, innerClassCount);
+ int[][] classInnerClassesRC = decodeBandInt("class_InnerClasses_RC", in, Codec.UNSIGNED5, classInnerClassesN);
+ int[][] classInnerClassesF = decodeBandInt("class_InnerClasses_F", in, Codec.UNSIGNED5, classInnerClassesN);
+ int flagsCount = 0;
+ for (int i = 0; i < classInnerClassesF.length; i++) {
+ for (int j = 0; j < classInnerClassesF[i].length; j++) {
+ if(classInnerClassesF[i][j] != 0) {
+ flagsCount++;
+ }
+ }
+ }
+ int[] classInnerClassesOuterRCN = decodeBandInt("class_InnerClasses_outer_RCN", in, Codec.UNSIGNED5, flagsCount);
+ int[] classInnerClassesNameRUN = decodeBandInt("class_InnerClasses_name_RUN", in, Codec.UNSIGNED5, flagsCount);
+
+
+ AttributeLayout versionLayout = attrMap.getAttributeLayout(
+ AttributeLayout.ATTRIBUTE_CLASS_FILE_VERSION,
+ AttributeLayout.CONTEXT_CLASS);
+ int versionCount = SegmentUtils.countMatches(classFlags, versionLayout);
+ int[] classFileVersionMinorH = decodeBandInt(
+ "class_file_version_minor_H", in, Codec.UNSIGNED5, versionCount);
+ int[] classFileVersionMajorH = decodeBandInt(
+ "class_file_version_major_H", in, Codec.UNSIGNED5, versionCount);
+
+
+ // Now process the attribute bands we have parsed
+ int sourceFileIndex = 0;
+ int enclosingMethodIndex = 0;
+ int signatureIndex = 0;
+ int innerClassIndex = 0;
+ int versionIndex = 0;
+ classAttributes = new ArrayList[classCount];
for (int i = 0; i < classCount; i++) {
+ classAttributes[i] = new ArrayList();
long flag = classFlags[i];
- if (layout.matches(flag)) {
+ if (sourceFileLayout.matches(flag)) {
+ long result = classSourceFile[sourceFileIndex];
// we've got a value to read
// TODO File this as a sourcefile attribute and don't generate
// everything below
- long result = layout.getCodec().decode(in);
- Object value = layout.getValue(result, cpBands
+ Object value = sourceFileLayout.getValue(result, cpBands
.getConstantPool());
debug("Processed value " + value + " for SourceFile");
+ sourceFileIndex++;
+ }
+ if(enclosingMethodLayout.matches(flag)) {
+ // TODO
+ }
+ if(signatureLayout.matches(flag)) {
+// TODO
+ }
+ if(innerClassLayout.matches(flag)) {
+ // TODO
+ }
+ if(versionLayout.matches(flag)) {
+ // TODO
}
}
- debug("unimplemented class_EnclosingMethod_RC");
- debug("unimplemented class_EnclosingMethod_RDN");
- debug("unimplemented class_Signature_RS");
- parseClassMetadataBands();
- debug("unimplemented class_InnerClasses_N");
- debug("unimplemented class_InnerClasses_RC");
- debug("unimplemented class_InnerClasses_F");
- debug("unimplemented class_InnerClasses_outer_RCN");
- debug("unimplemented class_InnerClasses_inner_RCN");
- debug("unimplemented class_file_version_minor_H");
- debug("unimplemented class_file_version_major_H");
}
+
private void parseCodeBands(InputStream in) throws Pack200Exception,
IOException {
AttributeLayout layout = attrMap.getAttributeLayout(
@@ -359,11 +444,11 @@
AttributeLayout layout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_CODE, AttributeLayout.CONTEXT_METHOD);
- int codeBands = SegmentUtils.countMatches(methodFlags, layout);
+ int codeCount = SegmentUtils.countMatches(methodFlags, layout);
int[] codeHeaders = decodeBandInt("code_headers", in, Codec.BYTE1,
- codeBands);
+ codeCount);
int codeSpecialHeader = 0;
- for (int i = 0; i < codeBands; i++) {
+ for (int i = 0; i < codeCount; i++) {
if (codeHeaders[i] == 0)
codeSpecialHeader++;
}
@@ -374,11 +459,11 @@
int[] codeHandlerCountSpecials = decodeBandInt("code_handler_count",
in, Codec.UNSIGNED5, codeSpecialHeader);
- codeMaxStack = new int[codeBands];
- codeMaxNALocals = new int[codeBands];
- codeHandlerCount = new int[codeBands];
+ codeMaxStack = new int[codeCount];
+ codeMaxNALocals = new int[codeCount];
+ codeHandlerCount = new int[codeCount];
int special = 0;
- for (int i = 0; i < codeBands; i++) {
+ for (int i = 0; i < codeCount; i++) {
int header = 0xff & codeHeaders[i];
if (header < 0) {
throw new IllegalStateException("Shouldn't get here");
@@ -403,8 +488,17 @@
throw new IllegalStateException("Shouldn't get here either");
}
}
+ int sumCodeHandlerCount = 0;
+ for (int i = 0; i < codeHandlerCount.length; 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() ?
- codeBands : codeSpecialHeader;
+ codeCount : codeSpecialHeader;
parseCodeAttrBands(in, codeFlagsCount);
}
@@ -410,6 +504,7 @@
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 = 0;
for (int i = 0; i < codeFlagsCount; i++) {
long flag = codeFlags[i];
if ((flag & (1 << 16)) != 0)
@@ -415,14 +510,22 @@
if ((flag & (1 << 16)) != 0)
codeAttrCount++;
}
- if (codeAttrCount > 0)
- throw new Error(
- "There are attribute flags, and I don't know what to do with them");
- debug("unimplemented code_attr_count");
- debug("unimplemented code_attr_indexes");
- debug("unimplemented code_attr_calls");
-
+ System.out.println("codeAttrCount = " + codeAttrCount);
+ 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++) {
+ int index = codeAttrIndexes[i][j];
+ AttributeLayout layout = attrMap.getAttributeLayout(index, AttributeLayout.CONTEXT_CODE);
+ callCount += layout.numBackwardsCallables();
+ }
+ }
+ System.out.println("callCount = " + callCount);
+ 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));
+ System.out.println("lineNumberTables = " + lineNumberTableCount);
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);
@@ -430,6 +533,8 @@
for (int i = 0; i < types.length; i++) {
String type = types[i];
int lengthNBand = SegmentUtils.countMatches(codeFlags, attrMap.getAttributeLayout(type, AttributeLayout.CONTEXT_CODE));
+ System.out.println(type + " count = " + lengthNBand);
+
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);
@@ -597,10 +702,6 @@
}
}
- public int getClassAttrCount() {
- return classAttrCount;
- }
-
public int[] getClassFieldCount() {
return classFieldCount;
}
@@ -649,10 +750,6 @@
return fieldFlags;
}
- public int getMethodAttrCount() {
- return methodAttrCount;
- }
-
public ArrayList[][] getMethodAttributes() {
return methodAttributes;
}
Index: src/main/java/org/apache/harmony/pack200/Codec.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/Codec.java (revision 576831)
+++ src/main/java/org/apache/harmony/pack200/Codec.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.IOException;
import java.io.InputStream;
@@ -95,9 +93,6 @@
* by the Pack200 specification, which allow a codec to be referred to by
* canonical number. TODO Add links to canonical numbers when this has been
* done.
- *
- * @author Alex Blewitt
- * @version $Revision: $
*/
public abstract class Codec {
/**
@@ -129,7 +124,7 @@
public static final BHSDCodec DELTA5 = new BHSDCodec(5, 64, 1, 1);
/**
- * DELTA5 = (5,64,2,1): Used for the majority of numerical codings where
+ * MDELTA5 = (5,64,2,1): Used for the majority of numerical codings where
* there is a correlated sequence of signed values, but where most of them
* are expected to be non-negative.
*/
@@ -147,7 +142,7 @@
public static final BHSDCodec UDELTA5 = new BHSDCodec(5, 64, 0, 1);
/**
- * USIGNED5 = (5,64): Used for small unsigned values.
+ * UNSIGNED5 = (5,64): Used for small unsigned values.
*/
public static final BHSDCodec UNSIGNED5 = new BHSDCodec(5, 64);
Index: src/main/java/org/apache/harmony/pack200/CodecEncoding.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/CodecEncoding.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/CodecEncoding.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
@@ -23,6 +21,7 @@
import java.io.InputStream;
public class CodecEncoding {
+
/**
* The canonical encodings are defined to allow a single byte to represent
* one of the standard encodings. The following values are defined in the
@@ -28,7 +27,7 @@
* one of the standard encodings. The following values are defined in the
* Pack200 specification, and this array cannot be changed.
*/
- private static Codec[] canonicalCodec = { null, new BHSDCodec(1, 256),
+ private static final Codec[] canonicalCodec = { null, new BHSDCodec(1, 256),
new BHSDCodec(1, 256, 1), new BHSDCodec(1, 256, 0, 1),
new BHSDCodec(1, 256, 1, 1), new BHSDCodec(2, 256),
new BHSDCodec(2, 256, 1), new BHSDCodec(2, 256, 0, 1),
@@ -100,7 +99,7 @@
* @throws Pack200Exception
*/
public static Codec getCodec(int value, InputStream in, Codec defaultCodec) throws IOException, Pack200Exception {
- // Sanity check to make sure that no-one's been buggering with
+ // Sanity check to make sure that no-one has changed
// the canonical codecs, which would really cause havoc
if (canonicalCodec.length != 116)
throw new Error("Canonical encodings have been incorrectly modified");
Index: src/main/java/org/apache/harmony/pack200/CpBands.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/CpBands.java (revision 576831)
+++ src/main/java/org/apache/harmony/pack200/CpBands.java (working copy)
@@ -209,8 +209,8 @@
private void parseCpLong(InputStream in) throws IOException,
Pack200Exception {
int cpLongCount = header.getCpLongCount();
- cpLong = parseFlags("cp_Long", in, cpLongCount, new int[] { 1 },
- Codec.UDELTA5, Codec.DELTA5)[0];
+ cpLong = parseFlags("cp_Long", in, cpLongCount,
+ Codec.UDELTA5, Codec.DELTA5);
}
/**
@@ -262,7 +262,18 @@
String[] cpSignatureForm = parseReferences("cp_Signature_form", in,
Codec.DELTA5, cpSignatureCount, cpUTF8);
cpSignature = new String[cpSignatureCount];
- long last = 0;
+ int lCount = 0;
+ for (int i = 0; i < cpSignatureCount; i++) {
+ String form = cpSignatureForm[i];
+ char[] chars = form.toCharArray();
+ for (int j = 0; j < chars.length; j++) {
+ if(chars[j] == 'L') {
+ lCount++;
+ }
+ }
+ }
+ String[] cpSignatureClasses = parseReferences("cp_Signature_classes", in, Codec.UDELTA5, lCount, cpClass);
+ int index = 0;
for (int i = 0; i < cpSignatureCount; i++) {
String form = cpSignatureForm[i];
int len = form.length();
@@ -272,10 +283,10 @@
char c = form.charAt(j);
signature.append(c);
if (c == 'L') {
- int index = (int) (last = Codec.UDELTA5.decode(in, last));
- String className = cpClass[index];
+ String className = cpSignatureClasses[index];
list.add(className);
signature.append(className);
+ index++;
}
}
cpSignature[i] = signature.toString();
Index: src/main/java/org/apache/harmony/pack200/FileBands.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/FileBands.java (revision 572724)
+++ src/main/java/org/apache/harmony/pack200/FileBands.java (working copy)
@@ -67,42 +67,22 @@
Pack200Exception {
int numberOfFiles = header.getNumberOfFiles();
SegmentOptions options = header.getOptions();
- if (false && System.getProperty("debug.pack200") != null) {
- // TODO HACK
- fileSize = new long[numberOfFiles];
- fileModtime = new long[numberOfFiles];
- fileOptions = new long[numberOfFiles];
- fileName = new String[numberOfFiles];
- Arrays.fill(fileName, "");
- return;
- }
- long last;
+
fileName = parseReferences("file_name", in, Codec.UNSIGNED5,
numberOfFiles, cpUTF8);
- fileSize = new long[numberOfFiles];
- if (options.hasFileSizeHi()) {
- last = 0;
- for (int i = 0; i < numberOfFiles; i++) {
- fileSize[i] = (last = Codec.UNSIGNED5.decode(in, last)) << 32;
- }
- }
- last = 0;
- for (int i = 0; i < numberOfFiles; i++) {
- fileSize[i] |= (last = Codec.UNSIGNED5.decode(in, last));
- }
- fileModtime = new long[numberOfFiles];
+ fileSize = parseFlags("file_size", in, numberOfFiles, Codec.UNSIGNED5,
+ options.hasFileSizeHi());
if (options.hasFileModtime()) {
- last = 0;
- for (int i = 0; i < numberOfFiles; i++) {
- fileModtime[i] |= (last = Codec.DELTA5.decode(in, last));
- }
+ fileModtime = decodeBandLong("file_modtime", in, Codec.DELTA5,
+ numberOfFiles);
+ } else {
+ fileModtime = new long[numberOfFiles];
}
- fileOptions = new long[numberOfFiles];
if (options.hasFileOptions()) {
- last = 0;
- for (int i = 0; i < numberOfFiles; i++) {
- fileOptions[i] |= (last = Codec.UNSIGNED5.decode(in, last));
- }
+ fileOptions = decodeBandLong("file_options", in, Codec.UNSIGNED5,
+ numberOfFiles);
+ } else {
+ fileOptions = new long[numberOfFiles];
}
}
Index: src/main/java/org/apache/harmony/pack200/IcBands.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/IcBands.java (revision 572724)
+++ src/main/java/org/apache/harmony/pack200/IcBands.java (working copy)
@@ -62,12 +62,9 @@
int innerClassCount = header.getInnerClassCount();
icThisClass = parseReferences("ic_this_class", in, Codec.UDELTA5,
innerClassCount, cpClass);
- icFlags = new int[innerClassCount];
- long last = 0;
+ icFlags = decodeBandInt("ic_flags", in, Codec.UNSIGNED5, innerClassCount);
int outerClasses = 0;
- // ic_flags
for (int i = 0; i < innerClassCount; i++) {
- icFlags[i] = (int) (last = Codec.UNSIGNED5.decode(in, last));
if ((icFlags[i] & 1 << 16) != 0)
outerClasses++;
}
Index: src/main/java/org/apache/harmony/pack200/Pack200Exception.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/Pack200Exception.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/Pack200Exception.java (working copy)
@@ -15,14 +15,9 @@
* limitations under the License.
*/
package org.apache.harmony.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
/**
* Represents a problem with a Pack200 coding/decoding issue.
- *
- * @author Alex Blewitt
- * @version $Revision: $
*/
public class Pack200Exception extends Exception {
Index: src/main/java/org/apache/harmony/pack200/PopulationCodec.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/PopulationCodec.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/PopulationCodec.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.IOException;
import java.io.InputStream;
Index: src/main/java/org/apache/harmony/pack200/RunCodec.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/RunCodec.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/RunCodec.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.IOException;
import java.io.InputStream;
@@ -26,9 +24,6 @@
* the first codec, and the remaining codes are decoded from the remaining
* codec. Note that since this codec maintains state, the instances are
* not reusable.
- *
- * @author Alex Blewitt
- * @version $Revision: $
*/
public class RunCodec extends Codec {
private int k;
Index: src/main/java/org/apache/harmony/pack200/Segment.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/Segment.java (revision 583385)
+++ src/main/java/org/apache/harmony/pack200/Segment.java (working copy)
@@ -16,10 +16,6 @@
*/
package org.apache.harmony.pack200;
-// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-// NOTE: Do not extract strings as messages; this code is still a
-// work-in-progress
-// NOTE: Also, don't get rid of 'else' statements for the hell of it ...
import java.io.BufferedInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@@ -64,9 +60,6 @@
* In any case, if GZip decompression is being performed the input stream will
* be buffered at a higher level, and thus this can read on a byte-oriented
* basis.
- *
- * @author Alex Blewitt
- * @version $Revision: $
*/
public class Segment {
Index: src/main/java/org/apache/harmony/pack200/SegmentOptions.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/SegmentOptions.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/SegmentOptions.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
/**
* Stores the combinations of bit flags that can be used in the segment header
* options. Whilst this could be defined in {@link Segment}, it's cleaner to
@@ -25,9 +23,6 @@
* to determine the semantic meaning of the flags. In languages with a
* pre-processor, these may be defined by macros that do bitflag manipulation
* instead.
- *
- * @author Alex Blewitt
- * @version $Revision: $
*/
public class SegmentOptions {
private static final int DEFLATE_HINT = 1 << 5;
Index: src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/bytecode/ClassConstantPool.java (working copy)
@@ -16,10 +16,6 @@
*/
package org.apache.harmony.pack200.bytecode;
-// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-// NOTE: Do not extract strings as messages; this code is still a
-// work-in-progress
-// NOTE: Also, don't get rid of 'else' statements for the hell of it ...
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Index: src/main/java/org/apache/harmony/pack200/bytecode/ClassFile.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/bytecode/ClassFile.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/bytecode/ClassFile.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200.bytecode;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.DataOutputStream;
import java.io.IOException;
Index: src/main/java/org/apache/harmony/pack200/bytecode/ClassFileEntry.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/bytecode/ClassFileEntry.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/bytecode/ClassFileEntry.java (working copy)
@@ -16,10 +16,6 @@
*/
package org.apache.harmony.pack200.bytecode;
-// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-// NOTE: Do not extract strings as messages; this code is still a
-// work-in-progress
-// NOTE: Also, don't get rid of 'else' statements for the hell of it ...
import java.io.DataOutputStream;
import java.io.IOException;
Index: src/main/java/org/apache/harmony/pack200/bytecode/ConstantPoolEntry.java
===================================================================
--- src/main/java/org/apache/harmony/pack200/bytecode/ConstantPoolEntry.java (revision 565676)
+++ src/main/java/org/apache/harmony/pack200/bytecode/ConstantPoolEntry.java (working copy)
@@ -16,16 +16,10 @@
*/
package org.apache.harmony.pack200.bytecode;
-// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-// NOTE: Do not extract strings as messages; this code is still a
-// work-in-progress
-// NOTE: Also, don't get rid of 'else' statements for the hell of it ...
import java.io.DataOutputStream;
import java.io.IOException;
-
/**
- * @author alex
*
*/
public abstract class ConstantPoolEntry extends ClassFileEntry {
Index: src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutMapTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutMapTest.java (revision 565676)
+++ src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutMapTest.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200.tests;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import junit.framework.TestCase;
import org.apache.harmony.pack200.AttributeLayout;
Index: src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutTest.java (revision 572724)
+++ src/test/java/org/apache/harmony/pack200/tests/AttributeLayoutTest.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200.tests;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import junit.framework.TestCase;
import org.apache.harmony.pack200.AttributeLayout;
Index: src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java (revision 583385)
+++ src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java (working copy)
@@ -26,12 +26,20 @@
import org.apache.harmony.pack200.BHSDCodec;
import org.apache.harmony.pack200.BandSet;
import org.apache.harmony.pack200.Codec;
+import org.apache.harmony.pack200.CodecEncoding;
import org.apache.harmony.pack200.Pack200Exception;
import org.apache.harmony.pack200.Segment;
+import org.apache.harmony.pack200.SegmentHeader;
public class BandSetTest extends TestCase {
- private BandSet bandSet = new BandSet(new Segment()) {
+ public class MockSegment extends Segment {
+ public SegmentHeader getSegmentHeader() {
+ return new SegmentHeader();
+ }
+ }
+
+ private BandSet bandSet = new BandSet(new MockSegment()) {
public void pack(OutputStream outputStream) {
}
@@ -38,6 +46,7 @@
public void unpack(InputStream inputStream) throws IOException, Pack200Exception {
}
+
};
public void testDecodeBandInt() throws IOException, Pack200Exception {
@@ -52,11 +61,11 @@
public void testDecodeBandLong() throws IOException, Pack200Exception {
BHSDCodec codec = Codec.BYTE1;
- byte[] bytes = new byte[]{(byte)3,(byte)56,(byte)122,(byte)78, Byte.MAX_VALUE, Byte.MIN_VALUE};
+ byte[] bytes = new byte[]{(byte)3,(byte)56,(byte)122,(byte)78, (byte)0, (byte)255};
InputStream in = new ByteArrayInputStream(bytes);
- long[] longs = bandSet.decodeBandLong("Test Band", in, codec, 4);
+ long[] longs = bandSet.decodeBandLong("Test Band", in, codec, 6);
for (int i = 0; i < longs.length; i++) {
- assertEquals("Wrong value in position " + i, longs[i], bytes[i]);
+ assertEquals("Wrong value in position " + i, (byte)longs[i], bytes[i]);
}
//TODO: Should test this with other Codecs.
}
@@ -61,6 +70,17 @@
//TODO: Should test this with other Codecs.
}
+ public void testDecodeBandLong2() throws IOException, Pack200Exception {
+
+ BHSDCodec codec = Codec.DELTA5;
+ byte[] bytes = new byte[]{3, 1, 2, 3, 4, 5}; // 3 is decoded to -2 by DELTA5, which signifies a switch to BYTE1
+ InputStream in = new ByteArrayInputStream(bytes);
+ long[] longs = bandSet.decodeBandLong("Test Band", in, codec, 5);
+ for (int i = 0; i < longs.length; i++) {
+ assertEquals("Wrong value in position " + i, longs[i], bytes[i + 1]);
+ }
+ }
+
public void testParseFlags1() {
}
Index: src/test/java/org/apache/harmony/pack200/tests/BcBandsTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/BcBandsTest.java (revision 583385)
+++ src/test/java/org/apache/harmony/pack200/tests/BcBandsTest.java (working copy)
@@ -43,17 +43,7 @@
* should be replaced with properly encoded byte arrays when encoding is
* implemented.
*/
-public class BcBandsTest extends TestCase {
-
-
- private int numClasses = 1;
- private int[] numMethods = {1};
-
- public class MockSegmentHeader extends SegmentHeader {
- public int getClassCount() {
- return numClasses;
- }
- }
+public class BcBandsTest extends AbstractBandsTestCase {
public class MockClassBands extends ClassBands {
public MockClassBands(Segment segment) {
@@ -107,26 +97,7 @@
}
}
- public class MockAttributeDefinitionBands extends AttrDefinitionBands {
-
- public MockAttributeDefinitionBands(Segment segment) {
- super(segment);
- }
-
- public AttributeLayoutMap getAttributeDefinitionMap() {
- try {
- return new AttributeLayoutMap();
- } catch (Pack200Exception e) {
- fail(e.getLocalizedMessage());
- }
- return null;
- }
-
-
-
- }
-
- public class MockSegment extends Segment {
+ public class MockSegment extends AbstractBandsTestCase.MockSegment {
protected AttrDefinitionBands getAttrDefinitionBands() {
return new MockAttributeDefinitionBands(this);
}
@@ -138,10 +109,6 @@
protected ClassBands getClassBands() {
return new MockClassBands(this);
}
-
- public SegmentHeader getSegmentHeader() {
- return new MockSegmentHeader();
- }
}
BcBands bcBands = new BcBands(new MockSegment());
Index: src/test/java/org/apache/harmony/pack200/tests/CodecEncodingTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/CodecEncodingTest.java (revision 565676)
+++ src/test/java/org/apache/harmony/pack200/tests/CodecEncodingTest.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200.tests;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.HashMap;
@@ -31,11 +29,11 @@
import org.apache.harmony.pack200.Pack200Exception;
/**
- * @author Alex Blewitt
- * @version $Revision: $
+ *
*/
public class CodecEncodingTest extends TestCase {
- public void testCanonicalEncodings() throws IOException, Pack200Exception {
+
+ public void testCanonicalEncodings() throws IOException, Pack200Exception {
Codec defaultCodec = new BHSDCodec(2,16,0,0);
assertEquals(defaultCodec,CodecEncoding.getCodec(0,null, defaultCodec));
Map map = new HashMap();
@@ -164,4 +162,5 @@
assertEquals("(5,128,2,1)",CodecEncoding.getCodec(116,new ByteArrayInputStream(new byte[] { 0x25, (byte)0x7F}), null).toString());
assertEquals("(2,128,1,1)",CodecEncoding.getCodec(116,new ByteArrayInputStream(new byte[] { 0x0B, (byte)0x7F}), null).toString());
}
+
}
Index: src/test/java/org/apache/harmony/pack200/tests/CodecTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/CodecTest.java (revision 565676)
+++ src/test/java/org/apache/harmony/pack200/tests/CodecTest.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200.tests;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.ByteArrayInputStream;
import java.io.EOFException;
import java.io.IOException;
@@ -31,8 +29,7 @@
/**
- * @author Alex Blewitt
- * @version $Revision: $
+ *
*/
public class CodecTest extends TestCase {
Index: src/test/java/org/apache/harmony/pack200/tests/HelloWorld.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/HelloWorld.java (revision 587092)
+++ src/test/java/org/apache/harmony/pack200/tests/HelloWorld.java (working copy)
@@ -15,13 +15,9 @@
* limitations under the License.
*/
package org.apache.harmony.pack200.tests;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
/**
* This is intended to be used as a test class for unpacking a packed Jar file.
- * @author Alex Blewitt
- * @version $Revision: $
*/
public class HelloWorld {
int i=97,j=42,k=12345;
Index: src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java (revision 565676)
+++ src/test/java/org/apache/harmony/pack200/tests/PopulationCodecTest.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200.tests;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
Index: src/test/java/org/apache/harmony/pack200/tests/SegmentOptionsTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/SegmentOptionsTest.java (revision 565676)
+++ src/test/java/org/apache/harmony/pack200/tests/SegmentOptionsTest.java (working copy)
@@ -15,9 +15,7 @@
* limitations under the License.
*/
package org.apache.harmony.pack200.tests;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
import junit.framework.TestCase;
import org.apache.harmony.pack200.Pack200Exception;
@@ -24,11 +22,11 @@
import org.apache.harmony.pack200.SegmentOptions;
/**
- * @author Alex Blewitt
- * @version $Revision: $
+ *
*/
public class SegmentOptionsTest extends TestCase {
- public void testUnused() {
+
+ public void testUnused() {
int[] unused = new int[] { 3, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31 };
for (int i = 0; i < unused.length; i++) {
Index: src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java (revision 583385)
+++ src/test/java/org/apache/harmony/pack200/tests/SegmentTest.java (working copy)
@@ -16,10 +16,15 @@
*/
package org.apache.harmony.pack200.tests;
-import org.apache.harmony.pack200.Segment;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.util.jar.JarOutputStream;
import junit.framework.TestCase;
+import org.apache.harmony.pack200.Segment;
+
/**
* Tests for org.apache.harmony.pack200.Segment, which is the main class for pack200.
*/
@@ -31,9 +36,11 @@
}
public void testJustResources() throws Exception {
- assertNotNull(Segment
- .parse(Segment.class
- .getResourceAsStream("/org/apache/harmony/pack200/tests/JustResources.pack")));
+ InputStream in = Segment.class
+ .getResourceAsStream("/org/apache/harmony/pack200/tests/JustResources.pack");
+ Segment segment = Segment.parse(in);
+ assertNotNull(segment);
+ segment.writeJar(new JarOutputStream(new FileOutputStream(File.createTempFile("just", "Resources.jar"))), in);
}
public void testJustResourcesGZip() throws Exception {
@@ -41,7 +48,23 @@
.parse(Segment.class
.getResourceAsStream("/org/apache/harmony/pack200/tests/JustResources.pack.gz")));
}
-
+
+ // Test with an archive containing Harmony's SQL module, packed with -E1
+ public void testWithSqlE1() throws Exception {
+ assertNotNull(Segment
+ .parse(Segment.class
+ .getResourceAsStream("/org/apache/harmony/pack200/tests/sql-e1.pack.gz")));
+
+ }
+
+ // Test with an archive containing Harmony's Pack200 module, packed with -E1
+ public void testWithPack200E1() throws Exception {
+ assertNotNull(Segment
+ .parse(Segment.class
+ .getResourceAsStream("/org/apache/harmony/pack200/tests/pack200-e1.pack.gz")));
+
+ }
+
public void testInterfaceOnly() throws Exception {
assertNotNull(Segment
.parse(Segment.class
@@ -48,4 +71,5 @@
.getResourceAsStream("/org/apache/harmony/pack200/tests/InterfaceOnly.pack")));
}
+
}
\ No newline at end of file
Index: src/test/java/org/apache/harmony/pack200/tests/AbstractBandsTestCase.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/AbstractBandsTestCase.java
+++ src/test/java/org/apache/harmony/pack200/tests/AbstractBandsTestCase.java
@@ -0,0 +1,81 @@
+/*
+ * 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.tests;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.pack200.AttrDefinitionBands;
+import org.apache.harmony.pack200.AttributeLayoutMap;
+import org.apache.harmony.pack200.Pack200Exception;
+import org.apache.harmony.pack200.Segment;
+import org.apache.harmony.pack200.SegmentHeader;
+import org.apache.harmony.pack200.SegmentOptions;
+
+/**
+ *
+ */
+public abstract class AbstractBandsTestCase extends TestCase {
+
+ protected int numClasses = 1;
+ protected int[] numMethods = {1};
+
+ public class MockSegmentHeader extends SegmentHeader {
+ public int getClassCount() {
+ return numClasses;
+ }
+
+ public SegmentOptions getOptions() {
+ try {
+ return new SegmentOptions(0);
+ } catch (Pack200Exception e) {
+ return null;
+ }
+ }
+ }
+
+ public class MockAttributeDefinitionBands extends AttrDefinitionBands {
+
+ public MockAttributeDefinitionBands(Segment segment) {
+ super(segment);
+ }
+
+ public AttributeLayoutMap getAttributeDefinitionMap() {
+ try {
+ return new AttributeLayoutMap();
+ } catch (Pack200Exception e) {
+ fail(e.getLocalizedMessage());
+ }
+ return null;
+ }
+
+
+
+ }
+
+ public class MockSegment extends Segment {
+
+ protected AttrDefinitionBands getAttrDefinitionBands() {
+ return new MockAttributeDefinitionBands(this);
+ }
+
+ public SegmentHeader getSegmentHeader() {
+ return new MockSegmentHeader();
+ }
+ }
+
+
+}
Index: src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java
===================================================================
--- src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java
+++ src/test/java/org/apache/harmony/pack200/tests/BHSDCodecTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.tests;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.pack200.BHSDCodec;
+import org.apache.harmony.pack200.CodecEncoding;
+import org.apache.harmony.pack200.Pack200Exception;
+
+/**
+ * Tests for BHSDCodec
+ */
+public class BHSDCodecTest extends TestCase {
+
+
+ public void testEncodeDecode() throws IOException, Pack200Exception {
+ for (int i = 1; i < 116; i++) {
+
+ BHSDCodec codec = (BHSDCodec) CodecEncoding.getCodec(i, null, null);
+
+ // Test encode-decode with a selection of numbers within the range of the codec
+ long delta = (codec.largest() - codec.smallest()) / 4;
+ for (long j = codec.smallest(); j <= codec.largest() + 1; j += delta) {
+ byte[] encoded = codec.encode(j, 0);
+ long decoded = codec.decode(new ByteArrayInputStream(encoded),
+ 0);
+ if (j != decoded) {
+ fail("Failed with codec: " + codec + " expected: " + j
+ + ", got: " + decoded);
+ }
+ }
+
+ // Test encode-decode with 0
+ assertEquals(0, codec.decode(new ByteArrayInputStream(codec.encode(
+ 0, 0)), 0));
+ }
+ }
+
+}
\ 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
+++ src/test/java/org/apache/harmony/pack200/tests/ClassBandsTest.java
@@ -0,0 +1,144 @@
+/*
+ * 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.tests;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+import org.apache.harmony.pack200.ClassBands;
+import org.apache.harmony.pack200.Codec;
+import org.apache.harmony.pack200.CpBands;
+import org.apache.harmony.pack200.Pack200Exception;
+import org.apache.harmony.pack200.Segment;
+
+/**
+ *
+ */
+public class ClassBandsTest extends AbstractBandsTestCase {
+
+ private String[] cpClasses;
+ private String[] cpDescriptor;
+
+ public class MockCpBands extends CpBands {
+
+ public MockCpBands(Segment segment) {
+ super(segment);
+ }
+
+ public String[] getCpClass() {
+ return cpClasses;
+ }
+
+ public String[] getCpDescriptor() {
+ return cpDescriptor;
+ }
+
+ }
+
+ public class MockSegment extends AbstractBandsTestCase.MockSegment {
+ protected CpBands getCpBands() {
+ return new MockCpBands(this);
+ }
+
+ }
+
+
+
+ ClassBands classBands = new ClassBands(new MockSegment());
+
+ public void testSimple() throws IOException, Pack200Exception {
+ cpClasses = new String[] { "Class1", "Class2", "Class3", "Interface1", "Interface2" };
+ byte[] classThis = Codec.DELTA5.encode(1, 0);
+ byte[] classSuper = Codec.DELTA5.encode(2, 0);
+ byte[] classInterfaceCount = Codec.DELTA5.encode(2, 0);
+ byte[] classInterfaceRef1 = classBands.encodeBandLong(new long[] {3, 4}, Codec.DELTA5);
+ byte[] classFieldCount = Codec.DELTA5.encode(0, 0);
+ byte[] classMethodCount = Codec.DELTA5.encode(0, 0);
+ byte[] classFlags = Codec.UNSIGNED5.encode(0, 0);
+ byte[][] allArrays = new byte[][] { classThis, classSuper,
+ classInterfaceCount, classInterfaceRef1, classFieldCount,
+ classMethodCount, classFlags };
+ int total = classThis.length + classSuper.length
+ + classInterfaceCount.length + classInterfaceRef1.length
+ + classFieldCount.length + classMethodCount.length
+ + classFlags.length;
+ byte[] bytes = new byte[total];
+ int index = 0;
+ for (int i = 0; i < allArrays.length; i++) {
+ for (int j = 0; j < allArrays[i].length; j++) {
+ bytes[index] = allArrays[i][j];
+ index++;
+ }
+ }
+ ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+ classBands.unpack(in);
+ assertEquals(cpClasses[1], classBands.getClassThis()[0]);
+ assertEquals(cpClasses[2], classBands.getClassSuper()[0]);
+ assertEquals(1, classBands.getClassInterfaces().length);
+ assertEquals(2, classBands.getClassInterfaces()[0].length);
+ assertEquals(cpClasses[3], classBands.getClassInterfaces()[0][0]);
+ assertEquals(cpClasses[4], classBands.getClassInterfaces()[0][1]);
+ cpClasses = null;
+ }
+
+ public void testWithMethods() throws Pack200Exception, IOException {
+ cpClasses = new String[] { "Class1", "Class2", "Class3" };
+ cpDescriptor = new String[] {"method1", "method2", "method3"};
+ byte[] classThis = Codec.DELTA5.encode(1, 0);
+ byte[] classSuper = Codec.DELTA5.encode(2, 0);
+ byte[] classInterfaceCount = Codec.DELTA5.encode(0, 0);
+ byte[] classFieldCount = Codec.DELTA5.encode(0, 0);
+ byte[] classMethodCount = Codec.DELTA5.encode(3, 0);
+ byte[] methodDescr = classBands.encodeBandLong(new long[]{0, 1, 2}, Codec.MDELTA5);
+ byte[] methodFlagsLo = classBands.encodeBandLong(new long[]{0, 0, 0}, Codec.UNSIGNED5);
+ byte[] classFlags = Codec.UNSIGNED5.encode(0, 0);
+ byte[][] allArrays = new byte[][] { classThis, classSuper,
+ classInterfaceCount, classFieldCount, classMethodCount,
+ methodDescr, methodFlagsLo, classFlags, };
+ int total = 0;
+ for (int i = 0; i < allArrays.length; i++) {
+ total += allArrays[i].length;
+ }
+ byte[] bytes = new byte[total];
+ int index = 0;
+ for (int i = 0; i < allArrays.length; i++) {
+ for (int j = 0; j < allArrays[i].length; j++) {
+ bytes[index] = allArrays[i][j];
+ index++;
+ }
+ }
+ ByteArrayInputStream in = new ByteArrayInputStream(bytes);
+ classBands.unpack(in);
+ assertEquals(cpClasses[1], classBands.getClassThis()[0]);
+ assertEquals(cpClasses[2], classBands.getClassSuper()[0]);
+ assertEquals(1, classBands.getMethodDescr().length);
+ assertEquals(3, classBands.getMethodDescr()[0].length);
+ assertEquals(cpDescriptor[0], classBands.getMethodDescr()[0][0]);
+ assertEquals(cpDescriptor[1], classBands.getMethodDescr()[0][1]);
+ assertEquals(cpDescriptor[2], classBands.getMethodDescr()[0][2]);
+
+ cpClasses = null;
+ cpDescriptor = null;
+ }
+
+ public void testWithFields() {
+
+ }
+
+
+
+}