You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2008/01/04 12:14:27 UTC
svn commit: r608801 - in
/harmony/enhanced/classlib/trunk/modules/pack200/src:
main/java/org/apache/harmony/pack200/
main/java/org/apache/harmony/pack200/bytecode/
test/java/org/apache/harmony/pack200/tests/
Author: tellison
Date: Fri Jan 4 03:14:19 2008
New Revision: 608801
URL: http://svn.apache.org/viewvc?rev=608801&view=rev
Log:
Apply patch HARMONY-5370 ([classlib] [pack200] Support for compressor-defined class file attributes)
Added:
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java (with props)
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/NewAttribute.java (with props)
Modified:
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayout.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/EnclosingMethodAttribute.java
harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttrDefinitionBands.java Fri Jan 4 03:14:19 2008
@@ -18,7 +18,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
/**
*
@@ -41,14 +40,6 @@
}
/* (non-Javadoc)
- * @see org.apache.harmony.pack200.BandSet#pack(java.io.OutputStream)
- */
- public void pack(OutputStream outputStream) {
- // TODO Auto-generated method stub
-
- }
-
- /* (non-Javadoc)
* @see org.apache.harmony.pack200.BandSet#unpack(java.io.InputStream)
*/
public void unpack(InputStream in) throws IOException,
@@ -73,9 +64,11 @@
if(index == -1) {
index = overflowIndex++;
}
- attributeDefinitionMap.add(new AttributeLayout(
+ AttributeLayout layout = new AttributeLayout(
attributeDefinitionName[i], context,
- attributeDefinitionLayout[i], index));
+ attributeDefinitionLayout[i], index, false);
+ NewAttributeBands newBands = new NewAttributeBands(segment, layout);
+ attributeDefinitionMap.add(layout, newBands);
}
attributeDefinitionMap.checkMap();
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayout.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayout.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayout.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayout.java Fri Jan 4 03:14:19 2008
@@ -98,28 +98,46 @@
private long mask;
private String name;
+ private boolean isDefault;
+ private int backwardsCallCount;
+
+ /**
+ * Construct a default AttributeLayout
+ * (equivalent to <code>new AttributeLayout(name, context, layout, index, true);</code>)
+ * @param name
+ * @param context
+ * @param layout
+ * @param index
+ * @throws Pack200Exception
+ */
public AttributeLayout(String name, int context, String layout, int index)
throws Pack200Exception {
- super();
+ this(name, context, layout, index, true);
+ }
+
+ public AttributeLayout(String name, int context, String layout, int index,
+ boolean isDefault) throws Pack200Exception {
+ super();
this.index = index;
this.context = context;
- if (index >= 0) {
- this.mask = 1L << index;
- } else {
- this.mask = 0;
- }
+ if (index >= 0) {
+ this.mask = 1L << index;
+ } else {
+ this.mask = 0;
+ }
if (context != CONTEXT_CLASS && context != CONTEXT_CODE
&& context != CONTEXT_FIELD && context != CONTEXT_METHOD)
throw new Pack200Exception("Attribute context out of range: "
+ context);
- if (layout == null) // || layout.length() == 0)
- throw new Pack200Exception("Cannot have a null layout");
+ if (layout == null) // || layout.length() == 0)
+ throw new Pack200Exception("Cannot have a null layout");
if (name == null || name.length() == 0)
- throw new Pack200Exception("Cannot have an unnamed layout");
+ throw new Pack200Exception("Cannot have an unnamed layout");
this.name = name;
- this.layout = layout;
- }
+ this.layout = layout;
+ this.isDefault = isDefault;
+ }
public boolean equals(Object obj) {
@@ -243,18 +261,19 @@
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) {
- for (int i = 1; i < split.length; i++) {
- if(split[i].startsWith("-") || split[i].startsWith("0")) {
- num++;
- }
- }
+ return 1;
+ } else {
+ return backwardsCallCount;
}
- return num;
+ }
+
+
+ public boolean isDefaultLayout() {
+ return isDefault;
+ }
+
+ public void setBackwardsCallCount(int backwardsCallCount) {
+ this.backwardsCallCount = backwardsCallCount;
}
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeLayoutMap.java Fri Jan 4 03:14:19 2008
@@ -198,6 +198,8 @@
// the value of their context constants (AttributeLayout.CONTEXT_CLASS etc.)
private final Map[] layouts = new Map[] {classLayouts, fieldLayouts, methodLayouts, codeLayouts};
+ private final Map layoutsToBands = new HashMap();
+
public AttributeLayoutMap() throws Pack200Exception {
AttributeLayout[] defaultAttributeLayouts = getDefaultAttributeLayouts();
for (int i = 0; i < defaultAttributeLayouts.length; i++) {
@@ -208,6 +210,13 @@
public void add(AttributeLayout layout) {
layouts[layout.getContext()].put(new Integer(layout.getIndex()), layout);
}
+
+
+
+ public void add(AttributeLayout layout, NewAttributeBands newBands) {
+ add(layout);
+ layoutsToBands.put(layout, newBands);
+ }
public AttributeLayout getAttributeLayout(String name, int context)
throws Pack200Exception {
@@ -257,6 +266,10 @@
}
}
}
+ }
+
+ public NewAttributeBands getAttributeBands(AttributeLayout layout) {
+ return (NewAttributeBands) layoutsToBands.get(layout);
}
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BandSet.java Fri Jan 4 03:14:19 2008
@@ -19,12 +19,17 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
+import org.apache.harmony.pack200.bytecode.CPClass;
import org.apache.harmony.pack200.bytecode.CPDouble;
+import org.apache.harmony.pack200.bytecode.CPFieldRef;
import org.apache.harmony.pack200.bytecode.CPFloat;
import org.apache.harmony.pack200.bytecode.CPInteger;
+import org.apache.harmony.pack200.bytecode.CPInterfaceMethodRef;
import org.apache.harmony.pack200.bytecode.CPLong;
+import org.apache.harmony.pack200.bytecode.CPMethodRef;
+import org.apache.harmony.pack200.bytecode.CPNameAndType;
+import org.apache.harmony.pack200.bytecode.CPString;
import org.apache.harmony.pack200.bytecode.CPUTF8;
import org.apache.harmony.pack200.bytecode.ClassConstantPool;
@@ -32,8 +37,6 @@
public abstract void unpack(InputStream inputStream) throws IOException, Pack200Exception;
- public abstract void pack(OutputStream outputStream);
-
protected Segment segment;
protected SegmentHeader header;
@@ -482,6 +485,107 @@
result[i] = new CPUTF8[num];
System.arraycopy(refs, pos, result[i], 0, num);
pos += num;
+ }
+ return result;
+ }
+
+ public CPString[] parseCPStringReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception {
+ String[] reference = segment.getCpBands().getCpString();
+ int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1);
+ CPString[] result = new CPString[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 CPString(reference[index]);
+ }
+ return result;
+ }
+
+ public CPInterfaceMethodRef[] parseCPInterfaceMethodRefReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception {
+ String[] reference = segment.getCpBands().getCpIMethodClass();
+ String[] descriptors = segment.getCpBands().getCpIMethodDescriptor();
+ int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1);
+ CPInterfaceMethodRef[] result = new CPInterfaceMethodRef[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 CPInterfaceMethodRef(reference[index], descriptors[index]);
+ }
+ return result;
+ }
+
+ public CPMethodRef[] parseCPMethodRefReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception {
+ String[] reference = segment.getCpBands().getCpMethodClass();
+ String[] descriptors = segment.getCpBands().getCpMethodDescriptor();
+ int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1);
+ CPMethodRef[] result = new CPMethodRef[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 CPMethodRef(reference[index], descriptors[index]);
+ }
+ return result;
+ }
+
+ public CPFieldRef[] parseCPFieldRefReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception {
+ String[] reference = segment.getCpBands().getCpFieldClass();
+ String[] descriptors = segment.getCpBands().getCpFieldDescriptor();
+ int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1);
+ CPFieldRef[] result = new CPFieldRef[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 CPFieldRef(reference[index], descriptors[index]);
+ }
+ return result;
+ }
+
+ public CPNameAndType[] parseCPDescriptorReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception {
+ String[] reference = segment.getCpBands().getCpDescriptor();
+ int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1);
+ CPNameAndType[] result = new CPNameAndType[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 CPNameAndType(reference[index]);
+ }
+ return result;
+ }
+
+ public CPUTF8[] parseCPSignatureReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception {
+ String[] reference = segment.getCpBands().getCpSignature();
+ 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], ClassConstantPool.DOMAIN_UNDEFINED);
+ }
+ return result;
+ }
+
+ public CPClass[] parseCPClassReferences(String name, InputStream in, BHSDCodec codec, int count) throws IOException, Pack200Exception {
+ String[] reference = segment.getCpBands().getCpClass();
+ int[] indices = decodeBandInt(name, in, codec, count, reference.length - 1);
+ CPClass[] result = new CPClass[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 CPClass(reference[index]);
}
return result;
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/BcBands.java Fri Jan 4 03:14:19 2008
@@ -19,7 +19,6 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
@@ -27,7 +26,6 @@
import org.apache.harmony.pack200.bytecode.BCIRenumberedAttribute;
import org.apache.harmony.pack200.bytecode.ByteCode;
import org.apache.harmony.pack200.bytecode.CodeAttribute;
-import org.apache.harmony.pack200.bytecode.LineNumberTableAttribute;
import org.apache.harmony.pack200.bytecode.OperandManager;
/**
@@ -70,14 +68,6 @@
*/
public BcBands(Segment segment) {
super(segment);
- }
-
- /* (non-Javadoc)
- * @see org.apache.harmony.pack200.BandSet#pack(java.io.OutputStream)
- */
- public void pack(OutputStream outputStream) {
- // TODO Auto-generated method stub
-
}
/* (non-Javadoc)
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/ClassBands.java Fri Jan 4 03:14:19 2008
@@ -18,16 +18,18 @@
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Iterator;
+import java.util.List;
import org.apache.harmony.pack200.IcBands.ICTuple;
import org.apache.harmony.pack200.bytecode.Attribute;
import org.apache.harmony.pack200.bytecode.CPClass;
+import org.apache.harmony.pack200.bytecode.CPNameAndType;
import org.apache.harmony.pack200.bytecode.CPUTF8;
import org.apache.harmony.pack200.bytecode.ClassConstantPool;
import org.apache.harmony.pack200.bytecode.ConstantValueAttribute;
+import org.apache.harmony.pack200.bytecode.EnclosingMethodAttribute;
import org.apache.harmony.pack200.bytecode.ExceptionsAttribute;
import org.apache.harmony.pack200.bytecode.LineNumberTableAttribute;
import org.apache.harmony.pack200.bytecode.LocalVariableTableAttribute;
@@ -36,7 +38,7 @@
import org.apache.harmony.pack200.bytecode.SourceFileAttribute;
/**
- *
+ * Pack200 Class Bands
*/
public class ClassBands extends BandSet {
@@ -106,16 +108,6 @@
/*
* (non-Javadoc)
*
- * @see org.apache.harmony.pack200.BandSet#pack(java.io.OutputStream)
- */
- public void pack(OutputStream outputStream) {
- // TODO Auto-generated method stub
-
- }
-
- /*
- * (non-Javadoc)
- *
* @see org.apache.harmony.pack200.BandSet#unpack(java.io.InputStream)
*/
public void unpack(InputStream in) throws IOException, Pack200Exception {
@@ -143,6 +135,10 @@
Pack200Exception {
fieldDescr = parseReferences("field_descr", in, Codec.DELTA5,
classFieldCount, cpBands.getCpDescriptor());
+ parseFieldAttrBands(in);
+ }
+
+ private void parseFieldAttrBands(InputStream in) throws IOException, Pack200Exception {
fieldFlags = parseFlags("field_flags", in, classFieldCount,
Codec.UNSIGNED5, options.hasFieldFlagsHi());
int fieldAttrCount = SegmentUtils.countBit16(fieldFlags);
@@ -154,6 +150,15 @@
AttributeLayout.CONTEXT_FIELD);
int[] fieldAttrCalls = decodeBandInt("field_attr_calls", in,
Codec.UNSIGNED5, callCount);
+
+ // Assign empty field attributes
+ 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();
+ }
+ }
AttributeLayout constantValueLayout = attrMap.getAttributeLayout(
"ConstantValue", AttributeLayout.CONTEXT_FIELD);
@@ -172,11 +177,38 @@
Codec.UNSIGNED5, signatureCount);
int signatureIndex = 0;
- fieldAttributes = new ArrayList[classCount][];
+ int backwardsCallsUsed = parseFieldMetadataBands(in, fieldAttrCalls);
+
+ // Parse non-predefined attribute bands
+ int backwardsCallIndex = backwardsCallsUsed;
+ int limit = options.hasFieldFlagsHi() ? 62 : 31;
+ AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
+ int[] counts = new int[limit + 1];
+ List[] otherAttributes = new List[limit + 1];
+ for (int i = 0; i < limit; i++) {
+ AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_FIELD);
+ if(layout != null && !(layout.isDefaultLayout())) {
+ otherLayouts[i] = layout;
+ counts[i] = SegmentUtils.countMatches(fieldFlags,
+ layout);
+ }
+ }
+ for (int i = 0; i < counts.length; i++) {
+ if(counts[i] > 0) {
+ NewAttributeBands bands = attrMap.getAttributeBands(otherLayouts[i]);
+ otherAttributes[i] = bands.parseAttributes(in, counts[i]);
+ int numBackwardsCallables = otherLayouts[i].numBackwardsCallables();
+ if(numBackwardsCallables > 0) {
+ int[] backwardsCalls = new int[numBackwardsCallables];
+ System.arraycopy(fieldAttrCalls, backwardsCallIndex, backwardsCalls, 0, numBackwardsCallables);
+ bands.setBackwardsCalls(backwardsCalls);
+ backwardsCallIndex+= numBackwardsCallables;
+ }
+ }
+ }
+
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 (constantValueLayout.matches(flag)) {
// we've got a value to read
@@ -205,20 +237,28 @@
.add(new SignatureAttribute(value));
signatureIndex++;
}
+ // Non-predefined attributes
+ for (int k = 0; k < otherLayouts.length; k++) {
+ if(otherLayouts[k] != null && otherLayouts[k].matches(flag)) {
+ // Add the next attribute
+ fieldAttributes[i][j].add(otherAttributes[k].get(0));
+ otherAttributes[k].remove(0);
+ }
+ }
}
}
- parseFieldMetadataBands(in, fieldAttrCalls);
-
- // TODO: Parse other attribute bands
}
private void parseMethodBands(InputStream in) throws IOException,
Pack200Exception {
methodDescr = parseReferences("method_descr", in, Codec.MDELTA5,
- classMethodCount, cpBands.getCpDescriptor());
+ classMethodCount, cpBands.getCpDescriptor());
+ parseMethodAttrBands(in);
+ }
+
+ private void parseMethodAttrBands(InputStream in) throws IOException, Pack200Exception {
methodFlags = parseFlags("method_flags", in, classMethodCount,
Codec.UNSIGNED5, options.hasMethodFlagsHi());
-
int methodAttrCount = SegmentUtils.countBit16(methodFlags);
int[] methodAttrCounts = decodeBandInt("method_attr_count", in,
Codec.UNSIGNED5, methodAttrCount);
@@ -228,7 +268,7 @@
AttributeLayout.CONTEXT_METHOD);
methodAttrCalls = decodeBandInt("code_attr_calls", in, Codec.UNSIGNED5,
callCount);
-
+
// assign empty method attributes
methodAttributes = new ArrayList[classCount][];
for (int i = 0; i < classCount; i++) {
@@ -237,11 +277,98 @@
methodAttributes[i][j] = new ArrayList();
}
}
- parseAttributeMethodExceptions(in);
- parseAttributeMethodSigntaure(in);
- parseMethodMetadataBands(in, methodAttrCalls);
- // TODO: Parse other attribute bands
+ // Parse method exceptions attributes
+ AttributeLayout methodExceptionsLayout = attrMap.getAttributeLayout(AttributeLayout.ATTRIBUTE_EXCEPTIONS,
+ AttributeLayout.CONTEXT_METHOD);
+ int count = SegmentUtils.countMatches(methodFlags, methodExceptionsLayout);
+ int[] numExceptions = decodeBandInt("method_Exceptions_n", in,
+ Codec.UNSIGNED5, count);
+ String[][] methodExceptionsRS = parseReferences("method_Exceptions_RC",
+ in, Codec.UNSIGNED5, numExceptions, cpBands.getCpClass());
+
+ // Parse method signature attributes
+ AttributeLayout methodSignatureLayout = attrMap.getAttributeLayout(
+ AttributeLayout.ATTRIBUTE_SIGNATURE,
+ AttributeLayout.CONTEXT_METHOD);
+ int count1 = SegmentUtils.countMatches(methodFlags, methodSignatureLayout);
+ long[] methodSignatureRS = decodeBandLong("method_signature_RS", in,
+ Codec.UNSIGNED5, count1);
+
+ // Parse method metadata bands
+ int backwardsCallsUsed = parseMethodMetadataBands(in, methodAttrCalls);
+
+ // Parse non-predefined attribute bands
+ int backwardsCallIndex = backwardsCallsUsed;
+ int limit = options.hasMethodFlagsHi() ? 62 : 31;
+ AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
+ int[] counts = new int[limit + 1];
+ List[] otherAttributes = new List[limit + 1];
+ for (int i = 0; i < limit; i++) {
+ AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_METHOD);
+ if(layout != null && !(layout.isDefaultLayout())) {
+ otherLayouts[i] = layout;
+ counts[i] = SegmentUtils.countMatches(methodFlags,
+ layout);
+ }
+ }
+ for (int i = 0; i < counts.length; i++) {
+ if(counts[i] > 0) {
+ NewAttributeBands bands = attrMap.getAttributeBands(otherLayouts[i]);
+ otherAttributes[i] = bands.parseAttributes(in, counts[i]);
+ int numBackwardsCallables = otherLayouts[i].numBackwardsCallables();
+ if(numBackwardsCallables > 0) {
+ int[] backwardsCalls = new int[numBackwardsCallables];
+ System.arraycopy(methodAttrCalls, backwardsCallIndex, backwardsCalls, 0, numBackwardsCallables);
+ bands.setBackwardsCalls(backwardsCalls);
+ backwardsCallIndex+= numBackwardsCallables;
+ }
+ }
+ }
+
+ // Add attributes to the attribute arrays
+ int methodExceptionsIndex = 0;
+ int methodSignatureIndex = 0;
+ for (int i = 0; i < methodAttributes.length; i++) {
+ for (int j = 0; j < methodAttributes[i].length; j++) {
+ long flag = methodFlags[i][j];
+ if (methodExceptionsLayout.matches(flag)) {
+ int n = numExceptions[methodExceptionsIndex];
+ String[] exceptions = methodExceptionsRS[methodExceptionsIndex];
+ CPClass[] exceptionClasses = new CPClass[n];
+ for (int k = 0; k < n; k++) {
+ exceptionClasses[k] = new CPClass(exceptions[k]);
+ }
+ methodAttributes[i][j].add(new ExceptionsAttribute(
+ exceptionClasses));
+ methodExceptionsIndex++;
+ }
+ if (methodSignatureLayout.matches(flag)) {
+ // We've got a signature attribute
+ long result = methodSignatureRS[methodSignatureIndex];
+ String desc = methodDescr[i][j];
+ int colon = desc.indexOf(':');
+ 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 = methodSignatureLayout.getValue(result, type, cpBands
+ .getConstantPool());
+ methodAttributes[i][j]
+ .add(new ConstantValueAttribute(value));
+ methodSignatureIndex++;
+ }
+ // Non-predefined attributes
+ for (int k = 0; k < otherLayouts.length; k++) {
+ if(otherLayouts[k] != null && otherLayouts[k].matches(flag)) {
+ // Add the next attribute
+ methodAttributes[i][j].add(otherAttributes[k].get(0));
+ otherAttributes[k].remove(0);
+ }
+ }
+ }
+ }
}
private int getCallCount(int[][] methodAttrIndexes, long[][] flags,
@@ -270,71 +397,6 @@
return callCount;
}
- 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 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++;
- }
- }
- }
- }
-
- /**
- * @param in
- * @throws Pack200Exception
- * @throws IOException
- */
- private void parseAttributeMethodExceptions(InputStream in)
- throws Pack200Exception, IOException {
- AttributeLayout layout = attrMap.getAttributeLayout("Exceptions",
- AttributeLayout.CONTEXT_METHOD);
- 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++) {
- for (int j = 0; j < methodFlags[i].length; j++) {
- long flag = methodFlags[i][j];
- 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]);
- }
- methodAttributes[i][j].add(new ExceptionsAttribute(
- exceptionClasses));
- index++;
- }
- }
- }
- }
-
private void parseClassAttrBands(InputStream in) throws IOException,
Pack200Exception {
String[] cpUTF8 = cpBands.getCpUTF8();
@@ -371,10 +433,11 @@
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);
+ String[] enclosingMethodRC = parseReferences(
+ "class_EnclosingMethod_RC", in, Codec.UNSIGNED5,
+ enclosingMethodCount, cpClass);
+ String[] enclosingMethodRDN = parseReferences(
+ "class_EnclosingMethod_RDN", in, Codec.UNSIGNED5, enclosingMethodCount, cpBands.getCpDescriptor());
AttributeLayout signatureLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_SIGNATURE,
@@ -384,7 +447,7 @@
int[] classSignature = decodeBandInt("class_Signature_RS", in,
Codec.UNSIGNED5, signatureCount);
- parseClassMetadataBands(in, classAttrCalls);
+ int backwardsCallsUsed = parseClassMetadataBands(in, classAttrCalls);
AttributeLayout innerClassLayout = attrMap.getAttributeLayout(
AttributeLayout.ATTRIBUTE_INNER_CLASSES,
@@ -425,7 +488,34 @@
int defaultVersionMajor = header.getDefaultClassMajorVersion();
int defaultVersionMinor = header.getDefaultClassMinorVersion();
- // TODO: Parse other attribute bands
+
+ // Parse non-predefined attribute bands
+ int backwardsCallIndex = backwardsCallsUsed;
+ int limit = options.hasClassFlagsHi() ? 62 : 31;
+ AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
+ int[] counts = new int[limit + 1];
+ List[] otherAttributes = new List[limit + 1];
+ for (int i = 0; i < limit; i++) {
+ AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_CLASS);
+ if(layout != null && !(layout.isDefaultLayout())) {
+ otherLayouts[i] = layout;
+ counts[i] = SegmentUtils.countMatches(classFlags,
+ layout);
+ }
+ }
+ for (int i = 0; i < counts.length; i++) {
+ if(counts[i] > 0) {
+ NewAttributeBands bands = attrMap.getAttributeBands(otherLayouts[i]);
+ otherAttributes[i] = bands.parseAttributes(in, counts[i]);
+ int numBackwardsCallables = otherLayouts[i].numBackwardsCallables();
+ if(numBackwardsCallables > 0) {
+ int[] backwardsCalls = new int[numBackwardsCallables];
+ System.arraycopy(classAttrCalls, backwardsCallIndex, backwardsCalls, 0, numBackwardsCallables);
+ bands.setBackwardsCalls(backwardsCalls);
+ backwardsCallIndex+= numBackwardsCallables;
+ }
+ }
+ }
// Now process the attribute bands we have parsed
int sourceFileIndex = 0;
@@ -468,7 +558,10 @@
sourceFileIndex++;
}
if (enclosingMethodLayout.matches(flag)) {
- // long result =
+ CPClass theClass = new CPClass(enclosingMethodRC[enclosingMethodIndex]);
+ CPNameAndType theMethod = new CPNameAndType(enclosingMethodRDN[enclosingMethodIndex]);
+ classAttributes[i].add(new EnclosingMethodAttribute(theClass, theMethod));
+ enclosingMethodIndex++;
}
if (signatureLayout.matches(flag)) {
long result = classSignature[signatureIndex];
@@ -514,6 +607,14 @@
classVersionMajor[i] = defaultVersionMajor;
classVersionMinor[i] = defaultVersionMinor;
}
+ // Non-predefined attributes
+ for (int j = 0; j < otherLayouts.length; j++) {
+ if(otherLayouts[j] != null && otherLayouts[j].matches(flag)) {
+ // Add the next attribute
+ classAttributes[i].add(otherAttributes[j].get(0));
+ otherAttributes[j].remove(0);
+ }
+ }
}
}
@@ -689,6 +790,34 @@
"code_LocalVariableTypeTable_slot", in, Codec.UNSIGNED5,
localVariableTypeTableN);
+ // Parse non-predefined attribute bands
+ int backwardsCallIndex = 0;
+ int limit = options.hasCodeFlagsHi() ? 62 : 31;
+ AttributeLayout[] otherLayouts = new AttributeLayout[limit + 1];
+ int[] counts = new int[limit + 1];
+ List[] otherAttributes = new List[limit + 1];
+ for (int i = 0; i < limit; i++) {
+ AttributeLayout layout = attrMap.getAttributeLayout(i, AttributeLayout.CONTEXT_CODE);
+ if(layout != null && !(layout.isDefaultLayout())) {
+ otherLayouts[i] = layout;
+ counts[i] = SegmentUtils.countMatches(codeFlags,
+ layout);
+ }
+ }
+ for (int i = 0; i < counts.length; i++) {
+ if(counts[i] > 0) {
+ NewAttributeBands bands = attrMap.getAttributeBands(otherLayouts[i]);
+ otherAttributes[i] = bands.parseAttributes(in, counts[i]);
+ int numBackwardsCallables = otherLayouts[i].numBackwardsCallables();
+ if(numBackwardsCallables > 0) {
+ int[] backwardsCalls = new int[numBackwardsCallables];
+ System.arraycopy(codeAttrCalls, backwardsCallIndex, backwardsCalls, 0, numBackwardsCallables);
+ bands.setBackwardsCalls(backwardsCalls);
+ backwardsCallIndex+= numBackwardsCallables;
+ }
+ }
+ }
+
int lineNumberIndex = 0;
int lvtIndex = 0;
int lvttIndex = 0;
@@ -723,8 +852,16 @@
lvttIndex++;
codeAttributes[i].add(lvtta);
}
+ // Non-predefined attributes
+ for (int j = 0; j < otherLayouts.length; j++) {
+ if(otherLayouts[j] != null && otherLayouts[j].matches(codeFlags[i])) {
+ // Add the next attribute
+ codeAttributes[i].add(otherAttributes[j].get(0));
+ otherAttributes[j].remove(0);
+ }
+ }
}
- // TODO: Parse other attribute bands
+
}
private CPUTF8[][] stringsToCPUTF8(String[][] strings) {
@@ -748,8 +885,9 @@
return cpUTF8s;
}
- private void parseFieldMetadataBands(InputStream in, int[] fieldAttrCalls)
+ private int parseFieldMetadataBands(InputStream in, int[] fieldAttrCalls)
throws Pack200Exception, IOException {
+ int backwardsCallsUsed = 0;
String[] RxA = new String[] { "RVA", "RIA" };
AttributeLayout rvaLayout = attrMap.getAttributeLayout(
@@ -765,11 +903,14 @@
int[] backwardsCalls = new int[] {0, 0};
if(rvaCount > 0) {
backwardsCalls[0] = fieldAttrCalls[0];
+ backwardsCallsUsed++;
if(riaCount > 0) {
backwardsCalls[1] = fieldAttrCalls[1];
+ backwardsCallsUsed++;
}
} else if (riaCount > 0) {
backwardsCalls[1] = fieldAttrCalls[0];
+ backwardsCallsUsed++;
}
MetadataBandGroup[] mb = parseMetadata(in, RxA, RxACount, backwardsCalls, "field");
Iterator rvaAttributesIterator = mb[0].getAttributes().iterator();
@@ -784,6 +925,7 @@
}
}
}
+ return backwardsCallsUsed;
}
private MetadataBandGroup[] parseMetadata(InputStream in, String[] RxA, int[] RxACount,
@@ -884,14 +1026,16 @@
return mbg;
}
- private void parseMethodMetadataBands(InputStream in, int[] methodAttrCalls)
+ private int parseMethodMetadataBands(InputStream in, int[] methodAttrCalls)
throws Pack200Exception, IOException {
+ int backwardsCallsUsed = 0;
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) {
+ backwardsCallsUsed++;
backwardsCalls[i] = methodAttrCalls[methodAttrIndex];
methodAttrIndex++;
} else {
@@ -936,9 +1080,19 @@
}
}
}
+ return backwardsCallsUsed;
}
- private void parseClassMetadataBands(InputStream in, int[] classAttrCalls) throws Pack200Exception, IOException {
+ /**
+ * Parse the class metadata bands and return the number of backwards callables
+ * @param in
+ * @param classAttrCalls
+ * @return
+ * @throws Pack200Exception
+ * @throws IOException
+ */
+ private int parseClassMetadataBands(InputStream in, int[] classAttrCalls) throws Pack200Exception, IOException {
+ int numBackwardsCalls = 0;
String[] RxA = new String[] { "RVA", "RIA" };
AttributeLayout rvaLayout = attrMap.getAttributeLayout(
@@ -952,11 +1106,14 @@
int[] RxACount = new int[] { rvaCount, riaCount };
int[] backwardsCalls = new int[] {0, 0};
if(rvaCount > 0) {
+ numBackwardsCalls++;
backwardsCalls[0] = classAttrCalls[0];
if(riaCount > 0) {
+ numBackwardsCalls++;
backwardsCalls[1] = classAttrCalls[1];
}
} else if (riaCount > 0) {
+ numBackwardsCalls++;
backwardsCalls[1] = classAttrCalls[0];
}
MetadataBandGroup[] mbgs = parseMetadata(in, RxA, RxACount, backwardsCalls, "class");
@@ -970,6 +1127,7 @@
classAttributes[i].add(riaAttributesIterator.next());
}
}
+ return numBackwardsCalls;
}
public int[] getClassFieldCount() {
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/CpBands.java Fri Jan 4 03:14:19 2008
@@ -18,7 +18,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
import java.util.ArrayList;
public class CpBands extends BandSet {
@@ -78,10 +77,6 @@
parseCpField(in);
parseCpMethod(in);
parseCpIMethod(in);
- }
-
- public void pack(OutputStream outputStream) {
-
}
/**
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/FileBands.java Fri Jan 4 03:14:19 2008
@@ -18,7 +18,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
/**
* Parses the file band headers (not including the actual bits themselves).
@@ -48,14 +47,6 @@
public FileBands(Segment segment) {
super(segment);
this.cpUTF8 = segment.getCpBands().getCpUTF8();
- }
-
- /* (non-Javadoc)
- * @see org.apache.harmony.pack200.BandSet#pack(java.io.OutputStream)
- */
- public void pack(OutputStream outputStream) {
- // TODO Auto-generated method stub
-
}
/* (non-Javadoc)
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/IcBands.java Fri Jan 4 03:14:19 2008
@@ -18,7 +18,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
/**
* Pack200 Inner Class Bands
@@ -47,14 +46,6 @@
super(segment);
this.cpClass = segment.getCpBands().getCpClass();
this.cpUTF8 = segment.getCpBands().getCpUTF8();
- }
-
- /* (non-Javadoc)
- * @see org.apache.harmony.pack200.BandSet#pack(java.io.OutputStream)
- */
- public void pack(OutputStream outputStream) {
- // TODO Auto-generated method stub
-
}
/* (non-Javadoc)
Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java?rev=608801&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java (added)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java Fri Jan 4 03:14:19 2008
@@ -0,0 +1,920 @@
+/*
+ * 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.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.harmony.pack200.bytecode.Attribute;
+import org.apache.harmony.pack200.bytecode.CPClass;
+import org.apache.harmony.pack200.bytecode.CPDouble;
+import org.apache.harmony.pack200.bytecode.CPFieldRef;
+import org.apache.harmony.pack200.bytecode.CPFloat;
+import org.apache.harmony.pack200.bytecode.CPInteger;
+import org.apache.harmony.pack200.bytecode.CPInterfaceMethodRef;
+import org.apache.harmony.pack200.bytecode.CPLong;
+import org.apache.harmony.pack200.bytecode.CPMethodRef;
+import org.apache.harmony.pack200.bytecode.CPNameAndType;
+import org.apache.harmony.pack200.bytecode.CPString;
+import org.apache.harmony.pack200.bytecode.CPUTF8;
+import org.apache.harmony.pack200.bytecode.NewAttribute;
+
+/**
+ * Set of bands relating to a non-predefined attribute
+ */
+public class NewAttributeBands extends BandSet {
+
+ private AttributeLayout attributeLayout;
+
+ private List attributes;
+
+ private int backwardsCallCount;
+
+ private List attributeLayoutElements;
+
+ public NewAttributeBands(Segment segment, AttributeLayout attributeLayout) throws IOException {
+ super(segment);
+ this.attributeLayout = attributeLayout;
+ parseLayout();
+ attributeLayout.setBackwardsCallCount(backwardsCallCount);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.harmony.pack200.BandSet#unpack(java.io.InputStream)
+ */
+ public void unpack(InputStream in) throws IOException, Pack200Exception {
+ // does nothing - use parseAttributes instead
+ }
+
+ /**
+ * Returns the list of attributes read in by this band set. This method
+ * should only be called after unpack() or it will return null.
+ * @return List of Attributes
+ */
+ public List getAttributes() {
+ return attributes;
+ }
+
+ /**
+ * Parse the bands relating to this AttributeLayout and return the correct
+ * class file attributes as a List of {@link Attribute}
+ * @throws Pack200Exception
+ */
+ public List parseAttributes(InputStream in, int occurrenceCount)
+ throws IOException, Pack200Exception {
+ for (Iterator iter = attributeLayoutElements.iterator(); iter.hasNext();) {
+ AttributeLayoutElement element = (AttributeLayoutElement) iter.next();
+ element.readBands(in, occurrenceCount);
+ }
+
+ List attributes = new ArrayList();
+ for (int i = 0; i < occurrenceCount; i++) {
+ attributes.add(getOneAttribute(i, attributeLayoutElements));
+ }
+ return attributes;
+ }
+
+ /**
+ * Get one attribute at the given index from the various bands.
+ * The correct bands must have already been read in.
+ * @param index
+ * @param elements
+ * @return
+ */
+ private Attribute getOneAttribute(int index, List elements) {
+ NewAttribute attribute = new NewAttribute(attributeLayout.getName());
+ for (Iterator iter = elements.iterator(); iter.hasNext();) {
+ AttributeLayoutElement element = (AttributeLayoutElement) iter.next();
+ element.addToAttribute(index, attribute);
+ }
+ return attribute;
+ }
+
+ /**
+ * Tokenise the layout into AttributeElements
+ * @return a List of AttributeElements
+ * @throws IOException
+ */
+ private void parseLayout() throws IOException {
+ if(attributeLayoutElements == null) {
+ attributeLayoutElements = new ArrayList();
+ StringReader stream = new StringReader(attributeLayout.getLayout());
+ AttributeLayoutElement e;
+ while ((e = readNextAttributeElement(stream)) != null) {
+ attributeLayoutElements.add(e);
+ }
+ resolveCalls();
+ }
+ }
+
+ /**
+ * Resolve calls in the attribute layout and returns the number of backwards calls
+ *
+ * @param tokens -
+ * the attribute layout as a List of AttributeElements
+ */
+ private void resolveCalls() {
+ int backwardsCalls = 0;
+ for (int i = 0; i < attributeLayoutElements.size(); i++) {
+ AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElements.get(i);
+ if (element instanceof Callable) {
+ Callable callable = (Callable) element;
+ List body = callable.body; // Look for calls in the body
+ for (Iterator iter = body.iterator(); iter.hasNext();) {
+ LayoutElement layoutElement = (LayoutElement) iter.next();
+ if (layoutElement instanceof Call) {
+ // Set the callable for each call
+ Call call = (Call) layoutElement;
+ int index = call.callableIndex;
+ if (index == 0) { // Calls the parent callable
+ backwardsCalls++;
+ call.setCallable(callable);
+ } else if (index > 0) { // Forwards call
+ for (int k = i; k < attributeLayoutElements.size(); k++) {
+ AttributeLayoutElement el = (AttributeLayoutElement) attributeLayoutElements
+ .get(k);
+ if (el instanceof Callable) {
+ index--;
+ if (index == 0) {
+ call.setCallable((Callable) el);
+ break;
+ }
+ }
+ }
+ } else { // Backwards call
+ backwardsCalls++;
+ for (int k = i; k >= 0; k--) {
+ AttributeLayoutElement el = (AttributeLayoutElement) attributeLayoutElements
+ .get(k);
+ if (el instanceof Callable) {
+ index++;
+ if (index == 0) {
+ call.setCallable((Callable) el);
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ backwardsCallCount = backwardsCalls;
+ }
+
+ private AttributeLayoutElement readNextAttributeElement(StringReader stream)
+ throws IOException {
+ int nextChar = stream.read();
+ if (nextChar == -1) {
+ return null;
+ }
+ if (nextChar == '[') {
+ List body = readBody(getStreamUpToMatchingBracket(stream));
+ return new Callable(body);
+ } else {
+ return readNextLayoutElement(stream);
+ }
+ }
+
+ private LayoutElement readNextLayoutElement(StringReader stream)
+ throws IOException {
+ int nextChar = stream.read();
+ if (nextChar == -1) {
+ return null;
+ }
+ switch (nextChar) {
+ // Integrals
+ case 'B':
+ case 'H':
+ case 'I':
+ case 'V':
+ return new Integral(new String(new char[] { (char) nextChar }));
+ case 'S':
+ case 'F':
+ return new Integral(new String(new char[] { (char) nextChar,
+ (char) stream.read() }));
+ case 'P':
+ stream.mark(1);
+ if (stream.read() != 'O') {
+ stream.reset();
+ return new Integral("P" + (char) stream.read());
+ } else {
+ return new Integral("PO" + (char) stream.read());
+ }
+ case 'O':
+ stream.mark(1);
+ if (stream.read() != 'S') {
+ stream.reset();
+ return new Integral("O" + (char) stream.read());
+ } else {
+ return new Integral("OS" + (char) stream.read());
+ }
+
+ // Replication
+ case 'N':
+ char uint_type = (char) stream.read();
+ stream.read(); // '['
+ String str = readUpToMatchingBracket(stream);
+ return new Replication("" + uint_type, str);
+
+ // Union
+ case 'T':
+ String int_type = "" + (char) stream.read();
+ if (int_type.equals("S")) {
+ int_type += (char) stream.read();
+ }
+ List unionCases = new ArrayList();
+ UnionCase c;
+ while ((c = readNextUnionCase(stream)) != null) {
+ unionCases.add(c);
+ }
+ stream.read(); // '('
+ stream.read(); // '('
+ stream.read(); // '['
+ List body = null;
+ stream.mark(1);
+ char next = (char) stream.read();
+ if (next != ']') {
+ stream.reset();
+ body = readBody(getStreamUpToMatchingBracket(stream));
+ }
+ return new Union(int_type, unionCases, body);
+
+ // Call
+ case '(':
+ int number = readNumber(stream);
+ stream.read(); // ')'
+ return new Call(number);
+ // Reference
+ case 'K':
+ case 'R':
+ String string = "" + nextChar + (char) stream.read();
+ char nxt = (char) stream.read();
+ string += nxt;
+ if (nxt == 'N') {
+ string += (char) stream.read();
+ }
+ return new Reference(string);
+ }
+ return null;
+ }
+
+ /**
+ * Read a UnionCase from the stream
+ * @param stream
+ * @return
+ * @throws IOException
+ */
+ private UnionCase readNextUnionCase(StringReader stream) throws IOException {
+ stream.mark(2);
+ stream.read(); // '('
+ char next = (char) stream.read();
+ if (next == ')') {
+ stream.reset();
+ return null;
+ }
+ List tags = new ArrayList();
+ while (next != ')') {
+ tags.add(new Integer(readNumber(stream)));
+ next = (char) stream.read();
+ }
+ stream.read(); // '['
+ stream.mark(1);
+ next = (char) stream.read();
+ if (next == ']') {
+ return new UnionCase(tags);
+ } else {
+ stream.reset();
+ return new UnionCase(tags,
+ readBody(getStreamUpToMatchingBracket(stream)));
+ }
+ }
+
+ /**
+ * An AttributeLayoutElement is a part of an attribute layout and has one or more
+ * bands associated with it, which transmit the AttributeElement data for
+ * successive Attributes of this type.
+ */
+ private interface AttributeLayoutElement {
+
+ /**
+ * Read the bands associated with this part of the layout
+ *
+ * @param in
+ * @param count
+ * @throws Pack200Exception
+ * @throws IOException
+ */
+ public void readBands(InputStream in, int count) throws IOException, Pack200Exception;
+
+ /**
+ * Add the band data for this element at the given index to the attribute
+ *
+ * @param index
+ * @param attribute
+ */
+ public void addToAttribute(int index, NewAttribute attribute);
+
+ }
+
+ private abstract class LayoutElement implements AttributeLayoutElement {
+
+ protected int getLength(char uint_type) {
+ int length = 0;;
+ switch(uint_type) {
+ case 'B':
+ length = 1;
+ break;
+ case 'H':
+ length = 2;
+ break;
+ case 'I':
+ length = 4;
+ break;
+ case 'V':
+ length = 0;
+ break;
+ }
+ return length;
+ }
+ }
+
+ private class Integral extends LayoutElement {
+
+ private String tag;
+ private long[] band;
+
+ public Integral(String tag) {
+ this.tag = tag;
+ }
+
+ public void readBands(InputStream in, int count) throws IOException, Pack200Exception {
+ band = decodeBandLong(attributeLayout.getName() + "_" + tag, in, (BHSDCodec) getCodec(tag), count);
+ }
+
+ public void addToAttribute(int n, NewAttribute attribute) {
+ long value = band[n];
+ if(tag.equals("B") || tag.equals("FB")) {
+ attribute.addInteger(1, value);
+ } else if (tag.equals("SB")) {
+ attribute.addInteger(1, (byte)value);
+ } else if(tag.equals("H") || tag.equals("FH")) {
+ attribute.addInteger(2, value);
+ } else if (tag.equals("SH")) {
+ attribute.addInteger(2, (short)value);
+ } else if (tag.equals("I") || tag.equals("FI")) {
+ attribute.addInteger(4, value);
+ } else if (tag.equals("SI")) {
+ attribute.addInteger(4, (int) value);
+ } else if (tag.equals("V") || tag.equals("FV") || tag.equals("SV")) {
+ // Don't add V's - they shouldn't be written out to the class file
+ } else if (tag.startsWith("PO")) {
+ char uint_type = tag.substring(2).toCharArray()[0];
+ int length = getLength(uint_type);
+ attribute.addBCOffset(length, value);
+ } else if (tag.startsWith("P")) {
+ char uint_type = tag.substring(1).toCharArray()[0];
+ int length = getLength(uint_type);
+ attribute.addBCIndex(length, value);
+ } else if (tag.startsWith("OS")) {
+ char uint_type = tag.substring(1).toCharArray()[0];
+ int length = getLength(uint_type);
+ if(length == 1) {
+ value = (byte)value;
+ } else if(length == 2) {
+ value = (short)value;
+ } else if(length == 4) {
+ value = (int)value;
+ }
+ attribute.addBCLength(length, value);
+ } else if (tag.startsWith("O")) {
+ char uint_type = tag.substring(1).toCharArray()[0];
+ int length = getLength(uint_type);
+ attribute.addBCLength(length, value);
+ }
+ }
+
+ long getValue(int index) {
+ return band[index];
+ }
+
+ }
+
+ /**
+ * A replication is an array of layout elements, with an associated count
+ */
+ private class Replication extends LayoutElement {
+
+ private Integral countElement;
+
+ private List layoutElements = new ArrayList();
+
+ public Replication(String tag, String contents) throws IOException {
+ this.countElement = new Integral(tag);
+ StringReader stream = new StringReader(contents);
+ LayoutElement e;
+ while ((e = readNextLayoutElement(stream)) != null) {
+ layoutElements.add(e);
+ }
+ }
+
+ public void readBands(InputStream in, int count) throws IOException, Pack200Exception {
+ countElement.readBands(in, count);
+ int arrayCount = 0;
+ for (int i = 0; i < count; i++) {
+ arrayCount += countElement.getValue(i);
+ }
+ for (Iterator iter = layoutElements.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.readBands(in, arrayCount);
+ }
+ }
+
+ public void addToAttribute(int index, NewAttribute attribute) {
+ // Add the count value
+ countElement.addToAttribute(index, attribute);
+
+ // Add the corresponding array values
+ int offset = 0;
+ for (int i = 0; i < index; i++) {
+ offset += countElement.getValue(i);
+ }
+ long numElements = countElement.getValue(index);
+ for (int i = offset; i < offset + numElements; i++) {
+ for (Iterator iter = layoutElements.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.addToAttribute(i, attribute);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * A Union is a type of layout element where the tag value acts as a
+ * selector for one of the union cases
+ */
+ private class Union extends LayoutElement {
+
+ private Integral unionTag;
+ private List unionCases;
+ private List defaultCaseBody;
+ private int[] caseCounts;
+ private int defaultCount;
+
+ public Union(String tag, List unionCases, List body) {
+ this.unionTag = new Integral(tag);
+ this.unionCases = unionCases;
+ this.defaultCaseBody = body;
+ }
+
+ public void readBands(InputStream in, int count) throws IOException, Pack200Exception {
+ unionTag.readBands(in, count);
+ long[] values = unionTag.band;
+ // Count the band size for each union case then read the bands
+ caseCounts = new int[unionCases.size()];
+ for (int i = 0; i < caseCounts.length; i++) {
+ UnionCase unionCase = (UnionCase) unionCases.get(i);
+ for (int j = 0; j < values.length; j++) {
+ if(unionCase.hasTag(values[j])) {
+ caseCounts[i]++;
+ }
+ }
+ unionCase.readBands(in, caseCounts[i]);
+ }
+ // Count number of default cases then read the default bands
+ for (int i = 0; i < values.length; i++) {
+ boolean found = false;
+ for (Iterator iter = unionCases.iterator(); iter.hasNext();) {
+ UnionCase unionCase = (UnionCase) iter.next();
+ if(unionCase.hasTag(values[i])) {
+ found = true;
+ }
+ }
+ if(!found) {
+ defaultCount++;
+ }
+ }
+ if(defaultCaseBody != null) {
+ for (Iterator iter = defaultCaseBody.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.readBands(in, defaultCount);
+ }
+ }
+ }
+
+ public void addToAttribute(int n, NewAttribute attribute) {
+ unionTag.addToAttribute(n, attribute);
+ int offset = 0;
+ long[] tagBand = unionTag.band;
+ long tag = unionTag.getValue(n);
+ boolean defaultCase = true;
+ for (Iterator iter = unionCases.iterator(); iter.hasNext();) {
+ UnionCase element = (UnionCase) iter.next();
+ if(element.hasTag(tag)) {
+ defaultCase = false;
+ for (int j = 0; j < n; j++) {
+ if(element.hasTag(tagBand[j])) {
+ offset++;
+ }
+ }
+ element.addToAttribute(offset, attribute);
+ }
+ }
+ if(defaultCase) {
+ // default case
+ int defaultOffset = 0;
+ for (int j = 0; j < n; j++) {
+ boolean found = false;
+ for (Iterator iter = unionCases.iterator(); iter.hasNext();) {
+ UnionCase element = (UnionCase) iter.next();
+ if(element.hasTag(tagBand[j])) {
+ found = true;
+ }
+ }
+ if(!found) {
+ defaultOffset++;
+ }
+ }
+ if(defaultCaseBody != null) {
+ for (Iterator iter = defaultCaseBody.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.addToAttribute(defaultOffset, attribute);
+ }
+ }
+ }
+ }
+
+ }
+
+ private class Call extends LayoutElement {
+
+ private int callableIndex;
+ private Callable callable;
+
+ public Call(int callableIndex) {
+ this.callableIndex = callableIndex;
+ }
+
+ public void setCallable(Callable callable) {
+ this.callable = callable;
+ if(callableIndex < 1) {
+ callable.setBackwardsCallable();
+ }
+ }
+
+ public void readBands(InputStream in, int count) {
+ /*
+ * We don't read anything here, but we need to pass the extra count
+ * to the callable if it's a forwards call. For backwards callables
+ * the count is transmitted directly in the attribute bands and
+ * so it is added later.
+ */
+ if(callableIndex > 0) {
+ callable.addCount(count);
+ }
+ }
+
+ public void addToAttribute(int n, NewAttribute attribute) {
+ callable.addNextToAttribute(attribute);
+ }
+ }
+
+ /**
+ * Constant Pool Reference
+ */
+ private class Reference extends LayoutElement {
+
+ private String tag;
+
+ private Object band;
+
+ private int length;
+
+ public Reference(String tag) {
+ this.tag = tag;
+ length = getLength(tag.charAt(tag.length()));
+ }
+
+ public void readBands(InputStream in, int count) throws IOException, Pack200Exception {
+ if(tag.startsWith("KI")) { // Integer
+ band = parseCPIntReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("KJ")) { // Long
+ band = parseCPLongReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("KF")) { // Float
+ band = parseCPFloatReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("KD")) { // Double
+ band = parseCPDoubleReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("KS")) { // String
+ band = parseCPStringReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("RC")) { // Class
+ band = parseCPClassReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("RS")) { // Signature
+ band = parseCPSignatureReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("RD")) { // Descriptor
+ band = parseCPDescriptorReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("RF")) { // Field Reference
+ band = parseCPFieldRefReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("RM")) { // Method Reference
+ band = parseCPMethodRefReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("RI")) { // Interface Method Reference
+ band = parseCPInterfaceMethodRefReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ } else if(tag.startsWith("RU")) { // UTF8 String
+ band = parseCPUTF8References(attributeLayout.getName(), in, Codec.UNSIGNED5, count);
+ }
+ }
+
+ public void addToAttribute(int n, NewAttribute attribute) {
+ if(tag.startsWith("KI")) { // Integer
+ attribute.addCPConstant(length, ((CPInteger[])band)[n]);
+ } else if(tag.startsWith("KJ")) { // Long
+ attribute.addCPConstant(length, ((CPLong[])band)[n]);
+ } else if(tag.startsWith("KF")) { // Float
+ attribute.addCPConstant(length, ((CPFloat[])band)[n]);
+ } else if(tag.startsWith("KD")) { // Double
+ attribute.addCPConstant(length, ((CPDouble[])band)[n]);
+ } else if(tag.startsWith("KS")) { // String
+ attribute.addCPConstant(length, ((CPString[])band)[n]);
+ } else if(tag.startsWith("RC")) { // Class
+ attribute.addCPClass(length, ((CPClass[])band)[n]);
+ } else if(tag.startsWith("RS")) { // Signature
+ attribute.addCPUTF8(length, ((CPUTF8[])band)[n]);
+ } else if(tag.startsWith("RD")) { // Descriptor
+ attribute.addCPNameAndType(length, ((CPNameAndType[])band)[n]);
+ } else if(tag.startsWith("RF")) { // Field Reference
+ attribute.addCPFieldRef(length, ((CPFieldRef[])band)[n]);
+ } else if(tag.startsWith("RM")) { // Method Reference
+ attribute.addCPMethodRef(length, ((CPMethodRef[])band)[n]);
+ } else if(tag.startsWith("RI")) { // Interface Method Reference
+ attribute.addCPIMethodRef(length, ((CPInterfaceMethodRef[])band)[n]);
+ } else if(tag.startsWith("RU")) { // UTF8 String
+ attribute.addCPUTF8(length, ((CPUTF8[])band)[n]);
+ }
+ }
+
+ }
+
+ private class Callable implements AttributeLayoutElement {
+
+ private List body;
+
+ private boolean isBackwardsCallable;
+
+ public Callable(List body) throws IOException {
+ this.body = body;
+ }
+
+ private int count;
+ private int index;
+
+ /**
+ * Used by calls when adding band contents to attributes
+ * so they don't have to keep track of the internal index
+ * of the callable
+ * @param attribute
+ */
+ public void addNextToAttribute(NewAttribute attribute) {
+ for (Iterator iter = body.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.addToAttribute(index, attribute);
+ }
+ index++;
+ }
+
+ /**
+ * Adds the count of a call to this callable (ie the number of calls)
+ * @param count
+ */
+ public void addCount(int count) {
+ this.count += count;
+ }
+
+ public void readBands(InputStream in, int count) throws IOException, Pack200Exception {
+ count += this.count;
+ for (Iterator iter = body.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.readBands(in, count);
+ }
+ }
+
+ public void addToAttribute(int n, NewAttribute attribute) {
+ // Ignore n because bands also contain element parts from calls
+ for (Iterator iter = body.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.addToAttribute(index, attribute);
+ }
+ index++;
+ }
+
+ public boolean isBackwardsCallable() {
+ return isBackwardsCallable;
+ }
+
+ /**
+ * Tells this Callable that it is a backwards callable
+ */
+ public void setBackwardsCallable() {
+ this.isBackwardsCallable = true;
+ }
+ }
+
+ /**
+ * A Union case
+ */
+ private class UnionCase extends LayoutElement {
+
+ private List body;
+
+ private List tags;
+
+ public UnionCase(List tags) {
+ this.tags = tags;
+ }
+
+ public boolean hasTag(long l) {
+ return tags.contains(new Integer((int) l));
+ }
+
+ public UnionCase(List tags, List body) throws IOException {
+ this.tags = tags;
+ this.body = body;
+ }
+
+ public void readBands(InputStream in, int count) throws IOException, Pack200Exception {
+ if(body != null) {
+ for (Iterator iter = body.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.readBands(in, count);
+ }
+ }
+ }
+
+ public void addToAttribute(int index, NewAttribute attribute) {
+ if(body != null) {
+ for (Iterator iter = body.iterator(); iter.hasNext();) {
+ LayoutElement element = (LayoutElement) iter.next();
+ element.addToAttribute(index, attribute);
+ }
+ }
+ }
+ }
+
+ /**
+ * Utility method to get the contents of the given stream, up to the next ']',
+ * (ignoring pairs of brackets '[' and ']')
+ * @param stream
+ * @return
+ * @throws IOException
+ */
+ private StringReader getStreamUpToMatchingBracket(StringReader stream)
+ throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int foundBracket = -1;
+ while (foundBracket != 0) {
+ char c = (char) stream.read();
+ if (c == ']') {
+ foundBracket++;
+ }
+ if (c == '[') {
+ foundBracket--;
+ }
+ if (!(foundBracket == 0)) {
+ sb.append(c);
+ }
+ }
+ return new StringReader(sb.toString());
+ }
+
+ /**
+ * Returns the codec that should be used for the given layout element
+ * @param layoutElement
+ * @return
+ */
+ public BHSDCodec getCodec(String layoutElement) {
+ if (layoutElement.indexOf("O") >= 0) { //$NON-NLS-1$
+ return Codec.BRANCH5;
+ } else if (layoutElement.indexOf("P") >= 0) { //$NON-NLS-1$
+ return Codec.BCI5;
+ } else if (layoutElement.indexOf("S") >= 0 && layoutElement.indexOf("KS") < 0 //$NON-NLS-1$ //$NON-NLS-2$
+ && layoutElement.indexOf("RS") < 0) { //$NON-NLS-1$
+ return Codec.SIGNED5;
+ } else if (layoutElement.indexOf("B") >= 0) { //$NON-NLS-1$
+ return Codec.BYTE1;
+ } else {
+ return Codec.UNSIGNED5;
+ }
+ }
+
+ /**
+ * Utility method to get the contents of the given stream, up to the next ']',
+ * (ignoring pairs of brackets '[' and ']')
+ * @param stream
+ * @return
+ * @throws IOException
+ */
+ private String readUpToMatchingBracket(StringReader stream)
+ throws IOException {
+ StringBuffer sb = new StringBuffer();
+ int foundBracket = -1;
+ while (foundBracket != 0) {
+ char c = (char) stream.read();
+ if (c == ']') {
+ foundBracket++;
+ }
+ if (c == '[') {
+ foundBracket--;
+ }
+ if (!(foundBracket == 0)) {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Read a number from the stream and return it
+ * @param stream
+ * @return
+ * @throws IOException
+ */
+ private int readNumber(StringReader stream) throws IOException {
+ stream.mark(1);
+ char first = (char) stream.read();
+ boolean negative = first == '-';
+ if (!negative) {
+ stream.reset();
+ }
+ stream.mark(100);
+ int i;
+ int length = 0;
+ while ((i = (stream.read())) != -1 && Character.isDigit((char) i)) {
+ length++;
+ }
+ stream.reset();
+ char[] digits = new char[length];
+ stream.read(digits);
+ return Integer.parseInt((negative ? "-" : "") + new String(digits));
+ }
+
+ /**
+ * Read a 'body' section of the layout from the given stream
+ * @param stream
+ * @return List of LayoutElements
+ * @throws IOException
+ */
+ private List readBody(StringReader stream) throws IOException {
+ List layoutElements = new ArrayList();
+ LayoutElement e;
+ while ((e = readNextLayoutElement(stream)) != null) {
+ layoutElements.add(e);
+ }
+ return layoutElements;
+ }
+
+ public int getBackwardsCallCount() {
+ return backwardsCallCount;
+ }
+
+ /**
+ * Once the attribute bands have been read the callables can be informed
+ * about the number of times each is subject to a backwards call. This
+ * method is used to set this information.
+ *
+ * @param backwardsCalls
+ * one int for each backwards callable, which contains the number
+ * of times that callable is subject to a backwards call.
+ * @throws IOException
+ */
+ public void setBackwardsCalls(int[] backwardsCalls) throws IOException {
+ int index = 0;
+ parseLayout();
+ for (Iterator iter = attributeLayoutElements.iterator(); iter.hasNext();) {
+ AttributeLayoutElement element = (AttributeLayoutElement) iter.next();
+ if(element instanceof Callable && ((Callable)element).isBackwardsCallable()) {
+ ((Callable)element).addCount(backwardsCalls[index]);
+ index++;
+ }
+ }
+ }
+
+}
\ No newline at end of file
Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/EnclosingMethodAttribute.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/EnclosingMethodAttribute.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/EnclosingMethodAttribute.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/EnclosingMethodAttribute.java Fri Jan 4 03:14:19 2008
@@ -24,12 +24,12 @@
private int class_index;
private int method_index;
private CPClass cpClass;
- private CPMethod cpMethod;
+ private CPNameAndType method;
- public EnclosingMethodAttribute(CPClass cpClass, CPMethod cpMethod) {
+ public EnclosingMethodAttribute(CPClass cpClass, CPNameAndType method) {
super("EnclosingMethod");
this.cpClass = cpClass;
- this.cpMethod = cpMethod;
+ this.method = method;
}
/* (non-Javadoc)
@@ -43,8 +43,8 @@
super.resolve(pool);
cpClass.resolve(pool);
class_index = pool.indexOf(cpClass);
- cpMethod.resolve(pool);
- method_index = pool.indexOf(cpMethod);
+ method.resolve(pool);
+ method_index = pool.indexOf(method);
}
/* (non-Javadoc)
Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/NewAttribute.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/NewAttribute.java?rev=608801&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/NewAttribute.java (added)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/NewAttribute.java Fri Jan 4 03:14:19 2008
@@ -0,0 +1,113 @@
+/*
+ * 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;
+
+/**
+ * A New (i.e. non-predefined) Class File attribute
+ */
+public class NewAttribute extends Attribute {
+
+ public NewAttribute(String attributeName) {
+ super(attributeName);
+ // TODO Auto-generated constructor stub
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.harmony.pack200.bytecode.Attribute#getLength()
+ */
+ protected int getLength() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.harmony.pack200.bytecode.Attribute#writeBody(java.io.DataOutputStream)
+ */
+ protected void writeBody(DataOutputStream dos) throws IOException {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.harmony.pack200.bytecode.ClassFileEntry#toString()
+ */
+ public String toString() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void addInteger(int length, long value) {
+
+ }
+
+ public void addBCOffset(int length, long value) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addBCIndex(int length, long value) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addBCLength(int length, long value) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addCPConstant(int length, CPConstant constant) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addCPClass(int length, CPClass class1) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addCPUTF8(int length, CPUTF8 cputf8) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addCPNameAndType(int length, CPNameAndType type) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addCPFieldRef(int length, CPFieldRef ref) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addCPMethodRef(int length, CPMethodRef ref) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void addCPIMethodRef(int length, CPInterfaceMethodRef ref) {
+ // TODO Auto-generated method stub
+
+ }
+
+
+
+
+}
Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/bytecode/NewAttribute.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java?rev=608801&r1=608800&r2=608801&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/BandSetTest.java Fri Jan 4 03:14:19 2008
@@ -26,7 +26,6 @@
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;