You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by sj...@apache.org on 2009/06/12 11:32:54 UTC
svn commit: r784048 [1/2] - in
/harmony/enhanced/classlib/trunk/modules/pack200/src:
main/java/org/apache/harmony/pack200/ main/java5/org/apache/harmony/pack200/
test/java/org/apache/harmony/pack200/tests/
Author: sjanuary
Date: Fri Jun 12 09:32:53 2009
New Revision: 784048
URL: http://svn.apache.org/viewvc?rev=784048&view=rev
Log:
Pack200 - support for non-standard class file attributes (-U,-C,-F,-M and -D command line options) and better framework for passing in other command line options.
Added:
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java (with props)
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/PackingOptions.java (with props)
Modified:
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.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/MetadataBandGroup.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Pack200ClassReader.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Segment.java
harmony/enhanced/classlib/trunk/modules/pack200/src/main/java5/org/apache/harmony/pack200/Pack200PackerAdapter.java
harmony/enhanced/classlib/trunk/modules/pack200/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java?rev=784048&r1=784047&r2=784048&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Archive.java Fri Jun 12 09:32:53 2009
@@ -32,34 +32,56 @@
import java.util.jar.Manifest;
import java.util.zip.GZIPOutputStream;
-import org.objectweb.asm.ClassReader;
-
/**
- *
+ * Archive is the main entry point to pack200 and represents a packed archive.
+ * An archive is constructed with either a JarInputStream and an output stream
+ * or a JarFile as input and an OutputStream. Options can be set, then
+ * <code>pack()</code> is called, to pack the Jar file into a pack200 archive.
*/
public class Archive {
private final JarInputStream inputStream;
private final OutputStream outputStream;
private JarFile jarFile;
- private long segmentLimit = 1000000;
private long currentSegmentSize;
- private boolean stripDebug;
- private int effort = 5;
+ private final PackingOptions options;
+ /**
+ * Creates an Archive with streams for the input and output.
+ *
+ * @param inputStream
+ * @param outputStream
+ * @param options - packing options (if null then defaults are used)
+ * @throws IOException
+ */
public Archive(JarInputStream inputStream, OutputStream outputStream,
- boolean gzip) throws IOException {
+ PackingOptions options) throws IOException {
this.inputStream = inputStream;
- if (gzip) {
+ if(options == null) { // use all defaults
+ options = new PackingOptions();
+ }
+ this.options = options;
+ if (options.isGzip()) {
outputStream = new GZIPOutputStream(outputStream);
}
this.outputStream = new BufferedOutputStream(outputStream);
}
+ /**
+ * Creates an Archive with the given input file and a stream for the output
+ *
+ * @param jarFile - the input file
+ * @param outputStream
+ * @param options - packing options (if null then defaults are used)
+ * @throws IOException
+ */
public Archive(JarFile jarFile, OutputStream outputStream,
- boolean gzip) throws IOException {
-
- if (gzip) {
+ PackingOptions options) throws IOException {
+ if(options == null) { // use all defaults
+ options = new PackingOptions();
+ }
+ this.options = options;
+ if (options.isGzip()) {
outputStream = new GZIPOutputStream(outputStream);
}
this.outputStream = new BufferedOutputStream(outputStream);
@@ -67,26 +89,21 @@
inputStream = null;
}
- public void setSegmentLimit(int limit) {
- segmentLimit = limit;
- }
-
- public void setEffort(int effort) {
- this.effort = effort;
- }
-
- public void stripDebugAttributes() {
- stripDebug = true;
- }
-
+ /**
+ * Pack the archive
+ * @throws Pack200Exception
+ * @throws IOException
+ */
public void pack() throws Pack200Exception, IOException {
List classes = new ArrayList();
List files = new ArrayList();
+ int effort = options.getEffort();
+ long segmentLimit = options.getSegmentLimit();
+
if(effort == 0) {
doZeroEffortPack();
} else {
-
if (inputStream != null) {
Manifest manifest = jarFile != null ? jarFile.getManifest()
: inputStream.getManifest();
@@ -109,7 +126,7 @@
if (!added) { // not added because segment has reached
// maximum size
if(classes.size() > 0 || files.size() > 0) {
- new Segment().pack(classes, files, outputStream, stripDebug, effort);
+ new Segment().pack(classes, files, outputStream, options);
classes = new ArrayList();
files = new ArrayList();
currentSegmentSize = 0;
@@ -118,7 +135,7 @@
}
} else if (segmentLimit == 0 && estimateSize(jarEntry) > 0) {
// create a new segment for each class unless size = 0
- new Segment().pack(classes, files, outputStream, stripDebug, effort);
+ new Segment().pack(classes, files, outputStream, options);
classes = new ArrayList();
files = new ArrayList();
}
@@ -132,7 +149,7 @@
jarFile.getInputStream(jarEntry)), classes, files);
if (!added) { // not added because segment has reached maximum
// size
- new Segment().pack(classes, files, outputStream, stripDebug, effort);
+ new Segment().pack(classes, files, outputStream, options);
classes = new ArrayList();
files = new ArrayList();
currentSegmentSize = 0;
@@ -141,14 +158,14 @@
currentSegmentSize = 0; // ignore the size of the first entry for compatibility with the RI
} else if (segmentLimit == 0 && estimateSize(jarEntry) > 0) {
// create a new segment for each class unless size = 0
- new Segment().pack(classes, files, outputStream, stripDebug, effort);
+ new Segment().pack(classes, files, outputStream, options);
classes = new ArrayList();
files = new ArrayList();
}
}
}
if(classes.size() > 0 || files.size() > 0) {
- new Segment().pack(classes, files, outputStream, stripDebug, effort);
+ new Segment().pack(classes, files, outputStream, options);
}
outputStream.close();
}
@@ -207,6 +224,7 @@
private boolean addJarEntry(JarEntry jarEntry, InputStream stream,
List javaClasses, List files) throws IOException, Pack200Exception {
+ long segmentLimit = options.getSegmentLimit();
String name = jarEntry.getName();
long size = jarEntry.getSize();
if (size > Integer.MAX_VALUE) {
@@ -232,7 +250,8 @@
throw new RuntimeException("Error reading from stream");
}
if (name.endsWith(".class")) {
- ClassReader classParser = new Pack200ClassReader(bytes);
+ Pack200ClassReader classParser = new Pack200ClassReader(bytes);
+ classParser.setFileName(name);
javaClasses.add(classParser);
bytes = new byte[0];
}
@@ -257,7 +276,7 @@
static class File {
private final String name;
- private final byte[] contents;
+ private byte[] contents;
private final long modtime;
public File(String name, byte[] contents, long modtime) {
@@ -281,6 +300,10 @@
public String toString() {
return name;
}
+
+ public void setContents(byte[] contents) {
+ this.contents = contents;
+ }
}
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java?rev=784048&r1=784047&r2=784048&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java Fri Jun 12 09:32:53 2009
@@ -24,9 +24,11 @@
import java.util.List;
import java.util.Map;
+import org.objectweb.asm.Attribute;
+
/**
- * Attribute Definition bands define how any unknown attributes should be
- * read by the decompressor.
+ * Attribute Definition bands define how any unknown attributes should be read
+ * by the decompressor.
*/
public class AttributeDefinitionBands extends BandSet {
@@ -35,98 +37,132 @@
public static final int CONTEXT_FIELD = 1;
public static final int CONTEXT_METHOD = 2;
- private final Map layouts = new HashMap();
-
- private final Map classAttributes = new HashMap();
- private final Map methodAttributes = new HashMap();
- private final Map fieldAttributes = new HashMap();
- private final Map codeAttributes = new HashMap();
+ private final List classAttributeLayouts = new ArrayList();
+ private final List methodAttributeLayouts = new ArrayList();
+ private final List fieldAttributeLayouts = new ArrayList();
+ private final List codeAttributeLayouts = new ArrayList();
private final List attributeDefinitions = new ArrayList();
private final CpBands cpBands;
private final Segment segment;
- public AttributeDefinitionBands(Segment segment, int effort) {
+ public AttributeDefinitionBands(Segment segment, int effort,
+ Attribute[] attributePrototypes) {
super(effort, segment.getSegmentHeader());
this.cpBands = segment.getCpBands();
this.segment = segment;
- }
-
- public void finaliseBands() {
- addSyntheticDefinitions();
- segmentHeader.setAttribute_definition_count(classAttributes.keySet()
- .size()
- + methodAttributes.keySet().size()
- + fieldAttributes.keySet().size()
- + codeAttributes.keySet().size()
- + attributeDefinitions.size());
- if (classAttributes.keySet().size() > 7) {
+ Map classLayouts = new HashMap();
+ Map methodLayouts = new HashMap();
+ Map fieldLayouts = new HashMap();
+ Map codeLayouts = new HashMap();
+
+ for (int i = 0; i < attributePrototypes.length; i++) {
+ NewAttribute newAttribute = (NewAttribute) attributePrototypes[i];
+ if (newAttribute.isContextClass()) {
+ classLayouts.put(newAttribute.type, newAttribute.getLayout());
+ }
+ if (newAttribute.isContextMethod()) {
+ methodLayouts.put(newAttribute.type, newAttribute.getLayout());
+ }
+ if (newAttribute.isContextField()) {
+ fieldLayouts.put(newAttribute.type, newAttribute.getLayout());
+ }
+ if (newAttribute.isContextCode()) {
+ codeLayouts.put(newAttribute.type, newAttribute.getLayout());
+ }
+ }
+ if (classLayouts.keySet().size() > 7) {
segmentHeader.setHave_class_flags_hi(true);
}
- if(methodAttributes.keySet().size() > 6) {
+ if (methodLayouts.keySet().size() > 6) {
segmentHeader.setHave_method_flags_hi(true);
}
- if(fieldAttributes.keySet().size() > 10) {
+ if (fieldLayouts.keySet().size() > 10) {
segmentHeader.setHave_field_flags_hi(true);
}
- if(codeAttributes.keySet().size() > 15) {
+ if (codeLayouts.keySet().size() > 15) {
segmentHeader.setHave_code_flags_hi(true);
}
- }
-
- public void pack(OutputStream out) throws IOException, Pack200Exception {
- int[] availableClassIndices = new int[] {25, 26, 27, 28, 29, 30, 31};
- if(classAttributes.size() > 7) {
+ int[] availableClassIndices = new int[] { 25, 26, 27, 28, 29, 30, 31 };
+ if (classLayouts.size() > 7) {
availableClassIndices = addHighIndices(availableClassIndices);
}
- addAttributeDefinitions(classAttributes, availableClassIndices, CONTEXT_CLASS);
- int[] availableMethodIndices = new int[] {26, 27, 28, 29, 30, 31};
- if(methodAttributes.size() > 6) {
+ addAttributeDefinitions(classLayouts, availableClassIndices,
+ CONTEXT_CLASS);
+ int[] availableMethodIndices = new int[] { 26, 27, 28, 29, 30, 31 };
+ if (methodAttributeLayouts.size() > 6) {
availableMethodIndices = addHighIndices(availableMethodIndices);
}
- addAttributeDefinitions(methodAttributes, availableMethodIndices, CONTEXT_METHOD);
- int[] availableFieldIndices = new int[] {18, 23, 24, 25, 26, 27, 28, 29, 30, 31};
- if(fieldAttributes.size() > 10) {
+ addAttributeDefinitions(methodLayouts, availableMethodIndices,
+ CONTEXT_METHOD);
+ int[] availableFieldIndices = new int[] { 18, 23, 24, 25, 26, 27, 28,
+ 29, 30, 31 };
+ if (fieldAttributeLayouts.size() > 10) {
availableFieldIndices = addHighIndices(availableFieldIndices);
}
- addAttributeDefinitions(fieldAttributes, availableFieldIndices, CONTEXT_FIELD);
- int[] availableCodeIndices = new int[] {17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31};
- if(codeAttributes.size() > 15) {
+ addAttributeDefinitions(fieldLayouts, availableFieldIndices,
+ CONTEXT_FIELD);
+ int[] availableCodeIndices = new int[] { 17, 18, 19, 20, 21, 22, 23,
+ 24, 25, 26, 27, 28, 29, 30, 31 };
+ if (codeAttributeLayouts.size() > 15) {
availableCodeIndices = addHighIndices(availableCodeIndices);
}
- addAttributeDefinitions(codeAttributes, availableCodeIndices, CONTEXT_CODE);
+ addAttributeDefinitions(codeLayouts, availableCodeIndices, CONTEXT_CODE);
+ }
+ /**
+ * All input classes for the segment have now been read in, so this method
+ * is called so that this class can calculate/complete anything it could not
+ * do while classes were being read.
+ */
+ public void finaliseBands() {
+ addSyntheticDefinitions();
+ segmentHeader.setAttribute_definition_count(attributeDefinitions.size());
+ }
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception {
int[] attributeDefinitionHeader = new int[attributeDefinitions.size()];
int[] attributeDefinitionName = new int[attributeDefinitions.size()];
int[] attributeDefinitionLayout = new int[attributeDefinitions.size()];
for (int i = 0; i < attributeDefinitionLayout.length; i++) {
- AttributeDefinition def = (AttributeDefinition) attributeDefinitions.get(i);
- attributeDefinitionHeader[i] = def.contextType | (def.index + 1 << 2);
+ AttributeDefinition def = (AttributeDefinition) attributeDefinitions
+ .get(i);
+ attributeDefinitionHeader[i] = def.contextType
+ | (def.index + 1 << 2);
attributeDefinitionName[i] = def.name.getIndex();
attributeDefinitionLayout[i] = def.layout.getIndex();
}
- out.write(encodeBandInt("attributeDefinitionHeader", attributeDefinitionHeader, Codec.BYTE1));
- out.write(encodeBandInt("attributeDefinitionName", attributeDefinitionName, Codec.UNSIGNED5));
- out.write(encodeBandInt("attributeDefinitionLayout", attributeDefinitionLayout, Codec.UNSIGNED5));
+ out.write(encodeBandInt("attributeDefinitionHeader",
+ attributeDefinitionHeader, Codec.BYTE1));
+ out.write(encodeBandInt("attributeDefinitionName",
+ attributeDefinitionName, Codec.UNSIGNED5));
+ out.write(encodeBandInt("attributeDefinitionLayout",
+ attributeDefinitionLayout, Codec.UNSIGNED5));
}
private void addSyntheticDefinitions() {
- boolean anySytheticClasses = segment.getClassBands().isAnySyntheticClasses();
- boolean anySyntheticMethods = segment.getClassBands().isAnySyntheticMethods();
- boolean anySyntheticFields = segment.getClassBands().isAnySyntheticFields();
- if(anySytheticClasses || anySyntheticMethods || anySyntheticFields) {
+ boolean anySytheticClasses = segment.getClassBands()
+ .isAnySyntheticClasses();
+ boolean anySyntheticMethods = segment.getClassBands()
+ .isAnySyntheticMethods();
+ boolean anySyntheticFields = segment.getClassBands()
+ .isAnySyntheticFields();
+ if (anySytheticClasses || anySyntheticMethods || anySyntheticFields) {
CPUTF8 syntheticUTF = cpBands.getCPUtf8("Synthetic");
CPUTF8 emptyUTF = cpBands.getCPUtf8("");
- if(anySytheticClasses) {
- attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_CLASS, syntheticUTF, emptyUTF));
+ if (anySytheticClasses) {
+ attributeDefinitions.add(new AttributeDefinition(12,
+ CONTEXT_CLASS, syntheticUTF, emptyUTF));
}
- if(anySyntheticMethods) {
- attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_METHOD, syntheticUTF, emptyUTF));
+ if (anySyntheticMethods) {
+ attributeDefinitions.add(new AttributeDefinition(12,
+ CONTEXT_METHOD, syntheticUTF, emptyUTF));
}
- if(anySyntheticFields) {
- attributeDefinitions.add(new AttributeDefinition(12, CONTEXT_FIELD, syntheticUTF, emptyUTF));
+ if (anySyntheticFields) {
+ attributeDefinitions.add(new AttributeDefinition(12,
+ CONTEXT_FIELD, syntheticUTF, emptyUTF));
}
}
}
@@ -137,29 +173,58 @@
temp[i] = availableIndices[i];
}
int j = 32;
- for (int i = availableIndices.length; i < temp.length ; i++) {
+ for (int i = availableIndices.length; i < temp.length; i++) {
temp[i] = j;
j++;
}
return temp;
}
- private void addAttributeDefinitions(Map attributes,
- int[] availableIndices, int contextType) {
+ private void addAttributeDefinitions(Map layouts, int[] availableIndices,
+ int contextType) {
int i = 0;
- for (Iterator iterator = attributes.keySet().iterator(); iterator.hasNext();) {
+ for (Iterator iterator = layouts.keySet().iterator(); iterator
+ .hasNext();) {
String name = (String) iterator.next();
String layout = (String) layouts.get(name);
int index = availableIndices[i];
- attributeDefinitions.add(new AttributeDefinition(index, contextType, cpBands.getCPUtf8(name), cpBands.getCPUtf8(layout)));
+ AttributeDefinition definition = new AttributeDefinition(index,
+ contextType, cpBands.getCPUtf8(name), cpBands
+ .getCPUtf8(layout));
+ attributeDefinitions.add(definition);
+ switch (contextType) {
+ case CONTEXT_CLASS:
+ classAttributeLayouts.add(definition);
+ break;
+ case CONTEXT_METHOD:
+ methodAttributeLayouts.add(definition);
+ break;
+ case CONTEXT_FIELD:
+ fieldAttributeLayouts.add(definition);
+ break;
+ case CONTEXT_CODE:
+ codeAttributeLayouts.add(definition);
+ }
}
}
- public void addLayout(String name, String layout) {
- layouts.put(name, layout);
+ public List getClassAttributeLayouts() {
+ return classAttributeLayouts;
+ }
+
+ public List getMethodAttributeLayouts() {
+ return methodAttributeLayouts;
+ }
+
+ public List getFieldAttributeLayouts() {
+ return fieldAttributeLayouts;
+ }
+
+ public List getCodeAttributeLayouts() {
+ return codeAttributeLayouts;
}
- private static class AttributeDefinition {
+ public static class AttributeDefinition {
public int index;
public int contextType;
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=784048&r1=784047&r2=784048&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 Jun 12 09:32:53 2009
@@ -19,6 +19,8 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
@@ -26,11 +28,15 @@
import java.util.Map;
import java.util.Set;
+import org.apache.harmony.pack200.AttributeDefinitionBands.AttributeDefinition;
import org.apache.harmony.pack200.IcBands.IcTuple;
-import org.objectweb.asm.Attribute;
import org.objectweb.asm.Label;
import org.objectweb.asm.Opcodes;
+/**
+ * Class bands (corresponds to the <code>class_bands</code> set of bands in the
+ * pack200 specification)
+ */
public class ClassBands extends BandSet {
private final CpBands cpBands;
@@ -77,6 +83,7 @@
private final List codeHandlerCatchPO = new ArrayList();
private final List codeHandlerClass = new ArrayList();
private final List codeFlags = new ArrayList();
+ private int[] code_attr_calls;
private final IntList codeLineNumberTableN = new IntList();
private final List codeLineNumberTableBciP = new ArrayList();
private final IntList codeLineNumberTableLine = new IntList();
@@ -103,6 +110,11 @@
private final MetadataBandGroup method_RIPA_bands;
private final MetadataBandGroup method_AD_bands;
+ private final List classAttributeBands = new ArrayList();
+ private final List methodAttributeBands = new ArrayList();
+ private final List fieldAttributeBands = new ArrayList();
+ private final List codeAttributeBands = new ArrayList();
+
private final List tempFieldFlags = new ArrayList();
private final List tempFieldDesc = new ArrayList();
private final List tempMethodFlags = new ArrayList();
@@ -114,9 +126,20 @@
private final Segment segment;
private final Map classReferencesInnerClass = new HashMap();
+ private final boolean stripDebug;
+
+ private int index = 0;
+
+ private int numMethodArgs = 0;
+ private int[] class_InnerClasses_N;
+ private CPClass[] class_InnerClasses_RC;
+ private int[] class_InnerClasses_F;
+ private List classInnerClassesOuterRCN;
+ private List classInnerClassesNameRUN;
- public ClassBands(Segment segment, int numClasses, int effort) {
+ public ClassBands(Segment segment, int numClasses, int effort, boolean stripDebug) throws IOException {
super(effort, segment.getSegmentHeader());
+ this.stripDebug = stripDebug;
this.segment = segment;
this.cpBands = segment.getCpBands();
this.attrBands = segment.getAttrBands();
@@ -143,16 +166,32 @@
method_RVPA_bands = new MetadataBandGroup("RVPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
method_RIPA_bands = new MetadataBandGroup("RIPA", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
method_AD_bands = new MetadataBandGroup("AD", MetadataBandGroup.CONTEXT_METHOD, cpBands, segmentHeader, effort);
- }
- private int index = 0;
+ createNewAttributeBands();
+ }
- private int numMethodArgs = 0;
- private int[] class_InnerClasses_N;
- private CPClass[] class_InnerClasses_RC;
- private int[] class_InnerClasses_F;
- private List classInnerClassesOuterRCN;
- private List classInnerClassesNameRUN;
+ private void createNewAttributeBands() throws IOException {
+ List classAttributeLayouts = attrBands.getClassAttributeLayouts();
+ for (Iterator iterator = classAttributeLayouts.iterator(); iterator.hasNext();) {
+ AttributeDefinition def = (AttributeDefinition) iterator.next();
+ classAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
+ }
+ List methodAttributeLayouts = attrBands.getMethodAttributeLayouts();
+ for (Iterator iterator = methodAttributeLayouts.iterator(); iterator.hasNext();) {
+ AttributeDefinition def = (AttributeDefinition) iterator.next();
+ methodAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
+ }
+ List fieldAttributeLayouts = attrBands.getFieldAttributeLayouts();
+ for (Iterator iterator = fieldAttributeLayouts.iterator(); iterator.hasNext();) {
+ AttributeDefinition def = (AttributeDefinition) iterator.next();
+ fieldAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
+ }
+ List codeAttributeLayouts = attrBands.getCodeAttributeLayouts();
+ for (Iterator iterator = codeAttributeLayouts.iterator(); iterator.hasNext();) {
+ AttributeDefinition def = (AttributeDefinition) iterator.next();
+ codeAttributeBands.add(new NewAttributeBands(effort, cpBands, segment.getSegmentHeader(), def));
+ }
+ }
public void addClass(int major, int flags, String className,
String signature, String superName, String[] interfaces) {
@@ -232,6 +271,11 @@
tempFieldFlags.add(new Long(flags));
}
+ /**
+ * All input classes for the segment have now been read in, so this method
+ * is called so that this class can calculate/complete anything it could not
+ * do while classes were being read.
+ */
public void finaliseBands() {
int defaultMajorVersion = segmentHeader.getDefaultMajorVersion();
for (int i = 0; i < class_flags.length; i++) {
@@ -332,6 +376,8 @@
IntList classAttrCalls = new IntList();
IntList fieldAttrCalls = new IntList();
IntList methodAttrCalls = new IntList();
+ IntList codeAttrCalls = new IntList();
+
if(class_RVA_bands.hasContent()) {
classAttrCalls.add(class_RVA_bands.numBackwardsCalls());
}
@@ -359,9 +405,61 @@
if(method_AD_bands.hasContent()) {
methodAttrCalls.add(method_AD_bands.numBackwardsCalls());
}
+
+ // Sort non-predefined attribute bands
+ Comparator comparator = new Comparator() {
+ public int compare(Object arg0, Object arg1) {
+ NewAttributeBands bands0 = (NewAttributeBands)arg0;
+ NewAttributeBands bands1 = (NewAttributeBands)arg1;
+ return bands0.getFlagIndex() - bands1.getFlagIndex();
+ }
+ };
+ Collections.sort(classAttributeBands, comparator);
+ Collections.sort(methodAttributeBands, comparator);
+ Collections.sort(fieldAttributeBands, comparator);
+ Collections.sort(codeAttributeBands, comparator);
+
+ for (Iterator iterator = classAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ if(bands.isUsedAtLeastOnce()) {
+ int[] backwardsCallCounts = bands.numBackwardsCalls();
+ for (int i = 0; i < backwardsCallCounts.length; i++) {
+ classAttrCalls.add(backwardsCallCounts[i]);
+ }
+ }
+ }
+ for (Iterator iterator = methodAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ if(bands.isUsedAtLeastOnce()) {
+ int[] backwardsCallCounts = bands.numBackwardsCalls();
+ for (int i = 0; i < backwardsCallCounts.length; i++) {
+ methodAttrCalls.add(backwardsCallCounts[i]);
+ }
+ }
+ }
+ for (Iterator iterator = fieldAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ if(bands.isUsedAtLeastOnce()) {
+ int[] backwardsCallCounts = bands.numBackwardsCalls();
+ for (int i = 0; i < backwardsCallCounts.length; i++) {
+ fieldAttrCalls.add(backwardsCallCounts[i]);
+ }
+ }
+ }
+ for (Iterator iterator = codeAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ if(bands.isUsedAtLeastOnce()) {
+ int[] backwardsCallCounts = bands.numBackwardsCalls();
+ for (int i = 0; i < backwardsCallCounts.length; i++) {
+ codeAttrCalls.add(backwardsCallCounts[i]);
+ }
+ }
+ }
+
class_attr_calls = classAttrCalls.toArray();
field_attr_calls = fieldAttrCalls.toArray();
method_attr_calls = methodAttrCalls.toArray();
+ code_attr_calls = codeAttrCalls.toArray();
}
public void pack(OutputStream out) throws IOException, Pack200Exception {
@@ -440,6 +538,10 @@
cpEntryListToArray(fieldSignature), Codec.UNSIGNED5));
field_RVA_bands.pack(out);
field_RIA_bands.pack(out);
+ for (Iterator iterator = fieldAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ bands.pack(out);
+ }
}
private void writeMethodAttributeBands(OutputStream out)
@@ -460,14 +562,25 @@
method_RVPA_bands.pack(out);
method_RIPA_bands.pack(out);
method_AD_bands.pack(out);
+ for (Iterator iterator = methodAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ bands.pack(out);
+ }
}
private void writeClassAttributeBands(OutputStream out) throws IOException,
Pack200Exception {
out.write(encodeFlags("class_flags", class_flags, Codec.UNSIGNED5,
Codec.UNSIGNED5, segmentHeader.have_class_flags_hi()));
+
+ // These bands are not needed, but could be used to reduce the size of
+ // the archive if there are enough different non-standard attributes
+ // defined that segmentHeader.have_class_flags_hi() is true. The same
+ // applies to method_attr_count, field_attr_count, code_attr_count etc.
+
// *class_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
// *class_attr_indexes :UNSIGNED5 [SUM(*class_attr_count)]
+
out.write(encodeBandInt("class_attr_calls", class_attr_calls, Codec.UNSIGNED5));
out.write(encodeBandInt("classSourceFile",
cpEntryOrNullListToArray(classSourceFile), Codec.UNSIGNED5));
@@ -490,6 +603,10 @@
classFileVersionMinor.toArray(), Codec.UNSIGNED5));
out.write(encodeBandInt("classFileVersionMajor",
classFileVersionMajor.toArray(), Codec.UNSIGNED5));
+ for (Iterator iterator = classAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ bands.pack(out);
+ }
}
private int[] getInts(CPClass[] cpClasses) {
@@ -527,7 +644,8 @@
// *code_attr_count :UNSIGNED5 [COUNT(1<<16,...)]
// *code_attr_indexes :UNSIGNED5 [SUM(*code_attr_count)]
- // *code_attr_calls :UNSIGNED5 [...]
+ out.write(encodeBandInt("code_attr_calls", code_attr_calls,
+ Codec.UNSIGNED5));
out.write(encodeBandInt("code_LineNumberTable_N",
codeLineNumberTableN.toArray(), Codec.UNSIGNED5));
out.write(encodeBandInt("code_LineNumberTable_bci_P",
@@ -562,7 +680,10 @@
Codec.UNSIGNED5));
out.write(encodeBandInt("code_LocalVariableTypeTable_slot",
codeLocalVariableTypeTableSlot.toArray(), Codec.UNSIGNED5));
-
+ for (Iterator iterator = codeAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ bands.pack(out);
+ }
}
public void addMethod(int flags, String name, String desc,
@@ -690,14 +811,64 @@
.getCPNameAndType(name, desc));
}
- public void addUnknownFieldAttribute(Attribute arg0) {
- // TODO Auto-generated method stub
-
- }
-
- public void addUnknownMethodAttribute(Attribute arg0) {
- // TODO Auto-generated method stub
-
+ public void addClassAttribute(NewAttribute attribute) {
+ // TODO: backwards calls
+ String attributeName = attribute.type;
+ for (Iterator iterator = classAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ if(bands.getAttributeName().equals(attributeName)) {
+ bands.addAttribute(attribute);
+ int flagIndex = bands.getFlagIndex();
+ class_flags[index] |= (1 << flagIndex);
+ return;
+ }
+ }
+ throw new RuntimeException("No suitable definition for " + attributeName);
+ }
+
+ public void addFieldAttribute(NewAttribute attribute) {
+ String attributeName = attribute.type;
+ for (Iterator iterator = fieldAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ if(bands.getAttributeName().equals(attributeName)) {
+ bands.addAttribute(attribute);
+ int flagIndex = bands.getFlagIndex();
+ Long flags = (Long)tempFieldFlags.remove(tempFieldFlags.size() - 1);
+ tempFieldFlags.add(new Long(flags.longValue() | (1 << flagIndex)));
+ return;
+ }
+ }
+ throw new RuntimeException("No suitable definition for " + attributeName);
+ }
+
+ public void addMethodAttribute(NewAttribute attribute) {
+ String attributeName = attribute.type;
+ for (Iterator iterator = methodAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ if(bands.getAttributeName().equals(attributeName)) {
+ bands.addAttribute(attribute);
+ int flagIndex = bands.getFlagIndex();
+ Long flags = (Long)tempMethodFlags.remove(tempMethodFlags.size() - 1);
+ tempMethodFlags.add(new Long(flags.longValue() | (1 << flagIndex)));
+ return;
+ }
+ }
+ throw new RuntimeException("No suitable definition for " + attributeName);
+ }
+
+ public void addCodeAttribute(NewAttribute attribute) {
+ String attributeName = attribute.type;
+ for (Iterator iterator = codeAttributeBands.iterator(); iterator.hasNext();) {
+ NewAttributeBands bands = (NewAttributeBands) iterator.next();
+ if(bands.getAttributeName().equals(attributeName)) {
+ bands.addAttribute(attribute);
+ int flagIndex = bands.getFlagIndex();
+ Long flags = (Long)codeFlags.remove(codeFlags.size() - 1);
+ codeFlags.add(new Long(flags.longValue() | (1 << flagIndex)));
+ return;
+ }
+ }
+ throw new RuntimeException("No suitable definition for " + attributeName);
}
public void addMaxStack(int maxStack, int maxLocals) {
@@ -713,10 +884,10 @@
codeMaxLocals.add(maxLocals);
}
- public void addCode(boolean stripDebug) {
+ public void addCode() {
codeHandlerCount.add(0);
if(!stripDebug) {
- codeFlags.add(new Long((1 << 2))); // TODO: What if there's no debug information?
+ codeFlags.add(new Long((1 << 2)));
codeLocalVariableTableN.add(0);
}
}
@@ -743,7 +914,6 @@
}
codeLineNumberTableLine.add(line);
codeLineNumberTableBciP.add(start);
- // TODO: bci renumbering
}
public void addLocalVariable(String name, String desc, String signature,
@@ -946,4 +1116,136 @@
Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
tempMethodFlags.add(new Long(flag.longValue() | (1<<25)));
}
+
+ /**
+ * Remove all entries for the current class
+ */
+ public void removeCurrentClass() {
+ // Note - this doesn't remove any entries added to the constant pool but
+ // that shouldn't be a problem
+ if ((class_flags[index] & (1 << 17)) != 0) {
+ classSourceFile.remove(classSourceFile.size() - 1);
+ }
+ if ((class_flags[index] & (1 << 18)) != 0) {
+ classEnclosingMethodClass
+ .remove(classEnclosingMethodClass.size() - 1);
+ classEnclosingMethodDesc
+ .remove(classEnclosingMethodDesc.size() - 1);
+ }
+ if ((class_flags[index] & (1 << 19)) != 0) {
+ classSignature.remove(classSignature.size() - 1);
+ }
+ if ((class_flags[index] & (1 << 21)) != 0) {
+ class_RVA_bands.removeLatest();
+ }
+ if ((class_flags[index] & (1 << 22)) != 0) {
+ class_RIA_bands.removeLatest();
+ }
+ for (Iterator iterator = tempFieldFlags.iterator(); iterator.hasNext();) {
+ Long flagsL = (Long) iterator.next();
+ long flags = flagsL.longValue();
+ if ((flags & (1 << 19)) != 0) {
+ fieldSignature.remove(fieldSignature.size() - 1);
+ }
+ if ((flags & (1 << 17)) != 0) {
+ fieldConstantValueKQ.remove(fieldConstantValueKQ.size() - 1);
+ }
+ if ((flags & (1 << 21)) != 0) {
+ field_RVA_bands.removeLatest();
+ }
+ if ((flags & (1 << 22)) != 0) {
+ field_RIA_bands.removeLatest();
+ }
+ }
+ for (Iterator iterator = tempMethodFlags.iterator(); iterator.hasNext();) {
+ Long flagsL = (Long) iterator.next();
+ long flags = flagsL.longValue();
+ if ((flags & (1 << 19)) != 0) {
+ methodSignature.remove(methodSignature.size() - 1);
+ }
+ if ((flags & (1 << 18)) != 0) {
+ int exceptions = methodExceptionNumber
+ .remove(methodExceptionNumber.size() - 1);
+ for (int i = 0; i < exceptions; i++) {
+ methodExceptionClasses
+ .remove(methodExceptionClasses.size() - 1);
+ }
+ }
+ if ((flags & (1 << 17)) != 0) { // has code attribute
+ codeMaxLocals.remove(codeMaxLocals.size() - 1);
+ codeMaxStack.remove(codeMaxStack.size() - 1);
+ int handlers = codeHandlerCount
+ .remove(codeHandlerCount.size() - 1);
+ for (int i = 0; i < handlers; i++) {
+ int index = codeHandlerStartP.size() - 1;
+ codeHandlerStartP.remove(index);
+ codeHandlerEndPO.remove(index);
+ codeHandlerCatchPO.remove(index);
+ codeHandlerClass.remove(index);
+ }
+ if (!stripDebug) {
+ long cdeFlags = ((Long) codeFlags
+ .remove(codeFlags.size() - 1)).longValue();
+ int numLocalVariables = codeLocalVariableTableN
+ .remove(codeLocalVariableTableN.size() - 1);
+ for (int i = 0; i < numLocalVariables; i++) {
+ int location = codeLocalVariableTableBciP.size() - 1;
+ codeLocalVariableTableBciP.remove(location);
+ codeLocalVariableTableSpanO.remove(location);
+ codeLocalVariableTableNameRU.remove(location);
+ codeLocalVariableTableTypeRS.remove(location);
+ codeLocalVariableTableSlot.remove(location);
+ }
+ if ((cdeFlags & (1 << 3)) != 0) {
+ int numLocalVariablesInTypeTable = codeLocalVariableTypeTableN
+ .remove(codeLocalVariableTypeTableN.size() - 1);
+ for (int i = 0; i < numLocalVariablesInTypeTable; i++) {
+ int location = codeLocalVariableTypeTableBciP
+ .size() - 1;
+ codeLocalVariableTypeTableBciP.remove(location);
+ codeLocalVariableTypeTableSpanO.remove(location);
+ codeLocalVariableTypeTableNameRU.remove(location);
+ codeLocalVariableTypeTableTypeRS.remove(location);
+ codeLocalVariableTypeTableSlot.remove(location);
+ }
+ }
+ if ((cdeFlags & (1 << 1)) != 0) {
+ int numLineNumbers = codeLineNumberTableN
+ .remove(codeLineNumberTableN.size() - 1);
+ for (int i = 0; i < numLineNumbers; i++) {
+ int location = codeLineNumberTableBciP.size() - 1;
+ codeLineNumberTableBciP.remove(location);
+ codeLineNumberTableLine.remove(location);
+ }
+ }
+ }
+ }
+ if ((flags & (1 << 21)) != 0) {
+ method_RVA_bands.removeLatest();
+ }
+ if ((flags & (1 << 22)) != 0) {
+ method_RIA_bands.removeLatest();
+ }
+ if ((flags & (1 << 23)) != 0) {
+ method_RVPA_bands.removeLatest();
+ }
+ if ((flags & (1 << 24)) != 0) {
+ method_RIPA_bands.removeLatest();
+ }
+ if ((flags & (1 << 25)) != 0) {
+ method_AD_bands.removeLatest();
+ }
+ }
+ class_this[index] = null;
+ class_super[index] = null;
+ class_interface_count[index] = 0;
+ class_interface[index] = null;
+ major_versions[index] = 0;
+ class_flags[index] = 0;
+ tempFieldDesc.clear();
+ tempFieldFlags.clear();
+ tempMethodDesc.clear();
+ tempMethodFlags.clear();
+ index--;
+ }
}
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java?rev=784048&r1=784047&r2=784048&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java Fri Jun 12 09:32:53 2009
@@ -36,9 +36,9 @@
private int numBackwardsCalls = 0;
public List param_NB = new ArrayList(); // TODO: Lazy instantiation?
- public List anno_N = new ArrayList();
+ public IntList anno_N = new IntList();
public List type_RS = new ArrayList();
- public List pair_N = new ArrayList();
+ public IntList pair_N = new IntList();
public List name_RU = new ArrayList();
public List T = new ArrayList();
public List caseI_KI = new ArrayList();
@@ -49,9 +49,9 @@
public List caseet_RS = new ArrayList();
public List caseec_RU = new ArrayList();
public List cases_RU = new ArrayList();
- public List casearray_N = new ArrayList();
+ public IntList casearray_N = new IntList();
public List nesttype_RS = new ArrayList();
- public List nestpair_N = new ArrayList();
+ public IntList nestpair_N = new IntList();
public List nestname_RU = new ArrayList();
private final CpBands cpBands;
@@ -59,7 +59,18 @@
/**
* Constructs a new MetadataBandGroup
- * @param type - must be either AD, RVA, RIA, RVPA or RIPA.
+ *
+ * @param type
+ * must be either AD, RVA, RIA, RVPA or RIPA.
+ * @param context
+ * <code>CONTEXT_CLASS</code>, <code>CONTEXT_METHOD</code> or
+ * <code>CONTEXT_FIELD</code>
+ * @param cpBands
+ * constant pool bands
+ * @param segmentHeader
+ * segment header
+ * @param effort
+ * packing effort
*/
public MetadataBandGroup(String type, int context, CpBands cpBands, SegmentHeader segmentHeader, int effort) {
super(effort, segmentHeader);
@@ -82,9 +93,9 @@
contextStr = "Method";
}
if(!type.equals("AD")) {
- out.write(encodeBandInt(contextStr + "_" + type + " anno_N", listToArray(anno_N), Codec.UNSIGNED5));
+ out.write(encodeBandInt(contextStr + "_" + type + " anno_N", anno_N.toArray(), Codec.UNSIGNED5));
out.write(encodeBandInt(contextStr + "_" + type + " type_RS", cpEntryListToArray(type_RS), Codec.UNSIGNED5));
- out.write(encodeBandInt(contextStr + "_" + type + " pair_N", listToArray(pair_N), Codec.UNSIGNED5));
+ out.write(encodeBandInt(contextStr + "_" + type + " pair_N", pair_N.toArray(), Codec.UNSIGNED5));
out.write(encodeBandInt(contextStr + "_" + type + " name_RU", cpEntryListToArray(name_RU), Codec.UNSIGNED5));
}
out.write(encodeBandInt(contextStr + "_" + type + " T", tagListToArray(T), Codec.BYTE1));
@@ -96,9 +107,9 @@
out.write(encodeBandInt(contextStr + "_" + type + " caseet_RS", cpEntryListToArray(caseet_RS), Codec.UNSIGNED5));
out.write(encodeBandInt(contextStr + "_" + type + " caseec_RU", cpEntryListToArray(caseec_RU), Codec.UNSIGNED5));
out.write(encodeBandInt(contextStr + "_" + type + " cases_RU", cpEntryListToArray(cases_RU), Codec.UNSIGNED5));
- out.write(encodeBandInt(contextStr + "_" + type + " casearray_N", listToArray(casearray_N), Codec.UNSIGNED5));
+ out.write(encodeBandInt(contextStr + "_" + type + " casearray_N", casearray_N.toArray(), Codec.UNSIGNED5));
out.write(encodeBandInt(contextStr + "_" + type + " nesttype_RS", cpEntryListToArray(nesttype_RS), Codec.UNSIGNED5));
- out.write(encodeBandInt(contextStr + "_" + type + " nestpair_N", listToArray(nestpair_N), Codec.UNSIGNED5));
+ out.write(encodeBandInt(contextStr + "_" + type + " nestpair_N", nestpair_N.toArray(), Codec.UNSIGNED5));
out.write(encodeBandInt(contextStr + "_" + type + " nestname_RU", cpEntryListToArray(nestname_RU), Codec.UNSIGNED5));
}
}
@@ -111,9 +122,21 @@
return ints;
}
+ /**
+ * Add an annotation to this set of bands
+ *
+ * @param desc
+ * @param nameRU
+ * @param t
+ * @param values
+ * @param caseArrayN
+ * @param nestTypeRS
+ * @param nestNameRU
+ * @param nestPairN
+ */
public void addAnnotation(String desc, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) {
type_RS.add(cpBands.getCPSignature(desc));
- pair_N.add(new Integer(t.size()));
+ pair_N.add(t.size());
for (Iterator iterator = nameRU.iterator(); iterator.hasNext();) {
String name = (String) iterator.next();
@@ -152,9 +175,9 @@
// do nothing here for [ or @ (handled below)
}
for (Iterator iterator = caseArrayN.iterator(); iterator.hasNext();) {
- Integer arraySize = (Integer) iterator.next();
+ int arraySize = ((Integer)iterator.next()).intValue();
casearray_N.add(arraySize);
- numBackwardsCalls += arraySize.intValue();
+ numBackwardsCalls += arraySize;
}
for (Iterator iterator = nesttype_RS.iterator(); iterator.hasNext();) {
String type = (String) iterator.next();
@@ -171,6 +194,9 @@
}
}
+ /**
+ * Returns true if any annotations have been added to this set of bands
+ */
public boolean hasContent() {
return type_RS.size() > 0;
}
@@ -180,12 +206,62 @@
}
public void incrementAnnoN() {
- Integer latest = (Integer)anno_N.remove(anno_N.size() -1);
- anno_N.add(new Integer(latest.intValue() + 1));
+ anno_N.increment(anno_N.size() - 1);
}
public void newEntryInAnnoN() {
- anno_N.add(new Integer(1));
+ anno_N.add(1);
+ }
+
+ /**
+ * Remove the latest annotation that was added to this group
+ */
+ public void removeLatest() {
+ int latest = anno_N.remove(anno_N.size() -1);
+ for (int i = 0; i < latest; i++) {
+ type_RS.remove(type_RS.size() - 1);
+ int pairs = pair_N.remove(pair_N.size() - 1);
+ for (int j = 0; j < pairs; j++) {
+ removeOnePair();
+ }
+ }
+ }
+
+ /*
+ * Convenience method for removeLatest
+ */
+ private void removeOnePair() {
+ String tag = (String) T.remove(T.size() - 1);
+ if (tag.equals("B") || tag.equals("C") || tag.equals("I")
+ || tag.equals("S") || tag.equals("Z")) {
+ caseI_KI.remove(caseI_KI.size() - 1);
+ } else if (tag.equals("D")) {
+ caseD_KD.remove(caseD_KD.size() - 1);
+ } else if (tag.equals("F")) {
+ caseF_KF.remove(caseF_KF.size() - 1);
+ } else if (tag.equals("J")) {
+ caseJ_KJ.remove(caseJ_KJ.size() - 1);
+ } else if (tag.equals("C")) {
+ casec_RS.remove(casec_RS.size() - 1);
+ } else if (tag.equals("e")) {
+ caseet_RS.remove(caseet_RS.size() - 1);
+ caseec_RU.remove(caseet_RS.size() - 1);
+ } else if (tag.equals("s")) {
+ cases_RU.remove(cases_RU.size() - 1);
+ } else if (tag.equals("[")) {
+ int arraySize = casearray_N.remove(casearray_N.size() - 1);
+ numBackwardsCalls -= arraySize;
+ for (int k = 0; k < arraySize; k++) {
+ removeOnePair();
+ }
+ } else if (tag.equals("@")) {
+ nesttype_RS.remove(nesttype_RS.size() - 1);
+ int numPairs = nestpair_N.remove(nestpair_N.size() - 1);
+ numBackwardsCalls -= numPairs;
+ for (int i = 0; i < numPairs; i++) {
+ removeOnePair();
+ }
+ }
}
}
Added: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java?rev=784048&view=auto
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java (added)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java Fri Jun 12 09:32:53 2009
@@ -0,0 +1,140 @@
+/*
+ * 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 org.objectweb.asm.Attribute;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Label;
+
+/**
+ * NewAttribute extends <code>Attribute</code> and manages unknown attributes
+ * encountered by ASM that have had a layout definition given to pack200 (e.g.
+ * via one of the -C, -M, -F or -D command line options)
+ */
+public class NewAttribute extends Attribute {
+
+ private boolean contextClass = false;
+ private boolean contextMethod = false;
+ private boolean contextField = false;
+ private boolean contextCode = false;
+
+ private final String layout;
+ private byte[] contents;
+ private int codeOff;
+ private Label[] labels;
+ private ClassReader classReader;
+ private char[] buf;
+
+ public NewAttribute(String type, String layout, int context) {
+ super(type);
+ this.layout = layout;
+ addContext(context);
+ }
+
+ public NewAttribute(ClassReader classReader, String type, String layout, byte[] contents, char[] buf,
+ int codeOff, Label[] labels) {
+ super(type);
+ this.classReader = classReader;
+ this.contents = contents;
+ this.layout = layout;
+ this.codeOff = codeOff;
+ this.labels = labels;
+ this.buf = buf;
+ }
+
+ public void addContext(int context) {
+ switch(context) {
+ case AttributeDefinitionBands.CONTEXT_CLASS:
+ contextClass = true;
+ break;
+ case AttributeDefinitionBands.CONTEXT_METHOD:
+ contextMethod = true;
+ break;
+ case AttributeDefinitionBands.CONTEXT_FIELD:
+ contextField = true;
+ break;
+ case AttributeDefinitionBands.CONTEXT_CODE:
+ contextCode = true;
+ }
+ }
+
+ public boolean isContextClass() {
+ return contextClass;
+ }
+
+ public boolean isContextMethod() {
+ return contextMethod;
+ }
+
+ public boolean isContextField() {
+ return contextField;
+ }
+
+ public boolean isContextCode() {
+ return contextCode;
+ }
+
+ public String getLayout() {
+ return layout;
+ }
+
+ public boolean isUnknown() {
+ return false;
+ }
+
+ public boolean isCodeAttribute() {
+ return codeOff != -1;
+ }
+
+ protected Attribute read(ClassReader cr, int off, int len, char[] buf,
+ int codeOff, Label[] labels) {
+ byte[] attributeContents = new byte[len];
+ System.arraycopy(cr.b, off, attributeContents, 0, len);
+ return new NewAttribute(cr, type, layout, attributeContents, buf, codeOff,
+ labels);
+ }
+
+ public boolean isUnknown(int context) {
+ switch(context) {
+ case AttributeDefinitionBands.CONTEXT_CLASS:
+ return contextClass;
+ case AttributeDefinitionBands.CONTEXT_METHOD:
+ return contextMethod;
+ case AttributeDefinitionBands.CONTEXT_FIELD:
+ return contextField;
+ case AttributeDefinitionBands.CONTEXT_CODE:
+ return contextCode;
+ }
+ return false;
+ }
+
+ public String readUTF8(int index) {
+ return classReader.readUTF8(index, buf);
+ }
+
+ public String readClass(int index) {
+ return classReader.readClass(index, buf);
+ }
+
+ public Object readConst(int index) {
+ return classReader.readConst(index, buf);
+ }
+
+ public byte[] getBytes() {
+ return contents;
+ }
+}
Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttribute.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
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=784048&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 Jun 12 09:32:53 2009
@@ -0,0 +1,780 @@
+/*
+ * 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.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.harmony.pack200.AttributeDefinitionBands.AttributeDefinition;
+
+/**
+ * Set of bands relating to a non-predefined attribute that has had a layout
+ * definition given to pack200 (e.g. via one of the -C, -M, -F or -D command
+ * line options)
+ */
+public class NewAttributeBands extends BandSet {
+
+ private List attributeLayoutElements;
+ private int[] backwardsCallCounts;
+ private final CpBands cpBands;
+ private final AttributeDefinition def;
+ private boolean usedAtLeastOnce;
+
+ public NewAttributeBands(int effort, CpBands cpBands, SegmentHeader header, AttributeDefinition def) throws IOException {
+ super(effort, header);
+ this.def = def;
+ this.cpBands = cpBands;
+ parseLayout();
+ }
+
+ public void addAttribute(NewAttribute attribute) {
+ usedAtLeastOnce = true;
+ InputStream stream = new ByteArrayInputStream(attribute.getBytes());
+ for (Iterator iterator = attributeLayoutElements.iterator(); iterator.hasNext();) {
+ AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator.next();
+ layoutElement.addAttributeToBand(attribute, stream);
+ }
+ }
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception {
+ for (Iterator iterator = attributeLayoutElements.iterator(); iterator.hasNext();) {
+ AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator.next();
+ layoutElement.pack(out);
+ }
+ }
+
+ public String getAttributeName() {
+ return def.name.getUnderlyingString();
+ }
+
+ public int getFlagIndex() {
+ return def.index;
+ }
+
+ public int[] numBackwardsCalls() {
+ return backwardsCallCounts;
+ }
+
+ public boolean isUsedAtLeastOnce() {
+ return usedAtLeastOnce;
+ }
+
+ private void parseLayout() throws IOException {
+ String layout = def.layout.getUnderlyingString();
+ if (attributeLayoutElements == null) {
+ attributeLayoutElements = new ArrayList();
+ StringReader stream = new StringReader(layout);
+ AttributeLayoutElement e;
+ while ((e = readNextAttributeElement(stream)) != null) {
+ attributeLayoutElements.add(e);
+ }
+ resolveCalls();
+ }
+ }
+
+ /**
+ * Resolve calls in the attribute layout and returns the number of backwards
+ * callables
+ *
+ * @param tokens -
+ * the attribute layout as a List of AttributeElements
+ */
+ private void resolveCalls() {
+ 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 (int iIndex = 0; iIndex < body.size(); iIndex++) {
+ LayoutElement layoutElement = (LayoutElement) body
+ .get(iIndex);
+ // Set the callable for each call
+ resolveCallsForElement(i, callable, layoutElement);
+ }
+ }
+ }
+ int backwardsCallableIndex = 0;
+ for (int i = 0; i < attributeLayoutElements.size(); i++) {
+ AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElements
+ .get(i);
+ if (element instanceof Callable) {
+ Callable callable = (Callable) element;
+ if(callable.isBackwardsCallable) {
+ callable.setBackwardsCallableIndex(backwardsCallableIndex);
+ backwardsCallableIndex++;
+ }
+ }
+ }
+ backwardsCallCounts = new int[backwardsCallableIndex];
+ }
+
+ private void resolveCallsForElement(int i,
+ Callable currentCallable, LayoutElement layoutElement) {
+ if (layoutElement instanceof Call) {
+ Call call = (Call) layoutElement;
+ int index = call.callableIndex;
+ if (index == 0) { // Calls the parent callable
+ call.setCallable(currentCallable);
+ } else if (index > 0) { // Forwards call
+ for (int k = i + 1; 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
+ 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;
+ }
+ }
+ }
+ }
+ } else if (layoutElement instanceof Replication) {
+ List children = ((Replication)layoutElement).layoutElements;
+ for (Iterator iterator = children.iterator(); iterator.hasNext();) {
+ LayoutElement object = (LayoutElement) iterator.next();
+ resolveCallsForElement(i, currentCallable, object);
+ }
+ }
+ }
+
+ 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 {
+ char nextChar = (char)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[] { nextChar }));
+ case 'S':
+ case 'F':
+ return new Integral(new String(new 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).intValue();
+ 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;
+ } else {
+ stream.reset();
+ stream.read(); // '('
+ }
+ List tags = new ArrayList();
+ Integer nextTag;
+ do {
+ nextTag = readNumber(stream);
+ if(nextTag != null) {
+ tags.add(nextTag);
+ stream.read(); // ',' or ')'
+ }
+ } while (nextTag != null);
+ 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 {
+
+ public void addAttributeToBand(NewAttribute attribute, InputStream stream);
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception;
+
+ // TODO: bci renumbering
+
+ }
+
+ 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 final String tag;
+ private final IntList band = new IntList();
+ private final BHSDCodec defaultCodec;
+
+ public Integral(String tag) {
+ this.tag = tag;
+ this.defaultCodec = getCodec(tag);
+ }
+
+ public void addAttributeToBand(NewAttribute attribute,
+ InputStream stream) {
+ int value = 0;
+ if (tag.equals("B") || tag.equals("FB")) {
+ value = readInteger(1, stream) & 0xFF; // unsigned byte
+ } else if (tag.equals("SB")) {
+ value = readInteger(1, stream);
+ } else if (tag.equals("H") || tag.equals("FH")) {
+ value = readInteger(2, stream) & 0xFFFF; // unsigned short
+ } else if (tag.equals("SH")) {
+ value = readInteger(2, stream);
+ } else if (tag.equals("I") || tag.equals("FI")) {
+ value = readInteger(4, stream);
+ } else if (tag.equals("SI")) {
+ value = readInteger(4, stream);
+ } else if (tag.equals("V") || tag.equals("FV") || tag.equals("SV")) {
+ // TODO
+ } else if (tag.startsWith("PO") || tag.startsWith("OS")) {
+ // TODO: bci renumbering
+ char uint_type = tag.substring(2).toCharArray()[0];
+ int length = getLength(uint_type);
+ value = readInteger(length, stream);
+ } else if (tag.startsWith("P") || tag.startsWith("O")) {
+ char uint_type = tag.substring(1).toCharArray()[0];
+ int length = getLength(uint_type);
+ value = readInteger(length, stream);
+ }
+ band.add(value);
+ }
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception {
+ out.write(encodeBandInt(tag, band.toArray(), defaultCodec));
+ }
+
+ public int latestValue() {
+ return band.get(band.size() - 1);
+ }
+
+ }
+
+ /**
+ * A replication is an array of layout elements, with an associated count
+ */
+ private class Replication extends LayoutElement {
+
+ private final Integral countElement;
+
+ private final 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 addAttributeToBand(NewAttribute attribute,
+ InputStream stream) {
+ countElement.addAttributeToBand(attribute, stream);
+ for (Iterator iterator = layoutElements.iterator(); iterator.hasNext();) {
+ AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator.next();
+ layoutElement.addAttributeToBand(attribute, stream);
+ }
+ }
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception {
+ countElement.pack(out);
+ for (Iterator iterator = layoutElements.iterator(); iterator.hasNext();) {
+ AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator.next();
+ layoutElement.pack(out);
+ }
+ }
+ }
+
+ /**
+ * 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 final Integral unionTag;
+ private final List unionCases;
+ private final List defaultCaseBody;
+
+ public Union(String tag, List unionCases, List body) {
+ this.unionTag = new Integral(tag);
+ this.unionCases = unionCases;
+ this.defaultCaseBody = body;
+ }
+
+ public void addAttributeToBand(NewAttribute attribute,
+ InputStream stream) {
+ unionTag.addAttributeToBand(attribute, stream);
+ long tag = unionTag.latestValue();
+ boolean defaultCase = true;
+ for (int i = 0; i < unionCases.size(); i++) {
+ UnionCase element = (UnionCase) unionCases.get(i);
+ if (element.hasTag(tag)) {
+ defaultCase = false;
+ element.addAttributeToBand(attribute, stream);
+ }
+ }
+ if (defaultCase) {
+ for (int i = 0; i < defaultCaseBody.size(); i++) {
+ LayoutElement element = (LayoutElement) defaultCaseBody
+ .get(i);
+ element.addAttributeToBand(attribute, stream);
+ }
+ }
+ }
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception {
+ unionTag.pack(out);
+ for (Iterator iterator = unionCases.iterator(); iterator.hasNext();) {
+ UnionCase unionCase = (UnionCase) iterator.next();
+ unionCase.pack(out);
+ }
+ for (Iterator iterator = defaultCaseBody.iterator(); iterator
+ .hasNext();) {
+ AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator
+ .next();
+ layoutElement.pack(out);
+ }
+ }
+ }
+
+ private class Call extends LayoutElement {
+
+ private final 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 addAttributeToBand(NewAttribute attribute,
+ InputStream stream) {
+ callable.addAttributeToBand(attribute, stream);
+ if(callableIndex < 1) {
+ callable.addBackwardsCall();
+ }
+ }
+
+ public void pack(OutputStream out) {
+ // do nothing here - as pack will be called on the callable at another time
+ }
+ }
+
+ /**
+ * Constant Pool Reference
+ */
+ private class Reference extends LayoutElement {
+
+ private final String tag;
+
+ private List band;
+
+ private final int length;
+
+ private boolean nullsAllowed = false;
+
+ public Reference(String tag) {
+ this.tag = tag;
+ length = getLength(tag.charAt(tag.length() - 1));
+ nullsAllowed = tag.indexOf('N') != -1;
+ }
+
+ public void addAttributeToBand(NewAttribute attribute,
+ InputStream stream) {
+ int index = readInteger(4, stream);
+ if(tag.startsWith("RC")) { // Class
+ band.add(cpBands.getCPClass(attribute.readClass(index)));
+ } else if (tag.startsWith("RU")) { // UTF8 String
+ band.add(cpBands.getCPUtf8(attribute.readUTF8(index)));
+ } else if (tag.startsWith("RS")) { // Signature
+ band.add(cpBands.getCPSignature(attribute.readUTF8(index)));
+ } else { // Constant
+ band.add(cpBands.getConstant(attribute.readConst(index)));
+ }
+ // TODO method and field references
+ }
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception {
+ int[] ints;
+ if(nullsAllowed) {
+ ints = cpEntryOrNullListToArray(band);
+ } else {
+ ints = cpEntryListToArray(band);
+ }
+ out.write(encodeBandInt(tag, ints, Codec.UNSIGNED5));
+ }
+
+ }
+
+ private class Callable implements AttributeLayoutElement {
+
+ private final List body;
+
+ private boolean isBackwardsCallable;
+
+ private int backwardsCallableIndex;
+
+ public Callable(List body) throws IOException {
+ this.body = body;
+ }
+
+ public void setBackwardsCallableIndex(int backwardsCallableIndex) {
+ this.backwardsCallableIndex = backwardsCallableIndex;
+ }
+
+ public void addBackwardsCall() {
+ backwardsCallCounts[backwardsCallableIndex]++;
+ }
+
+ public boolean isBackwardsCallable() {
+ return isBackwardsCallable;
+ }
+
+ /**
+ * Tells this Callable that it is a backwards callable
+ */
+ public void setBackwardsCallable() {
+ this.isBackwardsCallable = true;
+ }
+
+ public void addAttributeToBand(NewAttribute attribute,
+ InputStream stream) {
+ for (Iterator iterator = body.iterator(); iterator.hasNext();) {
+ AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator.next();
+ layoutElement.addAttributeToBand(attribute, stream);
+ }
+ }
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception {
+ for (Iterator iterator = body.iterator(); iterator.hasNext();) {
+ AttributeLayoutElement layoutElement = (AttributeLayoutElement) iterator.next();
+ layoutElement.pack(out);
+ }
+ }
+ }
+
+ /**
+ * A Union case
+ */
+ private class UnionCase extends LayoutElement {
+
+ private List body;
+
+ private final 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 addAttributeToBand(NewAttribute attribute,
+ InputStream stream) {
+ for (int i = 0; i < body.size(); i++) {
+ LayoutElement element = (LayoutElement) body.get(i);
+ element.addAttributeToBand(attribute, stream);
+ }
+ }
+
+ public void pack(OutputStream out) throws IOException, Pack200Exception {
+ for (int i = 0; i < body.size(); i++) {
+ LayoutElement element = (LayoutElement) body.get(i);
+ element.pack(out);
+ }
+ }
+ }
+
+ /**
+ * 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());
+ }
+
+ private int readInteger(int i, InputStream stream) {
+ int result = 0;
+ for (int j = 0; j < i; j++) {
+ try {
+ result = result << 8 | stream.read();
+ } catch (IOException e) {
+ throw new RuntimeException("Error reading unknown attribute");
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Returns the {@link BHSDCodec} that should be used for the given layout
+ * element
+ *
+ * @param layoutElement
+ */
+ private BHSDCodec getCodec(String layoutElement) {
+ if (layoutElement.indexOf('O') >= 0) {
+ return Codec.BRANCH5;
+ } else if (layoutElement.indexOf('P') >= 0) {
+ return Codec.BCI5;
+ } else if (layoutElement.indexOf('S') >= 0 && layoutElement.indexOf("KS") < 0 //$NON-NLS-1$
+ && layoutElement.indexOf("RS") < 0) { //$NON-NLS-1$
+ return Codec.SIGNED5;
+ } else if (layoutElement.indexOf('B') >= 0) {
+ 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 Integer 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();
+ if(length == 0) {
+ return null;
+ }
+ char[] digits = new char[length];
+ int read = stream.read(digits);
+ if (read != digits.length) {
+ throw new IOException("Error reading from the input stream");
+ }
+ return new Integer(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;
+ }
+
+}
Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Pack200ClassReader.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Pack200ClassReader.java?rev=784048&r1=784047&r2=784048&view=diff
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Pack200ClassReader.java (original)
+++ harmony/enhanced/classlib/trunk/modules/pack200/src/main/java/org/apache/harmony/pack200/Pack200ClassReader.java Fri Jun 12 09:32:53 2009
@@ -22,7 +22,7 @@
import org.objectweb.asm.ClassReader;
/**
- * Wrapper for ClassReader than enables pack200 to obtain extra class file
+ * Wrapper for ClassReader that enables pack200 to obtain extra class file
* information
*/
public class Pack200ClassReader extends ClassReader {
@@ -30,6 +30,7 @@
private boolean lastConstantHadWideIndex;
private int lastUnsignedShort;
private boolean anySyntheticAttributes;
+ private String fileName;
/**
* @param b
@@ -96,4 +97,12 @@
return anySyntheticAttributes;
}
+ public void setFileName(String name) {
+ this.fileName = name;
+ }
+
+ public String getFileName() {
+ return fileName;
+ }
+
}