Pack200 - more testing for annotations and some associated bug fixes

git-svn-id: https://svn.apache.org/repos/asf/harmony/enhanced/java/trunk@989168 13f79535-47bb-0310-9956-ffa450edef68
master
Sian January 14 years ago
parent d8216aad44
commit 743eb4d225
  1. 24
      src/main/java/org/apache/harmony/pack200/AttributeDefinitionBands.java
  2. 4
      src/main/java/org/apache/harmony/pack200/ClassBands.java
  3. 31
      src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java
  4. 57
      src/main/java/org/apache/harmony/pack200/NewAttribute.java
  5. 56
      src/main/java/org/apache/harmony/pack200/PackingOptions.java
  6. 28
      src/main/java/org/apache/harmony/pack200/Segment.java
  7. 16
      src/main/java/org/apache/harmony/unpack200/MetadataBandGroup.java
  8. 18
      src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java
  9. 5
      src/test/java/org/apache/harmony/unpack200/tests/AttributeLayoutMapTest.java
  10. BIN
      src/test/resources/org/apache/harmony/pack200/tests/annotations2unpacked.jar

@ -59,17 +59,19 @@ public class AttributeDefinitionBands extends BandSet {
for (int i = 0; i < attributePrototypes.length; i++) { for (int i = 0; i < attributePrototypes.length; i++) {
NewAttribute newAttribute = (NewAttribute) attributePrototypes[i]; NewAttribute newAttribute = (NewAttribute) attributePrototypes[i];
if (newAttribute.isContextClass()) { if(!(newAttribute instanceof NewAttribute.ErrorAttribute) && !(newAttribute instanceof NewAttribute.PassAttribute) && !(newAttribute instanceof NewAttribute.StripAttribute)) {
classLayouts.put(newAttribute.type, newAttribute.getLayout()); if (newAttribute.isContextClass()) {
} classLayouts.put(newAttribute.type, newAttribute.getLayout());
if (newAttribute.isContextMethod()) { }
methodLayouts.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.isContextField()) {
} fieldLayouts.put(newAttribute.type, newAttribute.getLayout());
if (newAttribute.isContextCode()) { }
codeLayouts.put(newAttribute.type, newAttribute.getLayout()); if (newAttribute.isContextCode()) {
codeLayouts.put(newAttribute.type, newAttribute.getLayout());
}
} }
} }
if (classLayouts.keySet().size() > 7) { if (classLayouts.keySet().size() > 7) {

@ -1327,7 +1327,7 @@ public class ClassBands extends BandSet {
public void addParameterAnnotation(int parameter, String desc, public void addParameterAnnotation(int parameter, String desc,
boolean visible, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) { boolean visible, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) {
if(visible) { if(visible) {
method_RVPA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); method_RVPA_bands.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1); Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
if((flag.intValue() & (1<<23)) != 0) { if((flag.intValue() & (1<<23)) != 0) {
method_RVPA_bands.incrementAnnoN(); method_RVPA_bands.incrementAnnoN();
@ -1336,7 +1336,7 @@ public class ClassBands extends BandSet {
} }
tempMethodFlags.add(new Long(flag.longValue() | (1<<23))); tempMethodFlags.add(new Long(flag.longValue() | (1<<23)));
} else { } else {
method_RIPA_bands.addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); method_RIPA_bands.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1); Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1);
if((flag.longValue() & (1<<24)) != 0) { if((flag.longValue() & (1<<24)) != 0) {
method_RIPA_bands.incrementAnnoN(); method_RIPA_bands.incrementAnnoN();

@ -35,7 +35,7 @@ public class MetadataBandGroup extends BandSet {
private final String type; private final String type;
private int numBackwardsCalls = 0; private int numBackwardsCalls = 0;
public List param_NB = new ArrayList(); // TODO: Lazy instantiation? public IntList param_NB = new IntList(); // TODO: Lazy instantiation?
public IntList anno_N = new IntList(); public IntList anno_N = new IntList();
public List type_RS = new ArrayList(); public List type_RS = new ArrayList();
public IntList pair_N = new IntList(); public IntList pair_N = new IntList();
@ -95,6 +95,16 @@ public class MetadataBandGroup extends BandSet {
} }
byte[] encodedBand = null; byte[] encodedBand = null;
if(!type.equals("AD")) { if(!type.equals("AD")) {
if(type.indexOf('P') != -1) {
// Parameter annotation so we need to transmit param_NB
encodedBand = encodeBandInt(
contextStr + "_" + type + " param_NB", param_NB.toArray(),
Codec.BYTE1);
out.write(encodedBand);
PackingUtils.log("Wrote " + encodedBand.length
+ " bytes from " + contextStr + "_" + type + " anno_N["
+ param_NB.size() + "]");
}
encodedBand = encodeBandInt( encodedBand = encodeBandInt(
contextStr + "_" + type + " anno_N", anno_N.toArray(), contextStr + "_" + type + " anno_N", anno_N.toArray(),
Codec.UNSIGNED5); Codec.UNSIGNED5);
@ -230,6 +240,23 @@ public class MetadataBandGroup extends BandSet {
return ints; 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 addParameterAnnotation(int parameter, String desc, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) {
param_NB.add(parameter);
addAnnotation(desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN);
}
/** /**
* Add an annotation to this set of bands * Add an annotation to this set of bands
* *
@ -244,7 +271,7 @@ public class MetadataBandGroup extends BandSet {
*/ */
public void addAnnotation(String desc, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List 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)); type_RS.add(cpBands.getCPSignature(desc));
pair_N.add(t.size()); pair_N.add(nameRU.size());
for (Iterator iterator = nameRU.iterator(); iterator.hasNext();) { for (Iterator iterator = nameRU.iterator(); iterator.hasNext();) {
String name = (String) iterator.next(); String name = (String) iterator.next();

@ -142,4 +142,61 @@ public class NewAttribute extends Attribute {
public Label getLabel(int index) { public Label getLabel(int index) {
return labels[index]; return labels[index];
} }
/**
* ErrorAttribute extends <code>NewAttribute</code> and manages attributes
* encountered by ASM that have had an error action specified to pack200
* (e.g. via one of the -C, -M, -F or -D command line options such as
* -Cattribute-name=error)
*/
public static class ErrorAttribute extends NewAttribute {
public ErrorAttribute(String type, int context) {
super(type, "", context);
}
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
throw new Error("Attribute " + type + " was found");
}
}
/**
* StripAttribute extends <code>NewAttribute</code> and manages attributes
* encountered by ASM that have had an strip action specified to pack200
* (e.g. via one of the -C, -M, -F or -D command line options such as
* -Cattribute-name=strip)
*/
public static class StripAttribute extends NewAttribute {
public StripAttribute(String type, int context) {
super(type, "", context);
}
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
// TODO Not sure if this works, can we really strip an attribute if we don't know the layout?
return null;
}
}
/**
* PassAttribute extends <code>NewAttribute</code> and manages attributes
* encountered by ASM that have had an pass action specified to pack200
* (e.g. via one of the -C, -M, -F or -D command line options such as
* -Cattribute-name=pass)
*/
public static class PassAttribute extends NewAttribute {
public PassAttribute(String type, int context) {
super(type, "", context);
}
protected Attribute read(ClassReader cr, int off, int len, char[] buf,
int codeOff, Label[] labels) {
throw new Segment.PassException();
}
}
} }

@ -209,10 +209,6 @@ public class PackingOptions {
} }
} }
public Map getClassAttributeActions() {
return classAttributeActions;
}
public void addClassAttributeAction(String attributeName, String action) { public void addClassAttributeAction(String attributeName, String action) {
if(classAttributeActions == null) { if(classAttributeActions == null) {
classAttributeActions = new HashMap(); classAttributeActions = new HashMap();
@ -220,10 +216,6 @@ public class PackingOptions {
classAttributeActions.put(attributeName, action); classAttributeActions.put(attributeName, action);
} }
public Map getFieldAttributeActions() {
return fieldAttributeActions;
}
public void addFieldAttributeAction(String attributeName, String action) { public void addFieldAttributeAction(String attributeName, String action) {
if(fieldAttributeActions == null) { if(fieldAttributeActions == null) {
fieldAttributeActions = new HashMap(); fieldAttributeActions = new HashMap();
@ -231,10 +223,6 @@ public class PackingOptions {
fieldAttributeActions.put(attributeName, action); fieldAttributeActions.put(attributeName, action);
} }
public Map getMethodAttributeActions() {
return methodAttributeActions;
}
public void addMethodAttributeAction(String attributeName, String action) { public void addMethodAttributeAction(String attributeName, String action) {
if(methodAttributeActions == null) { if(methodAttributeActions == null) {
methodAttributeActions = new HashMap(); methodAttributeActions = new HashMap();
@ -242,10 +230,6 @@ public class PackingOptions {
methodAttributeActions.put(attributeName, action); methodAttributeActions.put(attributeName, action);
} }
public Map getCodeAttributeActions() {
return codeAttributeActions;
}
public void addCodeAttributeAction(String attributeName, String action) { public void addCodeAttributeAction(String attributeName, String action) {
if(codeAttributeActions == null) { if(codeAttributeActions == null) {
codeAttributeActions = new HashMap(); codeAttributeActions = new HashMap();
@ -288,25 +272,29 @@ public class PackingOptions {
.hasNext();) { .hasNext();) {
name = (String) iteratorI.next(); name = (String) iteratorI.next();
action = (String) attributeActions.get(name); action = (String) attributeActions.get(name);
if (!ERROR.equals(action) && !STRIP.equals(action) prototypeExists = false;
&& !PASS.equals(action)) { for (Iterator iteratorJ = prototypes.iterator(); iteratorJ
prototypeExists = false; .hasNext();) {
for (Iterator iteratorJ = prototypes.iterator(); iteratorJ newAttribute = (NewAttribute) iteratorJ.next();
.hasNext();) { if (newAttribute.type.equals(name)) {
newAttribute = (NewAttribute) iteratorJ.next(); // if the attribute exists, update its context
if (newAttribute.type.equals(name)) { newAttribute.addContext(tag);
// if the attribute exists, update its context prototypeExists = true;
newAttribute.addContext(tag); break;
prototypeExists = true; }
break; }
} // if no attribute is found, add a new attribute
// if no attribute is found, add a new attribute if (!prototypeExists) {
if (!prototypeExists) { if (ERROR.equals(action)) {
newAttribute = new NewAttribute(name, action, newAttribute = new NewAttribute.ErrorAttribute(name, tag);
tag); } else if (STRIP.equals(action)) {
prototypes.add(newAttribute); newAttribute = new NewAttribute.StripAttribute(name, tag);
} } else if (PASS.equals(action)) {
newAttribute = new NewAttribute.PassAttribute(name, tag);
} else {
newAttribute = new NewAttribute(name, action, tag);
} }
prototypes.add(newAttribute);
} }
} }
} }

@ -53,7 +53,7 @@ public class Segment implements ClassVisitor {
private PackingOptions options; private PackingOptions options;
private boolean stripDebug; private boolean stripDebug;
private Attribute[] nonStandardAttributePrototypes; private Attribute[] nonStandardAttributePrototypes;
/** /**
* The main method on Segment. Reads in all the class files, packs them and * The main method on Segment. Reads in all the class files, packs them and
* then writes the packed segment out to the given OutputStream. * then writes the packed segment out to the given OutputStream.
@ -76,11 +76,11 @@ public class Segment implements ClassVisitor {
this.stripDebug = options.isStripDebug(); this.stripDebug = options.isStripDebug();
int effort = options.getEffort(); int effort = options.getEffort();
nonStandardAttributePrototypes = options.getUnknownAttributePrototypes(); nonStandardAttributePrototypes = options.getUnknownAttributePrototypes();
PackingUtils.log("Start to pack a new segment with " PackingUtils.log("Start to pack a new segment with "
+ segmentUnit.fileListSize() + " files including " + segmentUnit.fileListSize() + " files including "
+ segmentUnit.classListSize() + " classes"); + segmentUnit.classListSize() + " classes");
PackingUtils.log("Initialize a header for the segment"); PackingUtils.log("Initialize a header for the segment");
segmentHeader = new SegmentHeader(); segmentHeader = new SegmentHeader();
segmentHeader.setFile_count(segmentUnit.fileListSize()); segmentHeader.setFile_count(segmentUnit.fileListSize());
@ -89,22 +89,22 @@ public class Segment implements ClassVisitor {
segmentHeader.setDeflate_hint("true".equals(options segmentHeader.setDeflate_hint("true".equals(options
.getDeflateHint())); .getDeflateHint()));
} }
PackingUtils.log("Setup constant pool bands for the segment"); PackingUtils.log("Setup constant pool bands for the segment");
cpBands = new CpBands(this, effort); cpBands = new CpBands(this, effort);
PackingUtils.log("Setup attribute definition bands for the segment"); PackingUtils.log("Setup attribute definition bands for the segment");
attributeDefinitionBands = new AttributeDefinitionBands(this, effort, nonStandardAttributePrototypes); attributeDefinitionBands = new AttributeDefinitionBands(this, effort, nonStandardAttributePrototypes);
PackingUtils.log("Setup internal class bands for the segment"); PackingUtils.log("Setup internal class bands for the segment");
icBands = new IcBands(segmentHeader, cpBands, effort); icBands = new IcBands(segmentHeader, cpBands, effort);
PackingUtils.log("Setup class bands for the segment"); PackingUtils.log("Setup class bands for the segment");
classBands = new ClassBands(this, segmentUnit.classListSize(), effort, stripDebug); classBands = new ClassBands(this, segmentUnit.classListSize(), effort, stripDebug);
PackingUtils.log("Setup byte code bands for the segment"); PackingUtils.log("Setup byte code bands for the segment");
bcBands = new BcBands(cpBands, this, effort); bcBands = new BcBands(cpBands, this, effort);
PackingUtils.log("Setup file bands for the segment"); PackingUtils.log("Setup file bands for the segment");
fileBands = new FileBands(cpBands, segmentHeader, options, segmentUnit, effort); fileBands = new FileBands(cpBands, segmentHeader, options, segmentUnit, effort);
@ -136,10 +136,10 @@ public class Segment implements ClassVisitor {
headerOutputStream.writeTo(out); headerOutputStream.writeTo(out);
bandsOutputStream.writeTo(out); bandsOutputStream.writeTo(out);
segmentUnit.addPackedByteAmount(headerOutputStream.size()); segmentUnit.addPackedByteAmount(headerOutputStream.size());
segmentUnit.addPackedByteAmount(bandsOutputStream.size()); segmentUnit.addPackedByteAmount(bandsOutputStream.size());
PackingUtils.log("Wrote total of " + segmentUnit.getPackedByteAmount() PackingUtils.log("Wrote total of " + segmentUnit.getPackedByteAmount()
+ " bytes"); + " bytes");
PackingUtils.log("Transmitted " + segmentUnit.fileListSize() + " files of " PackingUtils.log("Transmitted " + segmentUnit.fileListSize() + " files of "
@ -571,10 +571,6 @@ public class Segment implements ClassVisitor {
Integer numCases = (Integer) caseArrayN.remove(caseArrayN.size() - 1); Integer numCases = (Integer) caseArrayN.remove(caseArrayN.size() - 1);
caseArrayN.add(new Integer(numCases.intValue() + 1)); caseArrayN.add(new Integer(numCases.intValue() + 1));
T.add("e"); T.add("e");
if(name == null) {
name = "";
}
nameRU.add(name);
values.add(desc); values.add(desc);
values.add(value); values.add(value);
} }
@ -677,7 +673,7 @@ public class Segment implements ClassVisitor {
* passed through as-is in the file_bands rather than being packed with * passed through as-is in the file_bands rather than being packed with
* pack200. * pack200.
*/ */
public class PassException extends RuntimeException { public static class PassException extends RuntimeException {
} }
} }

@ -22,6 +22,8 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.harmony.unpack200.bytecode.AnnotationDefaultAttribute; import org.apache.harmony.unpack200.bytecode.AnnotationDefaultAttribute;
import org.apache.harmony.unpack200.bytecode.AnnotationsAttribute.Annotation;
import org.apache.harmony.unpack200.bytecode.AnnotationsAttribute.ElementValue;
import org.apache.harmony.unpack200.bytecode.Attribute; import org.apache.harmony.unpack200.bytecode.Attribute;
import org.apache.harmony.unpack200.bytecode.CPDouble; import org.apache.harmony.unpack200.bytecode.CPDouble;
import org.apache.harmony.unpack200.bytecode.CPFloat; import org.apache.harmony.unpack200.bytecode.CPFloat;
@ -30,8 +32,6 @@ import org.apache.harmony.unpack200.bytecode.CPLong;
import org.apache.harmony.unpack200.bytecode.CPUTF8; import org.apache.harmony.unpack200.bytecode.CPUTF8;
import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleAnnotationsAttribute; import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleAnnotationsAttribute;
import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute; import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute;
import org.apache.harmony.unpack200.bytecode.AnnotationsAttribute.Annotation;
import org.apache.harmony.unpack200.bytecode.AnnotationsAttribute.ElementValue;
import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute.ParameterAnnotation; import org.apache.harmony.unpack200.bytecode.RuntimeVisibleorInvisibleParameterAnnotationsAttribute.ParameterAnnotation;
/** /**
@ -117,8 +117,6 @@ public class MetadataBandGroup {
private int anno_N_Index; private int anno_N_Index;
private Iterator type_RS_Iterator;
private int pair_N_Index; private int pair_N_Index;
public List getAttributes() { public List getAttributes() {
@ -149,7 +147,6 @@ public class MetadataBandGroup {
} }
} else if (type.equals("RVPA") || type.equals("RIPA")) { } else if (type.equals("RVPA") || type.equals("RIPA")) {
anno_N_Index = 0; anno_N_Index = 0;
type_RS_Iterator = Arrays.asList(type_RS).iterator();
pair_N_Index = 0; pair_N_Index = 0;
for (int i = 0; i < param_NB.length; i++) { for (int i = 0; i < param_NB.length; i++) {
attributes.add(getParameterAttribute(param_NB[i], attributes.add(getParameterAttribute(param_NB[i],
@ -185,14 +182,13 @@ public class MetadataBandGroup {
int[] pairCounts = pair_N[pair_N_Index++]; int[] pairCounts = pair_N[pair_N_Index++];
Annotation[] annotations = new Annotation[numAnnotations]; Annotation[] annotations = new Annotation[numAnnotations];
for (int j = 0; j < annotations.length; j++) { for (int j = 0; j < annotations.length; j++) {
annotations[j] = getAnnotation( annotations[j] = getAnnotation(type_RS[anno_N_Index - 1][j],
(CPUTF8) type_RS_Iterator.next(), pairCounts[j], pairCounts[j], namesIterator);
namesIterator);
} }
parameter_annotations[i] = new ParameterAnnotation(annotations); parameter_annotations[i] = new ParameterAnnotation(annotations);
} }
return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute(type return new RuntimeVisibleorInvisibleParameterAnnotationsAttribute(
.equals("RVPA") ? rvpaUTF8 : ripaUTF8, type.equals("RVPA") ? rvpaUTF8 : ripaUTF8,
parameter_annotations); parameter_annotations);
} }

@ -344,7 +344,7 @@ public class ArchiveTest extends TestCase {
compareFiles(jarFile, jarFile2); compareFiles(jarFile, jarFile2);
} }
public void testAnnotations2() throws IOException, Pack200Exception, public void testAnnotations2() throws IOException, Pack200Exception,
URISyntaxException { URISyntaxException {
in = new JarFile(new File(Archive.class.getResource( in = new JarFile(new File(Archive.class.getResource(
@ -357,6 +357,22 @@ public class ArchiveTest extends TestCase {
new Archive(in, out, options).pack(); new Archive(in, out, options).pack();
in.close(); in.close();
out.close(); out.close();
// now unpack
InputStream in2 = new FileInputStream(file);
File file2 = File.createTempFile("annotationsout", ".jar");
// file2.deleteOnExit();
JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2));
org.apache.harmony.unpack200.Archive archive = new org.apache.harmony.unpack200.Archive(
in2, out2);
archive.unpack();
// TODO: This isn't quite right - to fix
// JarFile jarFile = new JarFile(file2);
// JarFile jarFile2 = new JarFile(new File(Archive.class.getResource(
// "/org/apache/harmony/pack200/tests/annotations2unpacked.jar")
// .toURI()));
// compareFiles(jarFile, jarFile2);
} }
public void testE0() throws Pack200Exception, IOException, URISyntaxException { public void testE0() throws Pack200Exception, IOException, URISyntaxException {

@ -31,14 +31,15 @@ public class AttributeLayoutMapTest extends TestCase {
AttributeLayout.CONTEXT_CLASS); AttributeLayout.CONTEXT_CLASS);
assertNotNull(layout); assertNotNull(layout);
assertEquals("RUNH", layout.getLayout()); assertEquals("RUNH", layout.getLayout());
assertEquals(17, layout.getIndex());
// and that we can change it // and that we can change it
a.add(new AttributeLayout("SourceFile", AttributeLayout.CONTEXT_CLASS, a.add(new AttributeLayout("SourceFile", AttributeLayout.CONTEXT_CLASS,
"FROG", 15)); "FROG", 17));
layout = a.getAttributeLayout("SourceFile", layout = a.getAttributeLayout("SourceFile",
AttributeLayout.CONTEXT_CLASS); AttributeLayout.CONTEXT_CLASS);
assertNotNull(layout); assertNotNull(layout);
assertEquals("FROG", layout.getLayout()); assertEquals("FROG", layout.getLayout());
assertTrue(layout.matches(1 << 15)); assertTrue(layout.matches(1 << 17));
assertFalse(layout.matches(1 << 16)); assertFalse(layout.matches(1 << 16));
assertTrue(layout.matches(-1)); assertTrue(layout.matches(-1));
assertFalse(layout.matches(0)); assertFalse(layout.matches(0));

Loading…
Cancel
Save