diff --git a/src/main/java/org/apache/harmony/pack200/BandSet.java b/src/main/java/org/apache/harmony/pack200/BandSet.java index a45dd83..c4f573a 100644 --- a/src/main/java/org/apache/harmony/pack200/BandSet.java +++ b/src/main/java/org/apache/harmony/pack200/BandSet.java @@ -331,26 +331,6 @@ public abstract class BandSet { } } - /** - * Returns true if the name of the source file can be predicted from the - * class name - * - * @param className - * the class name - * @param sourceFileName - * the source file name - */ - public boolean isPredictableSourceFileName(String className, String sourceFileName) { - if (className.indexOf('.') != -1) { - className = className.substring(className.lastIndexOf('.') + 1); - } - if (className.indexOf('$') != -1) { - className = className.substring(0, className.indexOf('$')); - } - className += ".java"; - return className.equals(sourceFileName); - } - // This could be useful if further enhancements are done but is not currently used // // private void encodeWithRunCodec(String name, int[] band, int index, diff --git a/src/main/java/org/apache/harmony/pack200/ClassBands.java b/src/main/java/org/apache/harmony/pack200/ClassBands.java index 0c843f5..094a90f 100644 --- a/src/main/java/org/apache/harmony/pack200/ClassBands.java +++ b/src/main/java/org/apache/harmony/pack200/ClassBands.java @@ -119,6 +119,8 @@ public class ClassBands extends BandSet { private final List tempFieldDesc = new ArrayList(); private final List tempMethodFlags = new ArrayList(); private final List tempMethodDesc = new ArrayList(); + private TempParamAnnotation tempMethodRVPA; + private TempParamAnnotation tempMethodRIPA; private boolean anySyntheticClasses = false; private boolean anySyntheticFields = false; @@ -153,6 +155,10 @@ public class ClassBands extends BandSet { field_flags = new long[numClasses][]; method_descr = new CPNameAndType[numClasses][]; method_flags = new long[numClasses][]; + for (int i = 0; i < numClasses; i++) { + field_flags[i] = new long[0]; + method_flags[i] = new long[0]; + } // minor_versions = new int[numClasses]; major_versions = new int[numClasses]; class_flags = new long[numClasses]; @@ -520,7 +526,7 @@ public class ClassBands extends BandSet { int totalFields = sum(class_field_count); int[] fieldDescr = new int[totalFields]; k = 0; - for (int i = 0; i < field_descr.length; i++) { + for (int i = 0; i < index; i++) { for (int j = 0; j < field_descr[i].length; j++) { CPNameAndType descr = field_descr[i][j]; fieldDescr[k] = descr.getIndex(); @@ -538,7 +544,7 @@ public class ClassBands extends BandSet { int totalMethods = sum(class_method_count); int[] methodDescr = new int[totalMethods]; k = 0; - for (int i = 0; i < method_descr.length; i++) { + for (int i = 0; i < index; i++) { for (int j = 0; j < method_descr[i].length; j++) { CPNameAndType descr = method_descr[i][j]; methodDescr[k] = descr.getIndex(); @@ -774,7 +780,9 @@ public class ClassBands extends BandSet { private int[] getInts(CPClass[] cpClasses) { int[] ints = new int[cpClasses.length]; for (int i = 0; i < ints.length; i++) { - ints[i] = cpClasses[i].getIndex(); + if(cpClasses[i] != null) { + ints[i] = cpClasses[i].getIndex(); + } } return ints; } @@ -999,6 +1007,24 @@ public class ClassBands extends BandSet { } public void endOfMethod() { + if (tempMethodRVPA != null) { + method_RVPA_bands.addParameterAnnotation(tempMethodRVPA.numParams, + tempMethodRVPA.annoN, tempMethodRVPA.pairN, + tempMethodRVPA.typeRS, tempMethodRVPA.nameRU, + tempMethodRVPA.t, tempMethodRVPA.values, + tempMethodRVPA.caseArrayN, tempMethodRVPA.nestTypeRS, + tempMethodRVPA.nestNameRU, tempMethodRVPA.nestPairN); + tempMethodRVPA = null; + } + if (tempMethodRIPA != null) { + method_RIPA_bands.addParameterAnnotation(tempMethodRIPA.numParams, + tempMethodRIPA.annoN, tempMethodRIPA.pairN, + tempMethodRIPA.typeRS, tempMethodRIPA.nameRU, + tempMethodRIPA.t, tempMethodRIPA.values, + tempMethodRIPA.caseArrayN, tempMethodRIPA.nestTypeRS, + tempMethodRIPA.nestNameRU, tempMethodRIPA.nestPairN); + tempMethodRIPA = null; + } if(codeFlags.size() > 0) { long latestCodeFlag = ((Long)codeFlags.get(codeFlags.size() - 1)).longValue(); int latestLocalVariableTableN = codeLocalVariableTableN.get(codeLocalVariableTableN.size() - 1); @@ -1327,26 +1353,57 @@ public class ClassBands extends BandSet { public void addParameterAnnotation(int parameter, String desc, boolean visible, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) { if(visible) { - method_RVPA_bands.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); - Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1); - if((flag.intValue() & (1<<23)) != 0) { - method_RVPA_bands.incrementAnnoN(); - } else { - method_RVPA_bands.newEntryInAnnoN(); + if(tempMethodRVPA == null) { + tempMethodRVPA = new TempParamAnnotation(numMethodArgs); + tempMethodRVPA.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); } + Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1); tempMethodFlags.add(new Long(flag.longValue() | (1<<23))); } else { - method_RIPA_bands.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); - Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1); - if((flag.longValue() & (1<<24)) != 0) { - method_RIPA_bands.incrementAnnoN(); - } else { - method_RIPA_bands.newEntryInAnnoN(); + if(tempMethodRIPA == null) { + tempMethodRIPA = new TempParamAnnotation(numMethodArgs); + tempMethodRIPA.addParameterAnnotation(parameter, desc, nameRU, t, values, caseArrayN, nestTypeRS, nestNameRU, nestPairN); } + Long flag = (Long) tempMethodFlags.remove(tempMethodFlags.size() - 1); tempMethodFlags.add(new Long(flag.longValue() | (1<<24))); } } + private static class TempParamAnnotation { + + int numParams; + int[] annoN; + IntList pairN = new IntList(); + List typeRS = new ArrayList(); + List nameRU = new ArrayList(); + List t = new ArrayList(); + List values = new ArrayList(); + List caseArrayN = new ArrayList(); + List nestTypeRS = new ArrayList(); + List nestNameRU = new ArrayList(); + List nestPairN = new ArrayList(); + + public TempParamAnnotation (int numParams) { + this.numParams = numParams; + annoN = new int[numParams]; + } + + public void addParameterAnnotation(int parameter, String desc, + List nameRU, List t, List values, List caseArrayN, + List nestTypeRS, List nestNameRU, List nestPairN) { + annoN[parameter]++; + typeRS.add(desc); + pairN.add(nameRU.size()); + this.nameRU.addAll(nameRU); + this.t.addAll(t); + this.values.addAll(values); + this.caseArrayN.addAll(caseArrayN); + this.nestTypeRS.addAll(nestTypeRS); + this.nestNameRU.addAll(nestNameRU); + this.nestPairN.addAll(nestPairN); + } + } + public void addAnnotation(int context, String desc, boolean visible, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) { switch (context) { case MetadataBandGroup.CONTEXT_CLASS: @@ -1548,6 +1605,12 @@ public class ClassBands extends BandSet { tempFieldFlags.clear(); tempMethodDesc.clear(); tempMethodFlags.clear(); - index--; + if(index > 0) { + index--; + } + } + + public int numClassesProcessed() { + return index; } } diff --git a/src/main/java/org/apache/harmony/pack200/FileBands.java b/src/main/java/org/apache/harmony/pack200/FileBands.java index 38bfcef..a23a46f 100644 --- a/src/main/java/org/apache/harmony/pack200/FileBands.java +++ b/src/main/java/org/apache/harmony/pack200/FileBands.java @@ -22,7 +22,6 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; -import java.util.TimeZone; import org.apache.harmony.pack200.Archive.PackingFile; import org.apache.harmony.pack200.Archive.SegmentUnit; @@ -41,11 +40,16 @@ public class FileBands extends BandSet { private final long[] file_size; private final int[] file_options; private final byte[][] file_bits; + private final List fileList; + private final PackingOptions options; + private final CpBands cpBands; public FileBands(CpBands cpBands, SegmentHeader segmentHeader, PackingOptions options, SegmentUnit segmentUnit, int effort) { super(effort, segmentHeader); - List fileList = segmentUnit.getFileList(); + fileList = segmentUnit.getFileList(); + this.options = options; + this.cpBands = cpBands; int size = fileList.size(); fileName = new CPUTF8[size]; file_modtime = new int[size]; @@ -88,7 +92,7 @@ public class FileBands extends BandSet { totalSize += file_size[i]; // update modification time - modtime = (packingFile.getModtime() + TimeZone.getDefault().getRawOffset()) / 1000L; + modtime = (packingFile.getModtime()) / 1000L; file_modtime[i] = (int) (modtime - archiveModtime); if (isLatest && latestModtime < file_modtime[i]) { latestModtime = file_modtime[i]; @@ -112,6 +116,14 @@ public class FileBands extends BandSet { public void finaliseBands() { file_name = new int[fileName.length]; for (int i = 0; i < file_name.length; i++) { + if (fileName[i].equals(cpBands.getCPUtf8(""))) { + PackingFile packingFile = (PackingFile) fileList.get(i); + String name = packingFile.getName(); + if (options.isPassFile(name)) { + fileName[i] = cpBands.getCPUtf8(name); + file_options[i] &= (1 << 1) ^ 0xFFFFFFFF; + } + } file_name[i] = fileName[i].getIndex(); } } diff --git a/src/main/java/org/apache/harmony/pack200/IntList.java b/src/main/java/org/apache/harmony/pack200/IntList.java index e2ba351..efa8e1c 100644 --- a/src/main/java/org/apache/harmony/pack200/IntList.java +++ b/src/main/java/org/apache/harmony/pack200/IntList.java @@ -250,4 +250,11 @@ public class IntList { return result; } + public void addAll(IntList list) { + growAtEnd(list.size()); + for (int i = 0; i < list.size(); i++) { + add(list.get(i)); + } + } + } diff --git a/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java b/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java index c396a28..1719396 100644 --- a/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java +++ b/src/main/java/org/apache/harmony/pack200/MetadataBandGroup.java @@ -252,9 +252,69 @@ public class MetadataBandGroup extends BandSet { * @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); + public void addParameterAnnotation(int numParams, int[] annoN, IntList pairN, List typeRS, List nameRU, List t, List values, List caseArrayN, List nestTypeRS, List nestNameRU, List nestPairN) { + param_NB.add(numParams); + for (int i = 0; i < annoN.length; i++) { + anno_N.add(annoN[i]); + } + pair_N.addAll(pairN); + for (Iterator iterator = typeRS.iterator(); iterator.hasNext();) { + String desc = (String) iterator.next(); + type_RS.add(cpBands.getCPSignature(desc)); + } + for (Iterator iterator = nameRU.iterator(); iterator.hasNext();) { + String name = (String) iterator.next(); + name_RU.add(cpBands.getCPUtf8(name)); + } + Iterator valuesIterator = values.iterator(); + for (Iterator iterator = t.iterator(); iterator.hasNext();) { + String tag = (String) iterator.next(); + T.add(tag); + if (tag.equals("B") || tag.equals("C") || tag.equals("I") + || tag.equals("S") || tag.equals("Z")) { + Integer value = (Integer)valuesIterator.next(); + caseI_KI.add(cpBands.getConstant(value)); + } else if (tag.equals("D")) { + Double value = (Double)valuesIterator.next(); + caseD_KD.add(cpBands.getConstant(value)); + } else if (tag.equals("F")) { + Float value = (Float)valuesIterator.next(); + caseF_KF.add(cpBands.getConstant(value)); + } else if (tag.equals("J")) { + Long value = (Long)valuesIterator.next(); + caseJ_KJ.add(cpBands.getConstant(value)); + } else if (tag.equals("c")) { + String value = (String)valuesIterator.next(); + casec_RS.add(cpBands.getCPSignature(value)); + } else if (tag.equals("e")) { + String value = (String)valuesIterator.next(); + String value2 = (String)valuesIterator.next(); + caseet_RS.add(cpBands.getCPSignature(value)); + caseec_RU.add(cpBands.getCPUtf8(value2)); + } else if (tag.equals("s")) { + String value = (String)valuesIterator.next(); + cases_RU.add(cpBands.getCPUtf8(value)); + } + // do nothing here for [ or @ (handled below) + } + for (Iterator iterator = caseArrayN.iterator(); iterator.hasNext();) { + int arraySize = ((Integer)iterator.next()).intValue(); + casearray_N.add(arraySize); + numBackwardsCalls += arraySize; + } + for (Iterator iterator = nestTypeRS.iterator(); iterator.hasNext();) { + String type = (String) iterator.next(); + nesttype_RS.add(cpBands.getCPSignature(type)); + } + for (Iterator iterator = nestNameRU.iterator(); iterator.hasNext();) { + String name = (String) iterator.next(); + nestname_RU.add(cpBands.getCPUtf8(name)); + } + for (Iterator iterator = nestPairN.iterator(); iterator.hasNext();) { + Integer numPairs = (Integer) iterator.next(); + nestpair_N.add(numPairs.intValue()); + numBackwardsCalls += numPairs.intValue(); + } } /** @@ -314,17 +374,17 @@ public class MetadataBandGroup extends BandSet { casearray_N.add(arraySize); numBackwardsCalls += arraySize; } - for (Iterator iterator = nesttype_RS.iterator(); iterator.hasNext();) { + for (Iterator iterator = nestTypeRS.iterator(); iterator.hasNext();) { String type = (String) iterator.next(); nesttype_RS.add(cpBands.getCPSignature(type)); } - for (Iterator iterator = nestname_RU.iterator(); iterator.hasNext();) { + for (Iterator iterator = nestNameRU.iterator(); iterator.hasNext();) { String name = (String) iterator.next(); nestname_RU.add(cpBands.getCPUtf8(name)); } for (Iterator iterator = nestPairN.iterator(); iterator.hasNext();) { Integer numPairs = (Integer) iterator.next(); - nestPairN.add(numPairs); + nestpair_N.add(numPairs.intValue()); numBackwardsCalls += numPairs.intValue(); } } diff --git a/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java b/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java index fe006ef..fcbd1b7 100644 --- a/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java +++ b/src/main/java/org/apache/harmony/pack200/NewAttributeBands.java @@ -155,7 +155,7 @@ public class NewAttributeBands extends BandSet { } } } else { // Backwards call - for (int k = i; k >= 0; k--) { + for (int k = i - 1; k >= 0; k--) { AttributeLayoutElement el = (AttributeLayoutElement) attributeLayoutElements .get(k); if (el instanceof Callable) { @@ -657,13 +657,10 @@ public class NewAttributeBands extends BandSet { 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; } diff --git a/src/main/java/org/apache/harmony/pack200/PackingOptions.java b/src/main/java/org/apache/harmony/pack200/PackingOptions.java index 61fed03..db1dd4e 100644 --- a/src/main/java/org/apache/harmony/pack200/PackingOptions.java +++ b/src/main/java/org/apache/harmony/pack200/PackingOptions.java @@ -35,7 +35,6 @@ public class PackingOptions { public static final String KEEP = "keep"; // All options are initially set to their defaults - private boolean repack = false; private boolean gzip = true; private boolean stripDebug = false; private boolean keepFileOrder = true; @@ -50,19 +49,10 @@ public class PackingOptions { private Map methodAttributeActions; private Map codeAttributeActions; private boolean verbose = false; - private boolean quiet = true; private String logFile; private Attribute[] unknownAttributeTypes; - public boolean isRepack() { - return repack; - } - - public void setRepack(boolean repack) { - this.repack = repack; - } - public boolean isGzip() { return gzip; } @@ -128,6 +118,14 @@ public class PackingOptions { } public void setDeflateHint(String deflateHint) { + if (!KEEP.equals(deflateHint) + && !"true".equals(deflateHint) + && !"false".equals(deflateHint)) { + throw new IllegalArgumentException( + "Bad argument: -H " + + deflateHint + + " ? deflate hint should be either true, false or keep (default)"); + } this.deflateHint = deflateHint; } @@ -245,12 +243,8 @@ public class PackingOptions { this.verbose = verbose; } - public boolean isQuiet() { - return quiet; - } - public void setQuiet(boolean quiet) { - this.quiet = quiet; + this.verbose = !quiet; } public String getLogFile() { diff --git a/src/main/java/org/apache/harmony/pack200/Segment.java b/src/main/java/org/apache/harmony/pack200/Segment.java index 7dab7f2..0223d2d 100644 --- a/src/main/java/org/apache/harmony/pack200/Segment.java +++ b/src/main/java/org/apache/harmony/pack200/Segment.java @@ -108,7 +108,7 @@ public class Segment implements ClassVisitor { PackingUtils.log("Setup file bands for the segment"); fileBands = new FileBands(cpBands, segmentHeader, options, segmentUnit, effort); - processClasses(segmentUnit); + processClasses(segmentUnit, nonStandardAttributePrototypes); cpBands.finaliseBands(); attributeDefinitionBands.finaliseBands(); @@ -124,11 +124,15 @@ public class Segment implements ClassVisitor { ByteArrayOutputStream bandsOutputStream = new ByteArrayOutputStream(); PackingUtils.log("Packing..."); + int finalNumberOfClasses = classBands.numClassesProcessed(); + segmentHeader.setClass_count(finalNumberOfClasses); cpBands.pack(bandsOutputStream); - attributeDefinitionBands.pack(bandsOutputStream); - icBands.pack(bandsOutputStream); - classBands.pack(bandsOutputStream); - bcBands.pack(bandsOutputStream); + if(finalNumberOfClasses > 0) { + attributeDefinitionBands.pack(bandsOutputStream); + icBands.pack(bandsOutputStream); + classBands.pack(bandsOutputStream); + bcBands.pack(bandsOutputStream); + } fileBands.pack(bandsOutputStream); ByteArrayOutputStream headerOutputStream = new ByteArrayOutputStream(); @@ -147,7 +151,7 @@ public class Segment implements ClassVisitor { + segmentUnit.getPackedByteAmount() + " bytes"); } - private void processClasses(SegmentUnit segmentUnit) throws Pack200Exception { + private void processClasses(SegmentUnit segmentUnit, Attribute[] attributes) throws Pack200Exception { segmentHeader.setClass_count(segmentUnit.classListSize()); for (Iterator iterator = segmentUnit.getClassList().iterator(); iterator.hasNext();) { Pack200ClassReader classReader = (Pack200ClassReader) iterator @@ -158,12 +162,14 @@ public class Segment implements ClassVisitor { flags |= ClassReader.SKIP_DEBUG; } try { - classReader.accept(this, flags); + classReader.accept(this, attributes, flags); } catch (PassException pe) { // Pass this class through as-is rather than packing it // TODO: probably need to deal with any inner classes classBands.removeCurrentClass(); String name = classReader.getFileName(); + options.addPassFile(name); + cpBands.addCPUtf8(name); boolean found = false; for (Iterator iterator2 = segmentUnit.getFileList().iterator(); iterator2 .hasNext();) { diff --git a/src/main/java/org/apache/harmony/unpack200/Archive.java b/src/main/java/org/apache/harmony/unpack200/Archive.java index a9a4933..927a4ad 100644 --- a/src/main/java/org/apache/harmony/unpack200/Archive.java +++ b/src/main/java/org/apache/harmony/unpack200/Archive.java @@ -234,7 +234,7 @@ public class Archive { public void setLogFile(String logFileName, boolean append) throws FileNotFoundException { - logFile = new FileOutputStream(logFileName, true); + logFile = new FileOutputStream(logFileName, append); } public void setDeflateHint(boolean deflateHint) { diff --git a/src/main/java/org/apache/harmony/unpack200/ClassBands.java b/src/main/java/org/apache/harmony/unpack200/ClassBands.java index 5562a56..ed5459f 100644 --- a/src/main/java/org/apache/harmony/unpack200/ClassBands.java +++ b/src/main/java/org/apache/harmony/unpack200/ClassBands.java @@ -1085,7 +1085,7 @@ public class ClassBands extends BandSet { + "_caseF_KF", in, Codec.UNSIGNED5, FCount); mbg[i].caseJ_KJ = parseCPLongReferences(contextName + "_" + rxa + "_caseJ_KJ", in, Codec.UNSIGNED5, JCount); - mbg[i].casec_RS = parseCPUTF8References(contextName + "_" + rxa + mbg[i].casec_RS = parseCPSignatureReferences(contextName + "_" + rxa + "_casec_RS", in, Codec.UNSIGNED5, cCount); mbg[i].caseet_RS = parseReferences(contextName + "_" + rxa + "_caseet_RS", in, Codec.UNSIGNED5, eCount, cpBands diff --git a/src/main/java/org/apache/harmony/unpack200/CpBands.java b/src/main/java/org/apache/harmony/unpack200/CpBands.java index b5b6918..b771d4b 100644 --- a/src/main/java/org/apache/harmony/unpack200/CpBands.java +++ b/src/main/java/org/apache/harmony/unpack200/CpBands.java @@ -88,7 +88,7 @@ public class CpBands extends BandSet { private Map mapUTF8; // TODO: Not used -// private Map mapSignature; + private Map mapSignature; private int intOffset; private int floatOffset; @@ -341,6 +341,7 @@ public class CpBands extends BandSet { Codec.DELTA5, cpSignatureCount); String[] cpSignatureForm = getReferences(cpSignatureInts, cpUTF8); cpSignature = new String[cpSignatureCount]; + mapSignature = new HashMap(); int lCount = 0; for (int i = 0; i < cpSignatureCount; i++) { String form = cpSignatureForm[i]; @@ -371,6 +372,7 @@ public class CpBands extends BandSet { } } cpSignature[i] = signature.toString(); + mapSignature.put(signature.toString(), new Integer(i)); } // for (int i = 0; i < cpSignatureInts.length; i++) { // if(cpSignatureInts[i] == -1) { @@ -547,19 +549,18 @@ public class CpBands extends BandSet { CPUTF8 cputf8 = (CPUTF8) stringsToCPUTF8.get(string); if (cputf8 == null) { Integer index = null; - if(searchForIndex) { + if(searchForIndex) { index = (Integer)mapUTF8.get(string); } if(index != null) { return cpUTF8Value(index.intValue()); } - /* TODO: mapSignature is not filled anywhere if(searchForIndex) { index = (Integer)mapSignature.get(string); } if(index != null) { return cpSignatureValue(index.intValue()); - }*/ + } cputf8 = new CPUTF8(string, -1); stringsToCPUTF8.put(string, cputf8); } diff --git a/src/main/java/org/apache/harmony/unpack200/NewAttributeBands.java b/src/main/java/org/apache/harmony/unpack200/NewAttributeBands.java index c27425d..a72e6e7 100644 --- a/src/main/java/org/apache/harmony/unpack200/NewAttributeBands.java +++ b/src/main/java/org/apache/harmony/unpack200/NewAttributeBands.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; @@ -49,7 +50,7 @@ public class NewAttributeBands extends BandSet { private int backwardsCallCount; - private List attributeLayoutElements; + protected List attributeLayoutElements; public NewAttributeBands(Segment segment, AttributeLayout attributeLayout) throws IOException { @@ -76,14 +77,15 @@ public class NewAttributeBands extends BandSet { */ public List parseAttributes(InputStream in, int occurrenceCount) throws IOException, Pack200Exception { - for(int i = 0; i < attributeLayoutElements.size(); i++) { - AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElements.get(i); + for (int i = 0; i < attributeLayoutElements.size(); i++) { + AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElements + .get(i); element.readBands(in, occurrenceCount); } List attributes = new ArrayList(occurrenceCount); for (int i = 0; i < occurrenceCount; i++) { - attributes.add(getOneAttribute(i, attributeLayoutElements)); + attributes.add(getOneAttribute(i, attributeLayoutElements)); } return attributes; } @@ -100,8 +102,9 @@ public class NewAttributeBands extends BandSet { NewAttribute attribute = new NewAttribute(segment.getCpBands() .cpUTF8Value(attributeLayout.getName()), attributeLayout.getIndex()); - for(int i = 0; i < elements.size(); i++) { - AttributeLayoutElement element = (AttributeLayoutElement) elements.get(i); + for (int i = 0; i < elements.size(); i++) { + AttributeLayoutElement element = (AttributeLayoutElement) elements + .get(i); element.addToAttribute(index, attribute); } return attribute; @@ -135,66 +138,67 @@ public class NewAttributeBands extends BandSet { .get(i); if (element instanceof Callable) { Callable callable = (Callable) element; - if(i == 0) { - callable.setFirstCallable(true); + if (i == 0) { + callable.setFirstCallable(true); } List body = callable.body; // Look for calls in the body - for(int iIndex = 0; iIndex < body.size(); iIndex++) { + for (int iIndex = 0; iIndex < body.size(); iIndex++) { LayoutElement layoutElement = (LayoutElement) body - .get(iIndex); - // Set the callable for each call - backwardsCalls += resolveCallsForElement(i, callable, - layoutElement); + .get(iIndex); + // Set the callable for each call + backwardsCalls += resolveCallsForElement(i, callable, + layoutElement); } } } backwardsCallCount = backwardsCalls; } - private int resolveCallsForElement(int i, - Callable currentCallable, LayoutElement layoutElement) { - int backwardsCalls = 0; - if (layoutElement instanceof Call) { + private int resolveCallsForElement(int i, Callable currentCallable, + LayoutElement layoutElement) { + int backwardsCalls = 0; + if (layoutElement instanceof Call) { Call call = (Call) layoutElement; - int index = call.callableIndex; - if (index == 0) { // Calls the parent callable - backwardsCalls++; - 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 - backwardsCalls++; - for (int k = i; k >= 0; k--) { - AttributeLayoutElement el = (AttributeLayoutElement) attributeLayoutElements - .get(k); - if (el instanceof Callable) { - index++; - if (index == 0) { - call.setCallable((Callable) el); - break; - } - } - } - } - } else if (layoutElement instanceof Replication) { - List children = ((Replication)layoutElement).layoutElements; - for (Iterator iterator = children.iterator(); iterator.hasNext();) { - LayoutElement object = (LayoutElement) iterator.next(); - backwardsCalls += resolveCallsForElement(i, currentCallable, object); - } - } - return backwardsCalls; - } + int index = call.callableIndex; + if (index == 0) { // Calls the parent callable + backwardsCalls++; + 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 + backwardsCalls++; + for (int k = i - 1; 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(); + backwardsCalls += resolveCallsForElement(i, currentCallable, + object); + } + } + return backwardsCalls; + } private AttributeLayoutElement readNextAttributeElement(StringReader stream) throws IOException { @@ -224,10 +228,10 @@ public class NewAttributeBands extends BandSet { case 'H': case 'I': case 'V': - return new Integral(new String(new char[] { (char)nextChar })); + return new Integral(new String(new char[] { (char) nextChar })); case 'S': case 'F': - return new Integral(new String(new char[] { (char)nextChar, + return new Integral(new String(new char[] { (char) nextChar, (char) stream.read() })); case 'P': stream.mark(1); @@ -284,7 +288,7 @@ public class NewAttributeBands extends BandSet { // Reference case 'K': case 'R': - String string = "" + (char)nextChar + (char) stream.read(); + String string = "" + (char) nextChar + (char) stream.read(); char nxt = (char) stream.read(); string += nxt; if (nxt == 'N') { @@ -316,9 +320,9 @@ public class NewAttributeBands extends BandSet { List tags = new ArrayList(); Integer nextTag; do { - nextTag = readNumber(stream); - if(nextTag != null) { - tags.add(nextTag); + nextTag = readNumber(stream); + if (nextTag != null) { + tags.add(nextTag); stream.read(); // ',' or ')' } } while (nextTag != null); @@ -385,9 +389,10 @@ public class NewAttributeBands extends BandSet { } } - private class Integral extends LayoutElement { + public class Integral extends LayoutElement { private final String tag; + private int[] band; public Integral(String tag) { @@ -447,12 +452,16 @@ public class NewAttributeBands extends BandSet { return band[index]; } + public String getTag() { + return tag; + } + } /** * A replication is an array of layout elements, with an associated count */ - private class Replication extends LayoutElement { + public class Replication extends LayoutElement { private final Integral countElement; @@ -474,7 +483,7 @@ public class NewAttributeBands extends BandSet { for (int i = 0; i < count; i++) { arrayCount += countElement.getValue(i); } - for(int i = 0; i < layoutElements.size(); i++) { + for (int i = 0; i < layoutElements.size(); i++) { LayoutElement element = (LayoutElement) layoutElements.get(i); element.readBands(in, arrayCount); } @@ -492,18 +501,27 @@ public class NewAttributeBands extends BandSet { long numElements = countElement.getValue(index); for (int i = offset; i < offset + numElements; i++) { for (int it = 0; it < layoutElements.size(); it++) { - LayoutElement element = (LayoutElement) layoutElements.get(it); + LayoutElement element = (LayoutElement) layoutElements + .get(it); element.addToAttribute(i, attribute); } } } + + public Integral getCountElement() { + return countElement; + } + + public List getLayoutElements() { + return layoutElements; + } } /** * 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 { + public class Union extends LayoutElement { private final Integral unionTag; private final List unionCases; @@ -535,7 +553,7 @@ public class NewAttributeBands extends BandSet { // Count number of default cases then read the default bands for (int i = 0; i < values.length; i++) { boolean found = false; - for(int it = 0; it < unionCases.size(); it++) { + for (int it = 0; it < unionCases.size(); it++) { UnionCase unionCase = (UnionCase) unionCases.get(it); if (unionCase.hasTag(values[i])) { found = true; @@ -546,8 +564,9 @@ public class NewAttributeBands extends BandSet { } } if (defaultCaseBody != null) { - for(int i = 0; i < defaultCaseBody.size(); i++) { - LayoutElement element = (LayoutElement) defaultCaseBody.get(i); + for (int i = 0; i < defaultCaseBody.size(); i++) { + LayoutElement element = (LayoutElement) defaultCaseBody + .get(i); element.readBands(in, defaultCount); } } @@ -559,7 +578,7 @@ public class NewAttributeBands extends BandSet { int[] tagBand = unionTag.band; long tag = unionTag.getValue(n); boolean defaultCase = true; - for(int i = 0; i < unionCases.size(); i++) { + for (int i = 0; i < unionCases.size(); i++) { UnionCase element = (UnionCase) unionCases.get(i); if (element.hasTag(tag)) { defaultCase = false; @@ -576,7 +595,7 @@ public class NewAttributeBands extends BandSet { int defaultOffset = 0; for (int j = 0; j < n; j++) { boolean found = false; - for(int i = 0; i < unionCases.size(); i++) { + for (int i = 0; i < unionCases.size(); i++) { UnionCase element = (UnionCase) unionCases.get(i); if (element.hasTag(tagBand[j])) { found = true; @@ -587,17 +606,30 @@ public class NewAttributeBands extends BandSet { } } if (defaultCaseBody != null) { - for(int i = 0; i < defaultCaseBody.size(); i++) { - LayoutElement element = (LayoutElement) defaultCaseBody.get(i); + for (int i = 0; i < defaultCaseBody.size(); i++) { + LayoutElement element = (LayoutElement) defaultCaseBody + .get(i); element.addToAttribute(defaultOffset, attribute); } } } } + public Integral getUnionTag() { + return unionTag; + } + + public List getUnionCases() { + return unionCases; + } + + public List getDefaultCaseBody() { + return defaultCaseBody; + } + } - private class Call extends LayoutElement { + public class Call extends LayoutElement { private final int callableIndex; private Callable callable; @@ -628,12 +660,20 @@ public class NewAttributeBands extends BandSet { public void addToAttribute(int n, NewAttribute attribute) { callable.addNextToAttribute(attribute); } + + public int getCallableIndex() { + return callableIndex; + } + + public Callable getCallable() { + return callable; + } } /** * Constant Pool Reference */ - private class Reference extends LayoutElement { + public class Reference extends LayoutElement { private final String tag; @@ -679,8 +719,8 @@ public class NewAttributeBands extends BandSet { band = parseCPMethodRefReferences(attributeLayout.getName(), in, Codec.UNSIGNED5, count); } else if (tag.startsWith("RI")) { // Interface Method Reference - band = parseCPInterfaceMethodRefReferences(attributeLayout - .getName(), in, Codec.UNSIGNED5, count); + band = parseCPInterfaceMethodRefReferences( + attributeLayout.getName(), in, Codec.UNSIGNED5, count); } else if (tag.startsWith("RU")) { // UTF8 String band = parseCPUTF8References(attributeLayout.getName(), in, Codec.UNSIGNED5, count); @@ -716,15 +756,19 @@ public class NewAttributeBands extends BandSet { } } + public String getTag() { + return tag; + } + } - private static class Callable implements AttributeLayoutElement { + public static class Callable implements AttributeLayoutElement { private final List body; private boolean isBackwardsCallable; - private boolean isFirstCallable; + private boolean isFirstCallable; public Callable(List body) throws IOException { this.body = body; @@ -740,7 +784,7 @@ public class NewAttributeBands extends BandSet { * @param attribute */ public void addNextToAttribute(NewAttribute attribute) { - for(int i = 0; i < body.size(); i++) { + for (int i = 0; i < body.size(); i++) { LayoutElement element = (LayoutElement) body.get(i); element.addToAttribute(index, attribute); } @@ -758,26 +802,26 @@ public class NewAttributeBands extends BandSet { public void readBands(InputStream in, int count) throws IOException, Pack200Exception { - if(isFirstCallable) { - count += this.count; - } else { - count = this.count; - } - for(int i = 0; i < body.size(); i++) { + if (isFirstCallable) { + count += this.count; + } else { + count = this.count; + } + for (int i = 0; i < body.size(); i++) { LayoutElement element = (LayoutElement) body.get(i); element.readBands(in, count); } } public void addToAttribute(int n, NewAttribute attribute) { - if(isFirstCallable) { - // Ignore n because bands also contain element parts from calls - for(int i = 0; i < body.size(); i++) { - LayoutElement element = (LayoutElement) body.get(i); - element.addToAttribute(index, attribute); - } - index++; - } + if (isFirstCallable) { + // Ignore n because bands also contain element parts from calls + for (int i = 0; i < body.size(); i++) { + LayoutElement element = (LayoutElement) body.get(i); + element.addToAttribute(index, attribute); + } + index++; + } } public boolean isBackwardsCallable() { @@ -791,15 +835,19 @@ public class NewAttributeBands extends BandSet { this.isBackwardsCallable = true; } - public void setFirstCallable(boolean isFirstCallable) { - this.isFirstCallable = isFirstCallable; - } + public void setFirstCallable(boolean isFirstCallable) { + this.isFirstCallable = isFirstCallable; + } + + public List getBody() { + return body; + } } /** * A Union case */ - private class UnionCase extends LayoutElement { + public class UnionCase extends LayoutElement { private List body; @@ -821,7 +869,7 @@ public class NewAttributeBands extends BandSet { public void readBands(InputStream in, int count) throws IOException, Pack200Exception { if (body != null) { - for(int i = 0; i < body.size(); i++) { + for (int i = 0; i < body.size(); i++) { LayoutElement element = (LayoutElement) body.get(i); element.readBands(in, count); } @@ -830,12 +878,16 @@ public class NewAttributeBands extends BandSet { public void addToAttribute(int index, NewAttribute attribute) { if (body != null) { - for(int i = 0; i < body.size(); i++) { + for (int i = 0; i < body.size(); i++) { LayoutElement element = (LayoutElement) body.get(i); element.addToAttribute(index, attribute); } } } + + public List getBody() { + return body == null ? Collections.EMPTY_LIST : body; + } } /** @@ -876,7 +928,8 @@ public class NewAttributeBands extends BandSet { 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$ + } 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) { @@ -934,15 +987,16 @@ public class NewAttributeBands extends BandSet { length++; } stream.reset(); - if(length == 0) { - return null; + 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))); + return new Integer(Integer.parseInt((negative ? "-" : "") + + new String(digits))); } /** @@ -978,8 +1032,9 @@ public class NewAttributeBands extends BandSet { public void setBackwardsCalls(int[] backwardsCalls) throws IOException { int index = 0; parseLayout(); - for(int i = 0; i < attributeLayoutElements.size(); i++) { - AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElements.get(i); + for (int i = 0; i < attributeLayoutElements.size(); i++) { + AttributeLayoutElement element = (AttributeLayoutElement) attributeLayoutElements + .get(i); if (element instanceof Callable && ((Callable) element).isBackwardsCallable()) { ((Callable) element).addCount(backwardsCalls[index]); diff --git a/src/main/java/org/apache/harmony/unpack200/Segment.java b/src/main/java/org/apache/harmony/unpack200/Segment.java index 85c95d0..c2cfa48 100644 --- a/src/main/java/org/apache/harmony/unpack200/Segment.java +++ b/src/main/java/org/apache/harmony/unpack200/Segment.java @@ -506,6 +506,9 @@ public class Segment { void unpackWrite(JarOutputStream out) throws IOException, Pack200Exception { writeJar(out); + if(logStream != null) { + logStream.close(); + } } /** @@ -592,10 +595,6 @@ public class Segment { return attrDefinitionBands; } - protected BcBands getBcBands() { - return bcBands; - } - protected ClassBands getClassBands() { return classBands; } @@ -604,10 +603,6 @@ public class Segment { return cpBands; } - protected FileBands getFileBands() { - return fileBands; - } - protected IcBands getIcBands() { return icBands; } diff --git a/src/main/java/org/apache/harmony/unpack200/bytecode/AnnotationsAttribute.java b/src/main/java/org/apache/harmony/unpack200/bytecode/AnnotationsAttribute.java index 529cdbb..5d4f652 100644 --- a/src/main/java/org/apache/harmony/unpack200/bytecode/AnnotationsAttribute.java +++ b/src/main/java/org/apache/harmony/unpack200/bytecode/AnnotationsAttribute.java @@ -127,6 +127,9 @@ public abstract class AnnotationsAttribute extends Attribute { } else if (value instanceof CPClass) { ((CPClass) value).resolve(pool); constant_value_index = pool.indexOf((CPClass) value); + } else if (value instanceof CPUTF8) { + ((CPUTF8) value).resolve(pool); + constant_value_index = pool.indexOf((CPUTF8) value); } else if (value instanceof CPNameAndType) { ((CPNameAndType) value).resolve(pool); } else if (value instanceof Annotation) { @@ -149,9 +152,12 @@ public abstract class AnnotationsAttribute extends Attribute { ((Annotation) value).writeBody(dos); } else if (value instanceof ElementValue[]) { ElementValue[] nestedValues = (ElementValue[]) value; + dos.writeShort(nestedValues.length); for (int i = 0; i < nestedValues.length; i++) { nestedValues[i].writeBody(dos); } + } else { + throw new Error(""); } } @@ -166,6 +172,7 @@ public abstract class AnnotationsAttribute extends Attribute { case 'S': case 'Z': case 'c': + case 's': return 3; case 'e': return 5; diff --git a/src/main/java/org/apache/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java b/src/main/java/org/apache/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java index 6d7daa5..9d38991 100644 --- a/src/main/java/org/apache/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java +++ b/src/main/java/org/apache/harmony/unpack200/bytecode/RuntimeVisibleorInvisibleAnnotationsAttribute.java @@ -54,10 +54,14 @@ public class RuntimeVisibleorInvisibleAnnotationsAttribute extends } protected void writeBody(DataOutputStream dos) throws IOException { + int size = dos.size(); dos.writeShort(num_annotations); for (int i = 0; i < num_annotations; i++) { annotations[i].writeBody(dos); } + if (dos.size() - size != getLength()) { + throw new Error(); + } } public String toString() { diff --git a/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java b/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java index 6a414f3..2ce1990 100644 --- a/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java +++ b/src/test/java/org/apache/harmony/pack200/tests/ArchiveTest.java @@ -47,6 +47,7 @@ public class ArchiveTest extends TestCase { in = new JarFile(new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/hw.jar").toURI())); file = File.createTempFile("helloworld", ".pack.gz"); + file.deleteOnExit(); out = new FileOutputStream(file); new Archive(in, out, null).pack(); in.close(); @@ -55,6 +56,7 @@ public class ArchiveTest extends TestCase { // now unpack InputStream in2 = new FileInputStream(file); File file2 = File.createTempFile("helloworld", ".jar"); + file2.deleteOnExit(); JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2)); org.apache.harmony.unpack200.Archive archive = new org.apache.harmony.unpack200.Archive( in2, out2); @@ -63,7 +65,6 @@ public class ArchiveTest extends TestCase { in2.close(); JarFile jarFile = new JarFile(file2); - file2.deleteOnExit(); JarEntry entry = jarFile .getJarEntry("org/apache/harmony/archive/tests/internal/pack200/HelloWorld.class"); assertNotNull(entry); @@ -97,6 +98,7 @@ public class ArchiveTest extends TestCase { in = new JarFile(new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); file = File.createTempFile("sql", ".pack"); + file.deleteOnExit(); out = new FileOutputStream(file); PackingOptions options = new PackingOptions(); options.setGzip(false); @@ -108,11 +110,11 @@ public class ArchiveTest extends TestCase { // now unpack InputStream in2 = new FileInputStream(file); File file2 = File.createTempFile("sqlout", ".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(); JarFile jarFile = new JarFile(file2); - file2.deleteOnExit(); File compareFile = new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI()); @@ -128,6 +130,7 @@ public class ArchiveTest extends TestCase { "/org/apache/harmony/pack200/tests/largeClassUnpacked.jar") .toURI())); file = File.createTempFile("largeClass", ".pack"); + file.deleteOnExit(); out = new FileOutputStream(file); PackingOptions options = new PackingOptions(); options.setGzip(false); @@ -138,11 +141,11 @@ public class ArchiveTest extends TestCase { // now unpack InputStream in2 = new FileInputStream(file); File file2 = File.createTempFile("largeClassOut", ".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(); JarFile jarFile = new JarFile(file2); - file2.deleteOnExit(); File compareFile = new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/largeClassUnpacked.jar").toURI()); @@ -157,6 +160,7 @@ public class ArchiveTest extends TestCase { in = new JarFile(new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/jndi.jar").toURI())); file = File.createTempFile("jndi", ".pack"); + file.deleteOnExit(); out = new FileOutputStream(file); PackingOptions options = new PackingOptions(); options.setGzip(false); @@ -167,162 +171,24 @@ public class ArchiveTest extends TestCase { // now unpack InputStream in2 = new FileInputStream(file); File file2 = File.createTempFile("jndiout", ".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(); JarFile jarFile = new JarFile(file2); - file2.deleteOnExit(); JarFile jarFile2 = new JarFile(new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/jndiUnpacked.jar").toURI())); compareFiles(jarFile, jarFile2); } - public void testSegmentLimits() throws IOException, Pack200Exception, - URISyntaxException { - in = new JarFile(new File(Archive.class.getResource( - "/org/apache/harmony/pack200/tests/hw.jar").toURI())); - file = File.createTempFile("helloworld", ".pack.gz"); - out = new FileOutputStream(file); - PackingOptions options = new PackingOptions(); - options.setSegmentLimit(0); - Archive archive = new Archive(in, out, options); - archive.pack(); - in.close(); - out.close(); - - in = new JarFile(new File(Archive.class.getResource( - "/org/apache/harmony/pack200/tests/hw.jar").toURI())); - file = File.createTempFile("helloworld", ".pack.gz"); - out = new FileOutputStream(file); - options = new PackingOptions(); - options.setSegmentLimit(-1); - archive = new Archive(in, out, options); - archive.pack(); - in.close(); - out.close(); - - in = new JarFile(new File(Archive.class.getResource( - "/org/apache/harmony/pack200/tests/hw.jar").toURI())); - file = File.createTempFile("helloworld", ".pack.gz"); - out = new FileOutputStream(file); - options = new PackingOptions(); - options.setSegmentLimit(5000); - archive = new Archive(in, out, options); - archive.pack(); - in.close(); - out.close(); - } - - public void testStripDebug() throws IOException, Pack200Exception, URISyntaxException { - in = new JarFile(new File(Archive.class - .getResource("/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); - file = File.createTempFile("sql", ".pack"); - out = new FileOutputStream(file); - PackingOptions options = new PackingOptions(); - options.setGzip(false); - options.setStripDebug(true); - Archive archive = new Archive(in, out, options); - archive.pack(); - in.close(); - out.close(); - - // now unpack - InputStream in2 = new FileInputStream(file); - File file2 = File.createTempFile("sqloutNoDebug", ".jar"); - JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2)); - org.apache.harmony.unpack200.Archive u2archive = new org.apache.harmony.unpack200.Archive(in2, out2); - u2archive.unpack(); - - File compareFile = new File(Archive.class.getResource( - "/org/apache/harmony/pack200/tests/sqlUnpackedNoDebug.jar").toURI()); - JarFile jarFile = new JarFile(file2); - assertTrue(file2.length() < 250000); - file2.deleteOnExit(); - - JarFile jarFile2 = new JarFile(compareFile); - - compareFiles(jarFile, jarFile2); - } - - public void testPassFiles() throws IOException, URISyntaxException, Pack200Exception { - // Don't pass any - in = new JarFile(new File(Archive.class - .getResource("/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); - File file0 = File.createTempFile("sql", ".pack"); - out = new FileOutputStream(file0); - PackingOptions options = new PackingOptions(); - options.setGzip(false); - Archive archive = new Archive(in, out, options); - archive.pack(); - in.close(); - out.close(); - - // Pass one file - in = new JarFile(new File(Archive.class - .getResource("/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); - file = File.createTempFile("sql", ".pack"); - out = new FileOutputStream(file); - options = new PackingOptions(); - options.setGzip(false); - options.addPassFile("bin/test/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.class"); - assertTrue(options.isPassFile("bin/test/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.class")); - archive = new Archive(in, out, options); - archive.pack(); - in.close(); - out.close(); - - // Pass a whole directory - in = new JarFile(new File(Archive.class - .getResource("/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); - File file2 = File.createTempFile("sql", ".pack"); - out = new FileOutputStream(file2); - options = new PackingOptions(); - options.setGzip(false); - options.addPassFile("bin/test/org/apache/harmony/sql/tests/java/sql"); - assertTrue(options.isPassFile("bin/test/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.class")); - assertFalse(options.isPassFile("bin/test/org/apache/harmony/sql/tests/java/sqldata/SqlData.class")); - archive = new Archive(in, out, options); - archive.pack(); - in.close(); - out.close(); - - assertTrue("If files are passed then the pack file should be larger", file.length() > file0.length()); - assertTrue("If more files are passed then the pack file should be larger", file2.length() > file.length()); - - // now unpack - InputStream in2 = new FileInputStream(file); - File file3 = File.createTempFile("sql", ".jar"); - JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file3)); - org.apache.harmony.unpack200.Archive u2archive = new org.apache.harmony.unpack200.Archive(in2, out2); - u2archive.unpack(); - - File compareFile = new File(Archive.class.getResource( - "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI()); - JarFile jarFile = new JarFile(file3); - file2.deleteOnExit(); - - JarFile jarFile2 = new JarFile(compareFile); - // Check that both jars have the same entries - compareJarEntries(jarFile, jarFile2); - - // now unpack the file with lots of passed files - InputStream in3 = new FileInputStream(file2); - File file4 = File.createTempFile("sql", ".jar"); - JarOutputStream out3 = new JarOutputStream(new FileOutputStream(file4)); - u2archive = new org.apache.harmony.unpack200.Archive(in3, out3); - u2archive.unpack(); - jarFile = new JarFile(file4); - jarFile2 = new JarFile(compareFile); - compareJarEntries(jarFile, jarFile2); - } - public void testAnnotations() throws IOException, Pack200Exception, URISyntaxException { in = new JarFile(new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/annotationsUnpacked.jar") .toURI())); file = File.createTempFile("annotations", ".pack"); + file.deleteOnExit(); out = new FileOutputStream(file); PackingOptions options = new PackingOptions(); options.setGzip(false); @@ -333,12 +199,12 @@ public class ArchiveTest extends TestCase { // 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(); JarFile jarFile = new JarFile(file2); - file2.deleteOnExit(); JarFile jarFile2 = new JarFile(new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/annotationsUnpacked.jar").toURI())); @@ -347,10 +213,11 @@ public class ArchiveTest extends TestCase { public void testAnnotations2() throws IOException, Pack200Exception, URISyntaxException { + in = new JarFile(new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/annotations.jar").toURI())); file = File.createTempFile("annotations", ".pack"); - file.deleteOnExit(); +// file.deleteOnExit(); out = new FileOutputStream(file); PackingOptions options = new PackingOptions(); options.setGzip(false); @@ -361,51 +228,38 @@ public class ArchiveTest extends TestCase { // now unpack InputStream in2 = new FileInputStream(file); File file2 = File.createTempFile("annotationsout", ".jar"); - // file2.deleteOnExit(); +// 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); + JarFile jarFile = new JarFile(file2); + JarFile jarFile2 = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/annotationsRI.jar") + .toURI())); + compareFiles(jarFile, jarFile2); } - public void testE0() throws Pack200Exception, IOException, URISyntaxException { - File f1 = new File(Archive.class.getResource( - "/org/apache/harmony/pack200/tests/jndi.jar").toURI()); - in = new JarFile(f1); - file = File.createTempFile("jndiE0", ".pack"); - out = new FileOutputStream(file); - PackingOptions options = new PackingOptions(); - options.setGzip(false); - options.setEffort(0); - Archive archive = new Archive(in, out, options); - archive.pack(); - in.close(); - out.close(); - compareFiles(new JarFile(f1), new JarFile(file)); +// Test with an archive containing Annotations + public void testWithAnnotations2() throws Exception { + InputStream i = Archive.class + .getResourceAsStream("/org/apache/harmony/pack200/tests/annotationsRI.pack.gz"); + file = File.createTempFile("annotations", ".jar"); + file.deleteOnExit(); + JarOutputStream jout = new JarOutputStream(new FileOutputStream(file)); + org.apache.harmony.unpack200.Archive archive = new org.apache.harmony.unpack200.Archive( + i, jout); + archive.unpack(); + JarFile jarFile = new JarFile(file); + JarFile jarFile2 = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/annotationsRI.jar") + .toURI())); + compareFiles(jarFile, jarFile2); } -// public void testE0again() throws IOException, Pack200Exception, URISyntaxException { -// JarInputStream inputStream = new JarInputStream(Archive.class.getResourceAsStream("/org/apache/harmony/pack200/tests/jndi.jar")); -// file = File.createTempFile("jndiE0", ".pack"); -// out = new FileOutputStream(file); -// Archive archive = new Archive(inputStream, out, false); -// archive.setEffort(0); -// archive.pack(); -// inputStream.close(); -// out.close(); -// in = new JarFile(new File(Archive.class.getResource( -// "/org/apache/harmony/pack200/tests/jndi.jar").toURI())); -// compareFiles(in, new JarFile(file)); -// } - public void testMultipleJars() throws URISyntaxException, IOException, Pack200Exception { File folder = new File(Archive.class .getResource("/org/apache/harmony/pack200/tests/jars").toURI()); @@ -415,6 +269,7 @@ public class ArchiveTest extends TestCase { File inputFile = new File(folder, children[i]); in = new JarFile(inputFile); file = File.createTempFile("temp", ".pack.gz"); + file.deleteOnExit(); out = new FileOutputStream(file); // System.out.println("packing " + children[i]); new Archive(in, out, null).pack(); diff --git a/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java b/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java index 51ff186..3a7f990 100644 --- a/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java +++ b/src/test/java/org/apache/harmony/pack200/tests/NewAttributeBandsTest.java @@ -24,14 +24,12 @@ import java.util.List; import junit.framework.TestCase; import org.apache.harmony.pack200.AttributeDefinitionBands; +import org.apache.harmony.pack200.AttributeDefinitionBands.AttributeDefinition; import org.apache.harmony.pack200.CPUTF8; import org.apache.harmony.pack200.Codec; import org.apache.harmony.pack200.CpBands; import org.apache.harmony.pack200.NewAttribute; import org.apache.harmony.pack200.NewAttributeBands; -import org.apache.harmony.pack200.Pack200Exception; -import org.apache.harmony.pack200.SegmentHeader; -import org.apache.harmony.pack200.AttributeDefinitionBands.AttributeDefinition; import org.apache.harmony.pack200.NewAttributeBands.Call; import org.apache.harmony.pack200.NewAttributeBands.Callable; import org.apache.harmony.pack200.NewAttributeBands.Integral; @@ -39,6 +37,8 @@ import org.apache.harmony.pack200.NewAttributeBands.Reference; import org.apache.harmony.pack200.NewAttributeBands.Replication; import org.apache.harmony.pack200.NewAttributeBands.Union; import org.apache.harmony.pack200.NewAttributeBands.UnionCase; +import org.apache.harmony.pack200.Pack200Exception; +import org.apache.harmony.pack200.SegmentHeader; /** * Tests for pack200 support for non-predefined attributes @@ -200,6 +200,65 @@ public class NewAttributeBandsTest extends TestCase { Call call = (Call) repBody.get(0); assertEquals(1, call.getCallableIndex()); assertEquals(secondCallable, call.getCallable()); + assertFalse(firstCallable.isBackwardsCallable()); + assertFalse(secondCallable.isBackwardsCallable()); + assertFalse(thirdCallable.isBackwardsCallable()); + } + + public void testLayoutWithBackwardsCalls() throws Exception { + CPUTF8 name = new CPUTF8("TestAttribute"); + CPUTF8 layout = new CPUTF8("[NH[(1)]][KIH][(-1)]"); + MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1, + null, null, new AttributeDefinition(35, + AttributeDefinitionBands.CONTEXT_CLASS, name, layout)); + List layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(3, layoutElements.size()); + Callable firstCallable = (Callable) layoutElements.get(0); + Callable secondCallable = (Callable) layoutElements.get(1); + Callable thirdCallable = (Callable) layoutElements.get(2); + List thirdBody = thirdCallable.getBody(); + assertEquals(1, thirdBody.size()); + Call call = (Call) thirdBody.get(0); + assertEquals(secondCallable, call.getCallable()); + assertTrue(secondCallable.isBackwardsCallable()); + assertFalse(firstCallable.isBackwardsCallable()); + assertFalse(thirdCallable.isBackwardsCallable()); + + name = new CPUTF8("TestAttribute"); + layout = new CPUTF8("[NH[(1)]][KIH][(-2)]"); + newAttributeBands = new MockNewAttributeBands(1, null, null, + new AttributeDefinition(35, + AttributeDefinitionBands.CONTEXT_CLASS, name, layout)); + layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(3, layoutElements.size()); + firstCallable = (Callable) layoutElements.get(0); + secondCallable = (Callable) layoutElements.get(1); + thirdCallable = (Callable) layoutElements.get(2); + thirdBody = thirdCallable.getBody(); + assertEquals(1, thirdBody.size()); + call = (Call) thirdBody.get(0); + assertEquals(firstCallable, call.getCallable()); + assertTrue(firstCallable.isBackwardsCallable()); + assertFalse(secondCallable.isBackwardsCallable()); + assertFalse(thirdCallable.isBackwardsCallable()); + + name = new CPUTF8("TestAttribute"); + layout = new CPUTF8("[NH[(1)]][KIH][(0)]"); + newAttributeBands = new MockNewAttributeBands(1, null, null, + new AttributeDefinition(35, + AttributeDefinitionBands.CONTEXT_CLASS, name, layout)); + layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(3, layoutElements.size()); + firstCallable = (Callable) layoutElements.get(0); + secondCallable = (Callable) layoutElements.get(1); + thirdCallable = (Callable) layoutElements.get(2); + thirdBody = thirdCallable.getBody(); + assertEquals(1, thirdBody.size()); + call = (Call) thirdBody.get(0); + assertEquals(thirdCallable, call.getCallable()); + assertTrue(thirdCallable.isBackwardsCallable()); + assertFalse(firstCallable.isBackwardsCallable()); + assertFalse(secondCallable.isBackwardsCallable()); } public void testAddAttributes() throws IOException, Pack200Exception { @@ -208,12 +267,16 @@ public class NewAttributeBandsTest extends TestCase { MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1, null, null, new AttributeDefinition(35, AttributeDefinitionBands.CONTEXT_CLASS, name, layout)); - newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", "B", new byte[] {27}, null, 0, null)); - newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", "B", new byte[] {56}, null, 0, null)); - newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", "B", new byte[] {3}, null, 0, null)); + newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", + "B", new byte[] { 27 }, null, 0, null)); + newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", + "B", new byte[] { 56 }, null, 0, null)); + newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", + "B", new byte[] { 3 }, null, 0, null)); ByteArrayOutputStream out = new ByteArrayOutputStream(); newAttributeBands.pack(out); - // BYTE1 is used for B layouts so we don't need to unpack to test the results + // BYTE1 is used for B layouts so we don't need to unpack to test the + // results byte[] bytes = out.toByteArray(); assertEquals(3, bytes.length); assertEquals(27, bytes[0]); @@ -221,17 +284,20 @@ public class NewAttributeBandsTest extends TestCase { assertEquals(3, bytes[2]); } - public void testAddAttributesWithReplicationLayout() throws IOException, Pack200Exception { + public void testAddAttributesWithReplicationLayout() throws IOException, + Pack200Exception { CPUTF8 name = new CPUTF8("TestAttribute"); CPUTF8 layout = new CPUTF8("NB[SH]"); MockNewAttributeBands newAttributeBands = new MockNewAttributeBands(1, null, null, new AttributeDefinition(35, AttributeDefinitionBands.CONTEXT_CLASS, name, layout)); - newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", "B", new byte[] {1, 0, 100}, null, 0, null)); + newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", + "B", new byte[] { 1, 0, 100 }, null, 0, null)); short s = -50; - byte b1 = (byte)(s>>>8); - byte b2 = (byte)s; - newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", "B", new byte[] {3, 0, 5, 0, 25, b1, b2}, null, 0, null)); + byte b1 = (byte) (s >>> 8); + byte b2 = (byte) s; + newAttributeBands.addAttribute(new NewAttribute(null, "TestAttribute", + "B", new byte[] { 3, 0, 5, 0, 25, b1, b2 }, null, 0, null)); ByteArrayOutputStream out = new ByteArrayOutputStream(); newAttributeBands.pack(out); byte[] bytes = out.toByteArray(); @@ -239,7 +305,8 @@ public class NewAttributeBandsTest extends TestCase { assertEquals(3, bytes[1]); byte[] band = new byte[bytes.length - 2]; System.arraycopy(bytes, 2, band, 0, band.length); - int[] decoded = Codec.SIGNED5.decodeInts(4, new ByteArrayInputStream(band)); + int[] decoded = Codec.SIGNED5.decodeInts(4, new ByteArrayInputStream( + band)); assertEquals(4, decoded.length); assertEquals(100, decoded[0]); assertEquals(5, decoded[1]); diff --git a/src/test/java/org/apache/harmony/pack200/tests/PackingOptionsTest.java b/src/test/java/org/apache/harmony/pack200/tests/PackingOptionsTest.java new file mode 100644 index 0000000..035d146 --- /dev/null +++ b/src/test/java/org/apache/harmony/pack200/tests/PackingOptionsTest.java @@ -0,0 +1,658 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.harmony.pack200.tests; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.URISyntaxException; +import java.util.Enumeration; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.jar.JarOutputStream; + +import junit.framework.TestCase; + +import org.apache.harmony.pack200.Archive; +import org.apache.harmony.pack200.Pack200Exception; +import org.apache.harmony.pack200.PackingOptions; + +/** + * Test different options for packing a Jar file + */ +public class PackingOptionsTest extends TestCase { + + JarFile in; + OutputStream out; + File file; + + public void testKeepFileOrder() throws Exception { + // Test default first + PackingOptions options = new PackingOptions(); + assertTrue(options.isKeepFileOrder()); + options.setKeepFileOrder(false); + assertFalse(options.isKeepFileOrder()); + + // Test option works correctly. Test 'True'. + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); + file = File.createTempFile("sql", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + options = new PackingOptions(); + options.setGzip(false); + Archive archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + InputStream in2 = new FileInputStream(file); + File file2 = File.createTempFile("sql", ".jar"); + file2.deleteOnExit(); + JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2)); + org.apache.harmony.unpack200.Archive u2archive = new org.apache.harmony.unpack200.Archive( + in2, out2); + u2archive.unpack(); + + File compareFile = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI()); + JarFile jarFile = new JarFile(file2); + + JarFile jarFile2 = new JarFile(compareFile); + + // Check that both jars have the same entries in the same order + Enumeration entries = jarFile.entries(); + Enumeration entries2 = jarFile2.entries(); + while (entries.hasMoreElements()) { + + JarEntry entry = (JarEntry) entries.nextElement(); + assertNotNull(entry); + JarEntry entry2 = (JarEntry) entries2.nextElement(); + String name = entry.getName(); + String name2 = entry2.getName(); + assertEquals(name, name2); + } + + // Test 'false' + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); + file = File.createTempFile("sql", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + options = new PackingOptions(); + options.setKeepFileOrder(false); + options.setGzip(false); + archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + in2 = new FileInputStream(file); + file2 = File.createTempFile("sql", ".jar"); + file2.deleteOnExit(); + out2 = new JarOutputStream(new FileOutputStream(file2)); + u2archive = new org.apache.harmony.unpack200.Archive(in2, out2); + u2archive.unpack(); + + compareFile = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI()); + jarFile = new JarFile(file2); + + jarFile2 = new JarFile(compareFile); + // Check that both jars have the same entries (may be in a different + // order) + compareJarEntries(jarFile, jarFile2); + + // Check files are not in order this time + entries = jarFile.entries(); + entries2 = jarFile2.entries(); + boolean inOrder = true; + while (entries.hasMoreElements()) { + JarEntry entry = (JarEntry) entries.nextElement(); + assertNotNull(entry); + JarEntry entry2 = (JarEntry) entries2.nextElement(); + String name = entry.getName(); + String name2 = entry2.getName(); + if (!name.equals(name2)) { + inOrder = false; + break; + } + } + assertFalse("Files are not expected to be in order", inOrder); + } + + public void testDeflateHint() { + // Test default first + PackingOptions options = new PackingOptions(); + assertEquals("keep", options.getDeflateHint()); + options.setDeflateHint("true"); + assertEquals("true", options.getDeflateHint()); + options.setDeflateHint("false"); + assertEquals("false", options.getDeflateHint()); + try { + options.setDeflateHint("hello"); + fail("Should throw IllegalArgumentException for incorrect deflate hint"); + } catch (IllegalArgumentException iae) { + // pass + } + } + + public void testModificationTime() throws Exception { + // Test default first + PackingOptions options = new PackingOptions(); + assertEquals("keep", options.getModificationTime()); + options.setModificationTime("latest"); + assertEquals("latest", options.getModificationTime()); + try { + options.setModificationTime("true"); + fail("Should throw IllegalArgumentException for incorrect mod time"); + } catch (IllegalArgumentException iae) { + // pass + } + + // Test option works correctly. Test 'keep'. + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); + file = File.createTempFile("sql", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + options = new PackingOptions(); + options.setGzip(false); + Archive archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + InputStream in2 = new FileInputStream(file); + File file2 = File.createTempFile("sql", ".jar"); + file2.deleteOnExit(); + JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2)); + org.apache.harmony.unpack200.Archive u2archive = new org.apache.harmony.unpack200.Archive( + in2, out2); + u2archive.unpack(); + + File compareFile = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI()); + JarFile jarFile = new JarFile(file2); + + JarFile jarFile2 = new JarFile(compareFile); + + // Check that both jars have the same entries in the same order + Enumeration entries = jarFile.entries(); + Enumeration entries2 = jarFile2.entries(); + while (entries.hasMoreElements()) { + + JarEntry entry = (JarEntry) entries.nextElement(); + assertNotNull(entry); + JarEntry entry2 = (JarEntry) entries2.nextElement(); + String name = entry.getName(); + String name2 = entry2.getName(); + assertEquals(name, name2); + assertEquals(entry.getTime(), entry2.getTime()); + } + + // Test option works correctly. Test 'latest'. + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); + file = File.createTempFile("sql", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + options = new PackingOptions(); + options.setGzip(false); + options.setModificationTime("latest"); + archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + in2 = new FileInputStream(file); + file2 = File.createTempFile("sql", ".jar"); + file2.deleteOnExit(); + out2 = new JarOutputStream(new FileOutputStream(file2)); + u2archive = new org.apache.harmony.unpack200.Archive(in2, out2); + u2archive.unpack(); + + compareFile = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI()); + jarFile = new JarFile(file2); + + jarFile2 = new JarFile(compareFile); + + // Check that all modtimes are the same and some are not the same as the + // original + entries = jarFile.entries(); + entries2 = jarFile2.entries(); + long modtime = -1; + boolean sameAsOriginal = true; + while (entries.hasMoreElements()) { + JarEntry entry = (JarEntry) entries.nextElement(); + assertNotNull(entry); + JarEntry entry2 = (JarEntry) entries2.nextElement(); + String name = entry.getName(); + if (!name.startsWith("META-INF")) { + if (modtime == -1) { + modtime = entry.getTime(); + } else { + assertEquals(modtime, entry.getTime()); + } + } + if (entry2.getTime() != entry.getTime()) { + sameAsOriginal = false; + } + } + assertFalse("Some modtimes should have changed", sameAsOriginal); + } + + // Test verbose, quiet and log file options. + public void testLoggingOptions() throws Exception { + // Test defaults + PackingOptions options = new PackingOptions(); + assertFalse(options.isVerbose()); + assertNull(options.getLogFile()); + options.setVerbose(true); + assertTrue(options.isVerbose()); + options.setQuiet(true); + assertFalse(options.isVerbose()); + + File logFile = File.createTempFile("logfile", ".txt"); + logFile.deleteOnExit(); + options.setLogFile(logFile.getPath()); + assertEquals(logFile.getPath(), options.getLogFile()); + + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/hw.jar").toURI())); + file = File.createTempFile("helloworld", ".pack.gz"); + file.deleteOnExit(); + out = new FileOutputStream(file); + new Archive(in, out, options).pack(); + in.close(); + out.close(); + + // log file should be empty + FileReader reader = new FileReader(logFile); + assertFalse(reader.ready()); + reader.close(); + + options.setVerbose(true); + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/hw.jar").toURI())); + file = File.createTempFile("helloworld", ".pack.gz"); + file.deleteOnExit(); + out = new FileOutputStream(file); + new Archive(in, out, options).pack(); + in.close(); + out.close(); + + // log file should not be empty + reader = new FileReader(logFile); + assertTrue(reader.ready()); + reader.close(); + } + + public void testSegmentLimits() throws IOException, Pack200Exception, + URISyntaxException { + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/hw.jar").toURI())); + file = File.createTempFile("helloworld", ".pack.gz"); + file.deleteOnExit(); + out = new FileOutputStream(file); + PackingOptions options = new PackingOptions(); + options.setSegmentLimit(0); + Archive archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/hw.jar").toURI())); + file = File.createTempFile("helloworld", ".pack.gz"); + file.deleteOnExit(); + out = new FileOutputStream(file); + options = new PackingOptions(); + options.setSegmentLimit(-1); + archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/hw.jar").toURI())); + file = File.createTempFile("helloworld", ".pack.gz"); + file.deleteOnExit(); + out = new FileOutputStream(file); + options = new PackingOptions(); + options.setSegmentLimit(5000); + archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + } + + public void testStripDebug() throws IOException, Pack200Exception, + URISyntaxException { + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); + file = File.createTempFile("sql", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + PackingOptions options = new PackingOptions(); + options.setGzip(false); + options.setStripDebug(true); + Archive archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + // now unpack + InputStream in2 = new FileInputStream(file); + File file2 = File.createTempFile("sqloutNoDebug", ".jar"); + file2.deleteOnExit(); + JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2)); + org.apache.harmony.unpack200.Archive u2archive = new org.apache.harmony.unpack200.Archive( + in2, out2); + u2archive.unpack(); + + File compareFile = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpackedNoDebug.jar") + .toURI()); + JarFile jarFile = new JarFile(file2); + assertTrue(file2.length() < 250000); + + JarFile jarFile2 = new JarFile(compareFile); + + compareFiles(jarFile, jarFile2); + } + + public void testPassFiles() throws IOException, URISyntaxException, + Pack200Exception { + // Don't pass any + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); + File file0 = File.createTempFile("sql", ".pack"); + file0.deleteOnExit(); + out = new FileOutputStream(file0); + PackingOptions options = new PackingOptions(); + options.setGzip(false); + Archive archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + // Pass one file + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); + file = File.createTempFile("sql", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + options = new PackingOptions(); + options.setGzip(false); + options.addPassFile("bin/test/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.class"); + assertTrue(options + .isPassFile("bin/test/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.class")); + archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + // Pass a whole directory + in = new JarFile(new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI())); + File file2 = File.createTempFile("sql", ".pack"); + file2.deleteOnExit(); + out = new FileOutputStream(file2); + options = new PackingOptions(); + options.setGzip(false); + options.addPassFile("bin/test/org/apache/harmony/sql/tests/java/sql"); + assertTrue(options + .isPassFile("bin/test/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.class")); + assertFalse(options + .isPassFile("bin/test/org/apache/harmony/sql/tests/java/sqldata/SqlData.class")); + archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + + assertTrue("If files are passed then the pack file should be larger", + file.length() > file0.length()); + assertTrue( + "If more files are passed then the pack file should be larger", + file2.length() > file.length()); + + // now unpack + InputStream in2 = new FileInputStream(file); + File file3 = File.createTempFile("sql", ".jar"); + file3.deleteOnExit(); + JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file3)); + org.apache.harmony.unpack200.Archive u2archive = new org.apache.harmony.unpack200.Archive( + in2, out2); + u2archive.unpack(); + + File compareFile = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI()); + JarFile jarFile = new JarFile(file3); + + JarFile jarFile2 = new JarFile(compareFile); + // Check that both jars have the same entries + compareJarEntries(jarFile, jarFile2); + + // now unpack the file with lots of passed files + InputStream in3 = new FileInputStream(file2); + File file4 = File.createTempFile("sql", ".jar"); + file4.deleteOnExit(); + JarOutputStream out3 = new JarOutputStream(new FileOutputStream(file4)); + u2archive = new org.apache.harmony.unpack200.Archive(in3, out3); + u2archive.unpack(); + jarFile = new JarFile(file4); + jarFile2 = new JarFile(compareFile); + compareJarEntries(jarFile, jarFile2); + } + + public void testNewAttributes() throws Exception { + in = new JarFile( + new File( + Archive.class + .getResource( + "/org/apache/harmony/pack200/tests/jndiWithUnknownAttributes.jar") + .toURI())); + file = File.createTempFile("unknown", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + PackingOptions options = new PackingOptions(); + options.addClassAttributeAction("Pack200", "I"); + Archive ar = new Archive(in, out, options); + ar.pack(); + in.close(); + out.close(); + + // unpack and check this was done right + InputStream in2 = new FileInputStream(file); + File file2 = File.createTempFile("unknown", ".jar"); + file2.deleteOnExit(); + JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2)); + org.apache.harmony.unpack200.Archive u2archive = new org.apache.harmony.unpack200.Archive( + in2, out2); + u2archive.unpack(); + + // compare with original + File compareFile = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/jndiWithUnknownAttributes.jar").toURI()); + JarFile jarFile = new JarFile(file2); + + JarFile jarFile2 = new JarFile(compareFile); + assertEquals(jarFile2.size(), jarFile.size()); + compareJarEntries(jarFile, jarFile2); +// compareFiles(jarFile, jarFile2); + } + + public void testErrorAttributes() throws Exception { + in = new JarFile( + new File( + Archive.class + .getResource( + "/org/apache/harmony/pack200/tests/jndiWithUnknownAttributes.jar") + .toURI())); + file = File.createTempFile("unknown", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + PackingOptions options = new PackingOptions(); + options.addClassAttributeAction("Pack200", "error"); + Archive ar = new Archive(in, out, options); + try { + ar.pack(); + in.close(); + out.close(); + fail("fail"); + } catch (Error e) { + // pass + assertEquals("Attribute Pack200 was found", e.getMessage()); + } + } + + public void testPassAttributes() throws Exception { + in = new JarFile( + new File( + Archive.class + .getResource( + "/org/apache/harmony/pack200/tests/jndiWithUnknownAttributes.jar") + .toURI())); + file = File.createTempFile("unknown", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + PackingOptions options = new PackingOptions(); + options.addClassAttributeAction("Pack200", "pass"); + Archive ar = new Archive(in, out, options); + ar.pack(); + in.close(); + out.close(); + + // now unpack + InputStream in2 = new FileInputStream(file); + File file2 = File.createTempFile("unknown", ".jar"); + file2.deleteOnExit(); + JarOutputStream out2 = new JarOutputStream(new FileOutputStream(file2)); + org.apache.harmony.unpack200.Archive u2archive = new org.apache.harmony.unpack200.Archive( + in2, out2); + u2archive.unpack(); + + // compare with original + File compareFile = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/jndiWithUnknownAttributes.jar").toURI()); + JarFile jarFile = new JarFile(file2); + + JarFile jarFile2 = new JarFile(compareFile); + assertEquals(jarFile2.size(), jarFile.size()); + compareJarEntries(jarFile, jarFile2); + } + + public void testE0() throws Pack200Exception, IOException, + URISyntaxException { + File f1 = new File(Archive.class.getResource( + "/org/apache/harmony/pack200/tests/jndi.jar").toURI()); + in = new JarFile(f1); + file = File.createTempFile("jndiE0", ".pack"); + file.deleteOnExit(); + out = new FileOutputStream(file); + PackingOptions options = new PackingOptions(); + options.setGzip(false); + options.setEffort(0); + Archive archive = new Archive(in, out, options); + archive.pack(); + in.close(); + out.close(); + compareFiles(new JarFile(f1), new JarFile(file)); + + } + + // public void testE0again() throws IOException, Pack200Exception, + // URISyntaxException { + // JarInputStream inputStream = new + // JarInputStream(Archive.class.getResourceAsStream("/org/apache/harmony/pack200/tests/jndi.jar")); + // file = File.createTempFile("jndiE0", ".pack"); + // out = new FileOutputStream(file); + // Archive archive = new Archive(inputStream, out, false); + // archive.setEffort(0); + // archive.pack(); + // inputStream.close(); + // out.close(); + // in = new JarFile(new File(Archive.class.getResource( + // "/org/apache/harmony/pack200/tests/jndi.jar").toURI())); + // compareFiles(in, new JarFile(file)); + // } + + private void compareJarEntries(JarFile jarFile, JarFile jarFile2) + throws IOException { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + + JarEntry entry = (JarEntry) entries.nextElement(); + assertNotNull(entry); + + String name = entry.getName(); + JarEntry entry2 = jarFile2.getJarEntry(name); + assertNotNull("Missing Entry: " + name, entry2); + } + } + + private void compareFiles(JarFile jarFile, JarFile jarFile2) + throws IOException { + Enumeration entries = jarFile.entries(); + while (entries.hasMoreElements()) { + + JarEntry entry = (JarEntry) entries.nextElement(); + assertNotNull(entry); + + String name = entry.getName(); + JarEntry entry2 = jarFile2.getJarEntry(name); + assertNotNull("Missing Entry: " + name, entry2); + // assertEquals(entry.getTime(), entry2.getTime()); + if (!name.equals("META-INF/MANIFEST.MF")) { // Manifests aren't + // necessarily + // byte-for-byte + // identical + + InputStream ours = jarFile.getInputStream(entry); + InputStream expected = jarFile2.getInputStream(entry2); + + BufferedReader reader1 = new BufferedReader( + new InputStreamReader(ours)); + BufferedReader reader2 = new BufferedReader( + new InputStreamReader(expected)); + String line1 = reader1.readLine(); + String line2 = reader2.readLine(); + int i = 1; + while (line1 != null || line2 != null) { + assertEquals("Unpacked files differ for " + name, line2, + line1); + line1 = reader1.readLine(); + line2 = reader2.readLine(); + i++; + } + reader1.close(); + reader2.close(); + } + } + jarFile.close(); + jarFile2.close(); + } + +} diff --git a/src/test/java/org/apache/harmony/unpack200/tests/ArchiveTest.java b/src/test/java/org/apache/harmony/unpack200/tests/ArchiveTest.java index 3fbf93f..c50ea37 100644 --- a/src/test/java/org/apache/harmony/unpack200/tests/ArchiveTest.java +++ b/src/test/java/org/apache/harmony/unpack200/tests/ArchiveTest.java @@ -19,6 +19,7 @@ package org.apache.harmony.unpack200.tests; import java.io.BufferedReader; import java.io.File; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -65,11 +66,11 @@ public class ArchiveTest extends TestCase { in = Archive.class .getResourceAsStream("/org/apache/harmony/pack200/tests/sql.pack.gz"); file = File.createTempFile("sql", ".jar"); + file.deleteOnExit(); out = new JarOutputStream(new FileOutputStream(file)); Archive archive = new Archive(in, out); archive.unpack(); JarFile jarFile = new JarFile(file); - file.deleteOnExit(); File compareFile = new File(Archive.class.getResource( "/org/apache/harmony/pack200/tests/sqlUnpacked.jar").toURI()); @@ -172,6 +173,7 @@ public class ArchiveTest extends TestCase { in = Archive.class .getResourceAsStream("/org/apache/harmony/pack200/tests/LargeClass.pack.gz"); file = File.createTempFile("largeClass", ".jar"); + file.deleteOnExit(); out = new JarOutputStream(new FileOutputStream(file)); Archive archive = new Archive(in, out); archive.unpack(); @@ -196,4 +198,60 @@ public class ArchiveTest extends TestCase { file.delete(); } + // Test verbose, quiet and log file options. + public void testLoggingOptions() throws Exception { + // test default option, which is quiet (no output at all) + in = Archive.class + .getResourceAsStream("/org/apache/harmony/pack200/tests/sql.pack.gz"); + file = File.createTempFile("logtest", ".jar"); + file.deleteOnExit(); + out = new JarOutputStream(new FileOutputStream(file)); + Archive archive = new Archive(in, out); + File logFile = File.createTempFile("logfile", ".txt"); + logFile.deleteOnExit(); + archive.setLogFile(logFile.getPath()); + archive.unpack(); + + // log file should be empty + FileReader reader = new FileReader(logFile); + assertFalse(reader.ready()); + reader.close(); + + // test verbose + in = Archive.class + .getResourceAsStream("/org/apache/harmony/pack200/tests/sql.pack.gz"); + file = File.createTempFile("logtest", ".jar"); + file.deleteOnExit(); + out = new JarOutputStream(new FileOutputStream(file)); + archive = new Archive(in, out); + logFile = File.createTempFile("logfile", ".txt"); + logFile.deleteOnExit(); + archive.setLogFile(logFile.getPath()); + archive.setVerbose(true); + archive.unpack(); + + // log file should not be empty + reader = new FileReader(logFile); + assertTrue(reader.ready()); + reader.close(); + + // test setting quiet explicitly + in = Archive.class + .getResourceAsStream("/org/apache/harmony/pack200/tests/sql.pack.gz"); + file = File.createTempFile("logtest", ".jar"); + file.deleteOnExit(); + out = new JarOutputStream(new FileOutputStream(file)); + archive = new Archive(in, out); + logFile = File.createTempFile("logfile", ".txt"); + logFile.deleteOnExit(); + archive.setLogFile(logFile.getPath()); + archive.setQuiet(true); + archive.unpack(); + + // log file should be empty + reader = new FileReader(logFile); + assertFalse(reader.ready()); + reader.close(); + } + } \ No newline at end of file diff --git a/src/test/java/org/apache/harmony/unpack200/tests/NewAttributeBandsTest.java b/src/test/java/org/apache/harmony/unpack200/tests/NewAttributeBandsTest.java new file mode 100644 index 0000000..c121e94 --- /dev/null +++ b/src/test/java/org/apache/harmony/unpack200/tests/NewAttributeBandsTest.java @@ -0,0 +1,256 @@ +/* + * 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.unpack200.tests; + +import java.io.IOException; +import java.util.List; + +import org.apache.harmony.pack200.Pack200Exception; +import org.apache.harmony.unpack200.AttributeLayout; +import org.apache.harmony.unpack200.NewAttributeBands; +import org.apache.harmony.unpack200.NewAttributeBands.Call; +import org.apache.harmony.unpack200.NewAttributeBands.Callable; +import org.apache.harmony.unpack200.NewAttributeBands.Integral; +import org.apache.harmony.unpack200.NewAttributeBands.Reference; +import org.apache.harmony.unpack200.NewAttributeBands.Replication; +import org.apache.harmony.unpack200.NewAttributeBands.Union; +import org.apache.harmony.unpack200.NewAttributeBands.UnionCase; +import org.apache.harmony.unpack200.Segment; + +/** + * Tests for unpack200 support for non-predefined attributes + */ +public class NewAttributeBandsTest extends AbstractBandsTestCase { + + public void testEmptyLayout() throws IOException, Pack200Exception { + MockNewAttributeBands newAttributeBands = new MockNewAttributeBands( + new MockSegment(), new AttributeLayout("test", + AttributeLayout.CONTEXT_CLASS, "", 25)); + List layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(0, layoutElements.size()); + } + + public void testIntegralLayout() throws IOException, Pack200Exception { + tryIntegral("B"); + tryIntegral("FB"); + tryIntegral("SB"); + tryIntegral("H"); + tryIntegral("FH"); + tryIntegral("SH"); + tryIntegral("I"); + tryIntegral("FI"); + tryIntegral("SI"); + tryIntegral("PB"); + tryIntegral("OB"); + tryIntegral("OSB"); + tryIntegral("POB"); + tryIntegral("PH"); + tryIntegral("OH"); + tryIntegral("OSH"); + tryIntegral("POH"); + tryIntegral("PI"); + tryIntegral("OI"); + tryIntegral("OSI"); + tryIntegral("POI"); + } + + public void tryIntegral(String layout) throws IOException, Pack200Exception { + MockNewAttributeBands newAttributeBands = new MockNewAttributeBands( + new MockSegment(), new AttributeLayout("test", + AttributeLayout.CONTEXT_CLASS, layout, 25)); + List layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(1, layoutElements.size()); + Integral element = (Integral) layoutElements.get(0); + assertEquals(layout, element.getTag()); + } + + public void testReplicationLayout() throws IOException, Pack200Exception { + MockNewAttributeBands newAttributeBands = new MockNewAttributeBands( + new MockSegment(), new AttributeLayout("test", + AttributeLayout.CONTEXT_CLASS, "NH[PHOHRUHRSHH]", 25)); + List layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(1, layoutElements.size()); + Replication element = (Replication) layoutElements.get(0); + Integral countElement = element.getCountElement(); + assertEquals("H", countElement.getTag()); + List replicatedElements = element.getLayoutElements(); + assertEquals(5, replicatedElements.size()); + Integral firstElement = (Integral) replicatedElements.get(0); + assertEquals("PH", firstElement.getTag()); + Integral secondElement = (Integral) replicatedElements.get(1); + assertEquals("OH", secondElement.getTag()); + Reference thirdElement = (Reference) replicatedElements.get(2); + assertEquals("RUH", thirdElement.getTag()); + Reference fourthElement = (Reference) replicatedElements.get(3); + assertEquals("RSH", fourthElement.getTag()); + Integral fifthElement = (Integral) replicatedElements.get(4); + assertEquals("H", fifthElement.getTag()); + } + + public void testReferenceLayouts() throws IOException, Pack200Exception { + tryReference("KIB"); + tryReference("KIH"); + tryReference("KII"); + tryReference("KINH"); + tryReference("KJH"); + tryReference("KDH"); + tryReference("KSH"); + tryReference("KQH"); + tryReference("RCH"); + tryReference("RSH"); + tryReference("RDH"); + tryReference("RFH"); + tryReference("RMH"); + tryReference("RIH"); + tryReference("RUH"); + tryReference("RQH"); + tryReference("RQNH"); + tryReference("RQNI"); + } + + private void tryReference(String layout) throws IOException, + Pack200Exception { + MockNewAttributeBands newAttributeBands = new MockNewAttributeBands( + new MockSegment(), new AttributeLayout("test", + AttributeLayout.CONTEXT_CODE, layout, 26)); + List layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(1, layoutElements.size()); + Reference element = (Reference) layoutElements.get(0); + assertEquals(layout, element.getTag()); + } + + public void testUnionLayout() throws IOException, Pack200Exception { + MockNewAttributeBands newAttributeBands = new MockNewAttributeBands( + new MockSegment(), new AttributeLayout("test", + AttributeLayout.CONTEXT_CODE, + "TB(55)[FH](23)[]()[RSH]", 26)); + List layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(1, layoutElements.size()); + Union element = (Union) layoutElements.get(0); + Integral tag = element.getUnionTag(); + assertEquals("B", tag.getTag()); + List unionCases = element.getUnionCases(); + assertEquals(2, unionCases.size()); + UnionCase firstCase = (UnionCase) unionCases.get(0); + assertTrue(firstCase.hasTag(55)); + assertFalse(firstCase.hasTag(23)); + List body = firstCase.getBody(); + assertEquals(1, body.size()); + Integral bodyElement = (Integral) body.get(0); + assertEquals("FH", bodyElement.getTag()); + UnionCase secondCase = (UnionCase) unionCases.get(1); + assertTrue(secondCase.hasTag(23)); + assertFalse(secondCase.hasTag(55)); + body = secondCase.getBody(); + assertEquals(0, body.size()); + List defaultBody = element.getDefaultCaseBody(); + assertEquals(1, defaultBody.size()); + Reference ref = (Reference) defaultBody.get(0); + assertEquals("RSH", ref.getTag()); + } + + public void testLayoutWithCalls() throws IOException, Pack200Exception { + MockNewAttributeBands newAttributeBands = new MockNewAttributeBands( + new MockSegment(), + new AttributeLayout( + "test", + AttributeLayout.CONTEXT_FIELD, + "[NH[(1)]][RSH NH[RUH(1)]][TB(66,67,73,83,90)[KIH](68)[KDH](70)[KFH](74)[KJH](99)[RSH](101)[RSH RUH](115)[RUH](91)[NH[(0)]](64)[RSH[RUH(0)]]()[]]", + 26)); + List layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(3, layoutElements.size()); + Callable firstCallable = (Callable) layoutElements.get(0); + Callable secondCallable = (Callable) layoutElements.get(1); + Callable thirdCallable = (Callable) layoutElements.get(2); + List firstBody = firstCallable.getBody(); + assertEquals(1, firstBody.size()); + Replication rep = (Replication) firstBody.get(0); + List repBody = rep.getLayoutElements(); + assertEquals(1, repBody.size()); + Call call = (Call) repBody.get(0); + assertEquals(1, call.getCallableIndex()); + assertEquals(secondCallable, call.getCallable()); + assertFalse(firstCallable.isBackwardsCallable()); + assertFalse(secondCallable.isBackwardsCallable()); + assertFalse(thirdCallable.isBackwardsCallable()); + } + + public void testLayoutWithBackwardsCall() throws IOException, + Pack200Exception { + MockNewAttributeBands newAttributeBands = new MockNewAttributeBands( + new MockSegment(), new AttributeLayout("test", + AttributeLayout.CONTEXT_METHOD, "[NH[(1)]][KIH][(-1)]", + 20)); + List layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(3, layoutElements.size()); + Callable firstCallable = (Callable) layoutElements.get(0); + Callable secondCallable = (Callable) layoutElements.get(1); + Callable thirdCallable = (Callable) layoutElements.get(2); + List thirdBody = thirdCallable.getBody(); + assertEquals(1, thirdBody.size()); + Call call = (Call) thirdBody.get(0); + assertEquals(secondCallable, call.getCallable()); + assertTrue(secondCallable.isBackwardsCallable()); + assertFalse(firstCallable.isBackwardsCallable()); + assertFalse(thirdCallable.isBackwardsCallable()); + + newAttributeBands = new MockNewAttributeBands(new MockSegment(), + new AttributeLayout("test", AttributeLayout.CONTEXT_METHOD, + "[NH[(1)]][KIH][(-2)]", 20)); + layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(3, layoutElements.size()); + firstCallable = (Callable) layoutElements.get(0); + secondCallable = (Callable) layoutElements.get(1); + thirdCallable = (Callable) layoutElements.get(2); + thirdBody = thirdCallable.getBody(); + assertEquals(1, thirdBody.size()); + call = (Call) thirdBody.get(0); + assertEquals(firstCallable, call.getCallable()); + assertTrue(firstCallable.isBackwardsCallable()); + assertFalse(secondCallable.isBackwardsCallable()); + assertFalse(thirdCallable.isBackwardsCallable()); + + newAttributeBands = new MockNewAttributeBands(new MockSegment(), + new AttributeLayout("test", AttributeLayout.CONTEXT_METHOD, + "[NH[(1)]][KIH][(0)]", 20)); + layoutElements = newAttributeBands.getLayoutElements(); + assertEquals(3, layoutElements.size()); + firstCallable = (Callable) layoutElements.get(0); + secondCallable = (Callable) layoutElements.get(1); + thirdCallable = (Callable) layoutElements.get(2); + thirdBody = thirdCallable.getBody(); + assertEquals(1, thirdBody.size()); + call = (Call) thirdBody.get(0); + assertEquals(thirdCallable, call.getCallable()); + assertTrue(thirdCallable.isBackwardsCallable()); + assertFalse(firstCallable.isBackwardsCallable()); + assertFalse(secondCallable.isBackwardsCallable()); + assertFalse(firstCallable.isBackwardsCallable()); + } + + private class MockNewAttributeBands extends NewAttributeBands { + + public MockNewAttributeBands(Segment segment, AttributeLayout layout) + throws IOException { + super(segment, layout); + } + + public List getLayoutElements() { + return attributeLayoutElements; + } + } +} diff --git a/src/test/resources/org/apache/harmony/pack200/tests/annotationsRI.jar b/src/test/resources/org/apache/harmony/pack200/tests/annotationsRI.jar new file mode 100644 index 0000000..d8e9112 Binary files /dev/null and b/src/test/resources/org/apache/harmony/pack200/tests/annotationsRI.jar differ diff --git a/src/test/resources/org/apache/harmony/pack200/tests/jndiWithUnknownAttributes.jar b/src/test/resources/org/apache/harmony/pack200/tests/jndiWithUnknownAttributes.jar new file mode 100644 index 0000000..a9d6a97 Binary files /dev/null and b/src/test/resources/org/apache/harmony/pack200/tests/jndiWithUnknownAttributes.jar differ