You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ap...@apache.org on 2006/11/24 17:29:00 UTC

svn commit: r478907 [1/2] - in /harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200: ./ bytecode/

Author: apetrenko
Date: Fri Nov 24 08:28:57 2006
New Revision: 478907

URL: http://svn.apache.org/viewvc?view=rev&rev=478907
Log:
Patch for HARMONY-2246 "[classlib][pack200] Ongoing implementation"

Added:
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/Attribute.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPClass.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstant.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstantNumber.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPDouble.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPField.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFieldRef.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFloat.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPInteger.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPLong.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMember.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMethod.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPNameAndType.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPString.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPUTF8.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ClassConstantPool.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ClassFile.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ClassFileEntry.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ConstantPoolEntry.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ConstantValueAttribute.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ExceptionsAttribute.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/SourceFileAttribute.java
Removed:
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/ClassConstantPool.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/ClassFile.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/ClassFileEntry.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/ConstantPoolEntry.java
Modified:
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayout.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayoutMap.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Pack200PackerAdapter.java
    harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Segment.java

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayout.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayout.java?view=diff&rev=478907&r1=478906&r2=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayout.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayout.java Fri Nov 24 08:28:57 2006
@@ -15,9 +15,11 @@
  *  limitations under the License.
  */
 package org.apache.harmony.archive.internal.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
+// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
+// NOTE: Do not extract strings as messages; this code is still a
+// work-in-progress
+// NOTE: Also, don't get rid of 'else' statements for the hell of it ...
 import org.apache.harmony.archive.internal.pack200.Segment.SegmentConstantPool;
 
 public class AttributeLayout {
@@ -78,6 +80,40 @@
 
 	private long mask;
 
+	public static final String ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS = "RuntimeInvisibleAnnotations";
+
+	public static final String ATTRIBUTE_CLASS_FILE_VERSION = "class-file version";
+
+	public static final String ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS = "RuntimeInvisibleParameterAnnotations";
+
+	public static final String ATTRIBUTE_ANNOTATION_DEFAULT = "AnnotationDefault";
+
+	public static final String ATTRIBUTE_CODE = "Code";
+
+	public static final String ATTRIBUTE_SOURCE_FILE = "SourceFile";
+
+	public static final String ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE = "LocalVariableTypeTable";
+
+	public static final String ATTRIBUTE_LOCAL_VARIABLE_TABLE = "LocalVariableTable";
+
+	public static final String ATTRIBUTE_LINE_NUMBER_TABLE = "LineNumberTable";
+
+	public static final String ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS = "RuntimeVisibleParameterAnnotations";
+
+	public static final String ATTRIBUTE_INNER_CLASSES = "InnerClasses";
+
+	public static final String ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS = "RuntimeVisibleAnnotations";
+
+	public static final String ATTRIBUTE_DEPRECATED = "Deprecated";
+
+	public static final String ATTRIBUTE_CONSTANT_VALUE = "ConstantValue";
+
+	public static final String ATTRIBUTE_ENCLOSING_METHOD = "EnclosingMethod";
+
+	public static final String ATTRIBUTE_EXCEPTIONS = "Exceptions";
+
+	public static final String ATTRIBUTE_SIGNATURE = "Signature";
+
 	public static final int CONTEXT_CODE = 1 << 4;
 
 	public static final int CONTEXT_CLASS = 1 << 0;
@@ -112,16 +148,53 @@
 		}
 	}
 
+	public Object getValue(long value, String type, Segment segment)
+			throws Pack200Exception {
+		// TODO This really needs to be better tested, esp. the different types
+		// TODO This should have the ability to deal with RUN stuff too, and unions
+		if (layout.startsWith("KQ")) {
+			if (type.equals("Ljava/lang/String;")) {
+				Object value2 = getValue("KS", value, segment);
+				return value2;
+			} else {
+				return getValue("K" + type + layout.substring(2), value,
+						segment);
+			}
+		} else {
+			return getValue(layout, value, segment);
+		}
+	}
+
 	public Object getValue(long value, Segment segment) throws Pack200Exception {
+		return getValue(layout, value, segment);
+	}
+
+	private static Object getValue(String layout, long value, Segment segment)
+			throws Pack200Exception {
+		SegmentConstantPool pool = segment.getConstantPool();
 		if (layout.startsWith("R")) {
 			// references
 			if (layout.indexOf('N') != -1)
 				value--;
-			SegmentConstantPool pool = segment.getConstantPool();
 			if (layout.startsWith("RU")) {
 				return pool.getValue(SegmentConstantPool.UTF_8, value);
 			} else if (layout.startsWith("RS")) {
 				return pool.getValue(SegmentConstantPool.SIGNATURE, value);
+			}
+		} else if (layout.startsWith("K")) {
+			char type = layout.charAt(1);
+			switch (type) {
+			case 'S': // String
+				return pool.getValue(SegmentConstantPool.CP_STRING, value);
+			case 'I': // Int (or byte or short)
+			case 'C': // Char
+				return pool.getValue(SegmentConstantPool.CP_INT, value);
+			case 'F': // Float
+				return pool.getValue(SegmentConstantPool.CP_FLOAT, value);
+			case 'J': // Long
+				return pool.getValue(SegmentConstantPool.CP_LONG,value);
+			case 'D': // Double
+				return pool.getValue(SegmentConstantPool.CP_DOUBLE,value);
 			}
 		}
 		throw new Pack200Exception("Unknown layout encoding: " + layout);

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayoutMap.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayoutMap.java?view=diff&rev=478907&r1=478906&r2=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayoutMap.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/AttributeLayoutMap.java Fri Nov 24 08:28:57 2006
@@ -27,61 +27,59 @@
  * internationalised, and should not be translated.
  */
 public class AttributeLayoutMap {
-	// private static final String METADATA = "[NH[(1)]][RSHNH[RUH(1)]][TB(66,67,73,83,90)[KIH](68)[KDH](70)[KFH](74)[KJH](99)[RSH](101)[RSHRUH](115)[RUH](91)[NH[(0)]](64)[RSH[RUH(0)]]()[]]";
-
 	// create a whole bunch of AttributeLayouts here
 	private static AttributeLayout[] getDefaultAttributeLayouts()
 			throws Pack200Exception {
 		return new AttributeLayout[] {
-				new AttributeLayout("LineNumberTable",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_LINE_NUMBER_TABLE,
 						AttributeLayout.CONTEXT_CODE, "NH[PHH]", 1),
-				new AttributeLayout("LocalVariableTable",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TABLE,
 						AttributeLayout.CONTEXT_CODE, "NH[PHOHRUHRSHH]", 2),
-				new AttributeLayout("LocalVariableTypeTable",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_LOCAL_VARIABLE_TYPE_TABLE,
 						AttributeLayout.CONTEXT_CODE, "NH[PHOHRUHRSHH]", 3),
-				new AttributeLayout("SourceFile",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_SOURCE_FILE,
 						AttributeLayout.CONTEXT_CLASS, "RUNH", 17),
-				new AttributeLayout("ConstantValue",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_CONSTANT_VALUE,
 						AttributeLayout.CONTEXT_FIELD, "KQH", 17),
-				new AttributeLayout("Code", AttributeLayout.CONTEXT_METHOD,
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_CODE, AttributeLayout.CONTEXT_METHOD,
 						"*", 17),
-				new AttributeLayout("EnclosingMethod",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_ENCLOSING_METHOD,
 						AttributeLayout.CONTEXT_CLASS, "RCHRDNH", 18),
-				new AttributeLayout("Exceptions",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_EXCEPTIONS,
 						AttributeLayout.CONTEXT_METHOD, "NH[RCH]", 18),
-				new AttributeLayout("Signature", AttributeLayout.CONTEXT_CLASS,
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE, AttributeLayout.CONTEXT_CLASS,
 						"RSH", 19),
-				new AttributeLayout("Signature", AttributeLayout.CONTEXT_FIELD,
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE, AttributeLayout.CONTEXT_FIELD,
 						"RSH", 19),
-				new AttributeLayout("Signature",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_SIGNATURE,
 						AttributeLayout.CONTEXT_METHOD, "RSH", 19),
-				new AttributeLayout("Deprecated",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_DEPRECATED,
 						AttributeLayout.CONTEXT_CLASS, "", 20),
-				new AttributeLayout("Deprecated",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_DEPRECATED,
 						AttributeLayout.CONTEXT_FIELD, "", 20),
-				new AttributeLayout("Deprecated",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_DEPRECATED,
 						AttributeLayout.CONTEXT_METHOD, "", 20),
-				new AttributeLayout("RuntimeVisibleAnnotations",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS,
 						AttributeLayout.CONTEXT_CLASS, "*", 21),
-				new AttributeLayout("RuntimeVisibleAnnotations",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS,
 						AttributeLayout.CONTEXT_FIELD, "*", 21),
-				new AttributeLayout("RuntimeVisibleAnnotations",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS,
 						AttributeLayout.CONTEXT_METHOD, "*", 21),
-				new AttributeLayout("RuntimeInvisibleAnnotations",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS,
 						AttributeLayout.CONTEXT_CLASS, "*", 22),
-				new AttributeLayout("RuntimeInvisibleAnnotations",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS,
 						AttributeLayout.CONTEXT_FIELD, "*", 22),
-				new AttributeLayout("RuntimeInvisibleAnnotations",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS,
 						AttributeLayout.CONTEXT_METHOD, "*", 22),
-				new AttributeLayout("InnerClasses",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_INNER_CLASSES,
 						AttributeLayout.CONTEXT_CLASS, "*", 23),
-				new AttributeLayout("RuntimeVisibleParameterAnnotations",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS,
 						AttributeLayout.CONTEXT_METHOD, "*", 23),
-				new AttributeLayout("class-file version",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_CLASS_FILE_VERSION,
 						AttributeLayout.CONTEXT_CLASS, "*", 24),
-				new AttributeLayout("RuntimeInvisibleParameterAnnotations",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS,
 						AttributeLayout.CONTEXT_METHOD, "*", 24),
-				new AttributeLayout("AnnotationDefault",
+				new AttributeLayout(AttributeLayout.ATTRIBUTE_ANNOTATION_DEFAULT,
 						AttributeLayout.CONTEXT_METHOD, "*", 25) };
 	}
 

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Pack200PackerAdapter.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Pack200PackerAdapter.java?view=diff&rev=478907&r1=478906&r2=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Pack200PackerAdapter.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Pack200PackerAdapter.java Fri Nov 24 08:28:57 2006
@@ -18,10 +18,8 @@
 //NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
 //NOTE: Do not extract strings as messages; this code is still a work-in-progress
 //NOTE: Also, don't get rid of 'else' statements for the hell of it ...
-import java.beans.PropertyChangeListener;
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.SortedMap;
 import java.util.jar.JarFile;
 import java.util.jar.JarInputStream;
 import java.util.jar.Pack200.Packer;

Modified: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Segment.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Segment.java?view=diff&rev=478907&r1=478906&r2=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Segment.java (original)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/Segment.java Fri Nov 24 08:28:57 2006
@@ -15,20 +15,32 @@
  *  limitations under the License.
  */
 package org.apache.harmony.archive.internal.pack200;
-//NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
-//NOTE: Do not extract strings as messages; this code is still a work-in-progress
-//NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+
+// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
+// NOTE: Do not extract strings as messages; this code is still a
+// work-in-progress
+// NOTE: Also, don't get rid of 'else' statements for the hell of it ...
 import java.io.ByteArrayInputStream;
 import java.io.DataOutputStream;
 import java.io.EOFException;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.jar.JarEntry;
 import java.util.jar.JarOutputStream;
 import java.util.zip.GZIPInputStream;
 
-import org.apache.harmony.archive.internal.pack200.ClassFileEntry.SourceFile;
+import org.apache.harmony.archive.internal.pack200.bytecode.Attribute;
+import org.apache.harmony.archive.internal.pack200.bytecode.CPClass;
+import org.apache.harmony.archive.internal.pack200.bytecode.CPField;
+import org.apache.harmony.archive.internal.pack200.bytecode.CPMethod;
+import org.apache.harmony.archive.internal.pack200.bytecode.ClassConstantPool;
+import org.apache.harmony.archive.internal.pack200.bytecode.ClassFile;
+import org.apache.harmony.archive.internal.pack200.bytecode.ClassFileEntry;
+import org.apache.harmony.archive.internal.pack200.bytecode.ConstantValueAttribute;
+import org.apache.harmony.archive.internal.pack200.bytecode.ExceptionsAttribute;
+import org.apache.harmony.archive.internal.pack200.bytecode.SourceFileAttribute;
 
 /**
  * A Pack200 archive consists of one (or more) segments. Each segment is
@@ -65,23 +77,46 @@
 	public class SegmentConstantPool {
 		public static final int ALL = 0;
 
+		public static final int CP_DOUBLE = 7;
+
+		// define in archive order
+
+		public static final int CP_FLOAT = 4; // TODO Check this
+
+		public static final int CP_INT = 3;
+
+		public static final int CP_LONG = 6;
+
+		public static final int CP_STRING = 5;
+
 		public static final int SIGNATURE = 2; // TODO and more to come --
-												// define in archive order
 
 		public static final int UTF_8 = 1;
 
 		public Object getValue(int cp, long value) throws Pack200Exception {
-			int index = (int)value;
-			if (index == -1)
+			int index = (int) value;
+			if (index == -1) {
 				return null;
-			if (index < 0)
+			} else if (index < 0) {
 				throw new Pack200Exception("Cannot have a negative range");
-			if (cp == UTF_8)
+			} else if (cp == UTF_8) {
 				return cpUTF8[index];
-			if (cp == SIGNATURE)
+			} else if (cp == CP_STRING) {
+				return cpString[index];
+			} else if (cp == SIGNATURE) {
 				return cpSignature[index];
-			// etc
-			throw new Error("Get value incomplete");
+			} else if (cp == CP_INT) {
+				return new Integer(cpInt[index]);
+			} else if (cp == CP_FLOAT) {
+				return new Float(cpFloat[index]);
+			} else if (cp == CP_DOUBLE) {
+				return new Double(cpDouble[index]);
+			} else if (cp == CP_LONG) {
+				return new Long(cpLong[index]);
+			} else {
+				// etc
+				throw new Error("Get value incomplete");
+			}
 		}
 	}
 
@@ -144,6 +179,10 @@
 		}
 	}
 
+	private int archiveMajor;
+
+	private int archiveMinor;
+
 	private long archiveModtime;
 
 	private long archiveSize;
@@ -238,6 +277,8 @@
 
 	private int fieldAttrCount;
 
+	private ArrayList[][] fieldAttributes;
+
 	private String[][] fieldDescr;
 
 	private long[][] fieldFlags;
@@ -262,15 +303,15 @@
 
 	private int innerClassCount;
 
-	private int archiveMajor;
-
 	private int methodAttrCount;
 
+	private ArrayList[][] methodAttributes;
+
 	private String[][] methodDescr;
 
-	private long[][] methodFlags;
+	private ExceptionsAttribute[][] methodExceptions;
 
-	private int archiveMinor;
+	private long[][] methodFlags;
 
 	private int numberOfFiles;
 
@@ -280,6 +321,68 @@
 
 	private int segmentsRemaining;
 
+	private ClassFile buildClassFile(int classNum) {
+		ClassFile classFile = new ClassFile();
+		classFile.major = defaultClassMajorVersion; // TODO If
+		// classVersionMajor[] use
+		// that instead
+		classFile.minor = defaultClassMinorVersion; // TODO if
+		// classVersionMinor[] use
+		// that instead
+		// build constant pool
+		ClassConstantPool cp = classFile.pool;
+		String fullName = classThis[classNum];
+		// SourceFile attribute
+		int i = fullName.lastIndexOf("/") + 1; // if lastIndexOf==-1, then
+		// -1+1=0, so str.substring(0)
+		// == str
+		String fileName = fullName.substring(i) + ".java";
+		classFile.attributes = new Attribute[] { (Attribute) cp
+				.add(new SourceFileAttribute(fileName)) };
+		// this/superclass
+		ClassFileEntry cfThis = cp.add(new CPClass(fullName));
+		ClassFileEntry cfSuper = cp.add(new CPClass(classSuper[classNum]));
+		// add interfaces
+		ClassFileEntry cfInterfaces[] = new ClassFileEntry[classInterfaces[classNum].length];
+		for (i = 0; i < cfInterfaces.length; i++) {
+			cfInterfaces[i] = cp.add(new CPClass(classInterfaces[classNum][i]));
+		}
+		// add fields
+		ClassFileEntry cfFields[] = new ClassFileEntry[classFieldCount[classNum]];
+		// fieldDescr and fieldFlags used to create this
+		for (i = 0; i < cfFields.length; i++) {
+			cfFields[i] = cp.add(new CPField(fieldDescr[classNum][i],
+					fieldFlags[classNum][i], fieldAttributes[classNum][i]));
+		}
+		// add methods
+		ClassFileEntry cfMethods[] = new ClassFileEntry[classMethodCount[classNum]];
+		// fieldDescr and fieldFlags used to create this
+		for (i = 0; i < cfMethods.length; i++) {
+			cfMethods[i] = cp.add(new CPMethod(methodDescr[classNum][i],
+					methodFlags[classNum][i], methodAttributes[classNum][i]));
+		}
+		// sort CP according to cp_All
+		cp.resolve();
+		// print out entries
+		debug("Constant pool looks like:");
+		for (i = 1; i <= cp.size(); i++) {
+			debug(String.valueOf(i) + ":" + String.valueOf(cp.get(i)));
+		}
+		// NOTE the indexOf is only valid after the cp.resolve()
+		// build up remainder of file
+		classFile.accessFlags = (int) classFlags[classNum];
+		classFile.thisClass = cp.indexOf(cfThis);
+		classFile.superClass = cp.indexOf(cfSuper);
+		// TODO placate format of file for writing purposes
+		classFile.interfaces = new int[cfInterfaces.length];
+		for (i = 0; i < cfInterfaces.length; i++) {
+			classFile.interfaces[i] = cp.indexOf(cfInterfaces[i]);
+		}
+		classFile.fields = cfFields;
+		classFile.methods = cfMethods;
+		return classFile;
+	}
+
 	/**
 	 * This is a local debugging message to aid the developer in writing this
 	 * class. It will be removed before going into production. If the property
@@ -462,89 +565,6 @@
 	public int getNumberOfFiles() {
 		return numberOfFiles;
 	}
-	/**
-	 * Writes the segment to an output stream. The output stream should be pre-buffered for
-	 * efficiency. Also takes the same input stream for reading, since the file bits may
-	 * not be loaded and thus just copied from one stream to another.
-	 * Doesn't close the output stream when finished, in case there are more entries (e.g.
-	 * further segments) to be written.
-	 * @param out the JarOutputStream to write data to
-	 * @param in the same InputStream that was used to parse the segment
-	 * @throws IOException if an error occurs whilst reading or writing to the streams
-	 * @throws Pack200Exception if an error occurs whilst unpacking data
-	 */
-	public void writeJar(JarOutputStream out, InputStream in ) throws IOException, Pack200Exception {
-		processFileBits(in);
-		DataOutputStream dos = new DataOutputStream(out);
-		// out.setLevel(JarEntry.DEFLATED)
-		// now write the files out
-		int classNum = 0;
-		for(int i=0;i<numberOfFiles;i++) {
-			String name = fileName[i];
-			long modtime = archiveModtime + fileModtime[i];
-			boolean deflate = (fileOptions[i] & 1) == 1 || options.shouldDeflate(); 
-			boolean isClass = (fileOptions[i] & 2) == 2  || name == null || name.equals("");
-			if (isClass) {
-				// pull from headers
-				if (name == null || name.equals(""))
-					name = cpClass[classNum] + ".class";				
-			};
-			JarEntry entry = new JarEntry(name);
-			if (deflate)
-				entry.setMethod(JarEntry.DEFLATED);
-			entry.setTime(modtime);
-			out.putNextEntry(entry);
-			
-			if(isClass){
-				// write to dos
-				ClassFile classFile = buildClassFile(classNum);
-				classFile.write(dos);
-				dos.flush();
-				classNum++;
-			} else {
-				long size = fileSize[i];
-				entry.setSize(size);
-				// TODO pull from in
-				byte[] data = fileBits[i];
-				out.write(data);
-			}
-		}
-		dos.flush();
-		out.finish();
-		out.flush();
-	}
-
-	private ClassFile buildClassFile(int classNum) {
-		ClassFile classFile = new ClassFile();
-		classFile.major = defaultClassMajorVersion; // TODO If classVersionMajor[] use that instead
-		classFile.minor = defaultClassMinorVersion; // TODO if classVersionMinor[] use that instead
-		// build constant pool
-		ClassFileEntry cfThis = new ConstantPoolEntry.Class(classThis[classNum]);
-		ClassFileEntry cfSuper = new ConstantPoolEntry.Class(classSuper[classNum]);
-		ClassFileEntry cfInterfaces[] = new ClassFileEntry[classInterfaces[classNum].length];
-		for(int i=0;i<cfInterfaces.length;i++) {
-			cfInterfaces[i] = new ConstantPoolEntry.Class(classInterfaces[classNum][i]);
-		}
-		ClassConstantPool cp = classFile.pool;
-		cp.add(cfThis);
-		cp.add(cfSuper);
-		// build up remainder of file
-		classFile.accessFlags = (int) classFlags[classNum];
-		classFile.thisClass = cp.indexOf(cfThis);
-		classFile.superClass = cp.indexOf(cfSuper);
-		// TODO placate format of file for writing purposes
-		classFile.interfaces = new int[0];
-		classFile.fields = new int[0];
-		classFile.methods = new int[0];
-		SourceFile sf;
-		classFile.attributes = new ClassFileEntry.Attribute[] { sf = new ClassFileEntry.SourceFile(classThis[classNum]  + ".java") };
-		cp.add(sf);
-
-		// sort CP according to cp_All
-		cp.resolve();
-
-		return classFile;
-	}
 
 	private SegmentOptions getOptions() {
 		return options;
@@ -605,6 +625,75 @@
 		attributeDefinitionMap = new AttributeLayoutMap();
 	}
 
+	/**
+	 * @param in
+	 * @throws Pack200Exception
+	 * @throws IOException
+	 */
+	private void parseAttributeMethodExceptions(InputStream in)
+			throws Pack200Exception, IOException {
+		// TODO Should refactor this stuff into the layout somehow
+		AttributeLayout layout = attributeDefinitionMap.getAttributeLayout(
+				"Exceptions", AttributeLayout.CONTEXT_METHOD);
+		Codec codec = layout.getCodec();
+		methodExceptions = new ExceptionsAttribute[classCount][];
+		int[][] numExceptions = new int[classCount][];
+		for (int i = 0; i < classCount; i++) {
+			numExceptions[i] = new int[methodFlags[i].length];
+			for (int j = 0; j < methodFlags[i].length; j++) {
+				long flag = methodFlags[i][j];
+				if (layout.matches(flag)) {
+					numExceptions[i][j] = (int) codec.decode(in);
+				}
+			}
+		}
+		for (int i = 0; i < classCount; i++) {
+			methodExceptions[i] = new ExceptionsAttribute[methodFlags[i].length];
+			for (int j = 0; j < methodFlags[i].length; j++) {
+				long flag = methodFlags[i][j];
+				int n = numExceptions[i][j];
+				CPClass[] exceptions = new CPClass[n];
+				if (layout.matches(flag)) {
+					for (int k = 0; k < n; k++) {
+						long result = codec.decode(in);
+						exceptions[k] = new CPClass(cpClass[(int) result]);
+					}
+				}
+				methodExceptions[i][j] = new ExceptionsAttribute(exceptions);
+				methodAttributes[i][j].add(methodExceptions[i][j]);
+			}
+		}
+	}
+
+	/**
+	 * @param in
+	 * 
+	 */
+	private void parseAttributeMethodSignature(InputStream in)
+			throws Pack200Exception, IOException {
+		parseAttributeUnknown(AttributeLayout.ATTRIBUTE_SIGNATURE,
+				AttributeLayout.CONTEXT_METHOD, methodFlags);
+	}
+
+	/**
+	 * @param name
+	 * @param flags
+	 * @throws Pack200Exception
+	 */
+	private void parseAttributeUnknown(String name, int context, long[][] flags)
+			throws Pack200Exception {
+		debug("Parsing unknown attributes for " + name);
+		AttributeLayout layout = attributeDefinitionMap.getAttributeLayout(
+				name, context);
+		for (int i = 0; i < flags.length; i++) {
+			for (int j = 0; j < flags[i].length; j++) {
+				if (layout.matches(flags[i][j]))
+					throw new Error("We've got data for " + name
+							+ " and we don't know what to do with it (yet)");
+			}
+		}
+	}
+
 	private void parseBcBands(InputStream in) {
 		debug("Unimplemented bc_bands");
 	}
@@ -625,17 +714,19 @@
 		debug("unimplemented class_attr_indexes");
 		debug("unimplemented class_attr_calls");
 		AttributeLayout layout = attributeDefinitionMap.getAttributeLayout(
-				"SourceFile", AttributeLayout.CONTEXT_CLASS);
+				AttributeLayout.ATTRIBUTE_SOURCE_FILE,
+				AttributeLayout.CONTEXT_CLASS);
 		for (int i = 0; i < classCount; i++) {
 			long flag = classFlags[i];
 			if (layout.matches(flag)) {
 				// we've got a value to read
+				// TODO File this as a sourcefile attribute and don't generate
+				// everything below
 				long result = layout.getCodec().decode(in);
 				Object value = layout.getValue(result, this);
-				debug("Processed value " + value + " for SourceFile"); 
+				debug("Processed value " + value + " for SourceFile");
 			}
 		}
-		debug("unimplemented class_SourceFile_RUN");
 		debug("unimplemented class_EnclosingMethod_RC");
 		debug("unimplemented class_EnclosingMethod_RDN");
 		debug("unimplemented class_Signature_RS");
@@ -658,10 +749,10 @@
 		classInterfaces = new String[classCount][];
 		int[] classInterfaceLengths = decodeBandInt("class_interface_count",
 				in, Codec.DELTA5, classCount);
-		for (int i = 0; i < classCount; i++) {
-			classInterfaces[i] = parseReferences("class_interface", in,
-					Codec.DELTA5, classInterfaceLengths[i], cpClass);
-		}
+		// for (int i = 0; i < classCount; i++) {
+		classInterfaces = parseReferences("class_interface", in, Codec.DELTA5,
+				classCount, classInterfaceLengths, cpClass);
+		// }
 		classFieldCount = decodeBandInt("class_field_count", in, Codec.DELTA5,
 				classCount);
 		classMethodCount = decodeBandInt("class_method_count", in,
@@ -702,7 +793,22 @@
 		}
 	}
 
-	private void parseCodeBands(InputStream in) {
+	private void parseCodeBands(InputStream in) throws Pack200Exception {
+		// look through each method
+		int codeBands = 0;
+		AttributeLayout layout = attributeDefinitionMap.getAttributeLayout(
+				AttributeLayout.ATTRIBUTE_CODE,
+				AttributeLayout.CONTEXT_METHOD);
+
+		for (int i = 0; i < classCount; i++) {
+			for (int j = 0; j < methodFlags[i].length; j++) {
+				long flag = methodFlags[i][j];
+				if (layout.matches(flag)) 
+					codeBands++;
+			}
+		}
+		if (codeBands > 0)
+			throw new Error("Can't handle non-abstract, non-native methods/initialisers at the moment (found " + codeBands + " code bands)");
 		debug("unimplemented code_headers");
 		debug("unimplemented code_max_stack");
 		debug("unimplemented code_max_na_locals");
@@ -855,8 +961,8 @@
 
 	private void parseCpLong(InputStream in) throws IOException,
 			Pack200Exception {
-		cpLong = parseFlags("cp_Long", in, cpLongCount, Codec.UDELTA5,
-				Codec.DELTA5);
+		cpLong = parseFlags("cp_Long", in, cpLongCount, new int[] { 1 },
+				Codec.UDELTA5, Codec.DELTA5)[0];
 	}
 
 	/**
@@ -1015,16 +1121,10 @@
 
 	private void parseFieldBands(InputStream in) throws IOException,
 			Pack200Exception {
-		fieldDescr = new String[classCount][];
-		for (int i = 0; i < classCount; i++) {
-			fieldDescr[i] = parseReferences("field_descr", in, Codec.DELTA5,
-					classFieldCount[i], cpDescriptor);
-		}
-		fieldFlags = new long[classCount][];
-		for (int i = 0; i < classCount; i++) {
-			fieldFlags[i] = parseFlags("field_flags", in, classFieldCount[i],
-					Codec.UNSIGNED5, options.hasFieldFlagsHi());
-		}
+		fieldDescr = parseReferences("field_descr", in, Codec.DELTA5,
+				classCount, classFieldCount, cpDescriptor);
+		fieldFlags = parseFlags("field_flags", in, classCount, classFieldCount,
+				Codec.UNSIGNED5, options.hasFieldFlagsHi());
 		for (int i = 0; i < classCount; i++) {
 			for (int j = 0; j < fieldFlags[i].length; j++) {
 				long flag = fieldFlags[i][j];
@@ -1037,7 +1137,33 @@
 					"There are attribute flags, and I don't know what to do with them");
 		debug("unimplemented field_attr_indexes");
 		debug("unimplemented field_attr_calls");
-		debug("unimplemented field_ConstantValueKQ");
+		AttributeLayout layout = attributeDefinitionMap.getAttributeLayout(
+				"ConstantValue", AttributeLayout.CONTEXT_FIELD);
+		Codec codec = layout.getCodec();
+		fieldAttributes = new ArrayList[classCount][];
+		for (int i = 0; i < classCount; i++) {
+			fieldAttributes[i] = new ArrayList[fieldFlags[i].length];
+			for (int j = 0; j < fieldFlags[i].length; j++) {
+				fieldAttributes[i][j] = new ArrayList();
+				long flag = fieldFlags[i][j];
+				if (layout.matches(flag)) {
+					// we've got a value to read
+					long result = codec.decode(in);
+					String desc = fieldDescr[i][j];
+					int colon = desc.indexOf(':');
+					// String name = desc.substring(0, colon);
+					String type = desc.substring(colon + 1);
+					// TODO Got to get better at this ... in any case, it should
+					// be e.g. KIB or KIH
+					if (type.equals("B") || type.equals("H"))
+						type = "I";
+					Object value = layout.getValue(result, type, this);
+					fieldAttributes[i][j]
+							.add(new ConstantValueAttribute(value));
+					debug("Processed value " + value + " for ConstantValue");
+				}
+			}
+		}
 		debug("unimplemented field_Signature_RS");
 		parseMetadataBands("field");
 	}
@@ -1060,6 +1186,15 @@
 	 */
 	private void parseFileBands(InputStream in) throws IOException,
 			Pack200Exception {
+		if (false && System.getProperty("debug.pack200") != null) {
+			// TODO HACK
+			fileSize = new long[numberOfFiles];
+			fileModtime = new long[numberOfFiles];
+			fileOptions = new long[numberOfFiles];
+			fileName = new String[numberOfFiles];
+			Arrays.fill(fileName, "");
+			return;
+		}
 		long last;
 		fileName = parseReferences("file_name", in, Codec.UNSIGNED5,
 				numberOfFiles, cpUTF8);
@@ -1091,28 +1226,43 @@
 	}
 
 	private long[] parseFlags(String name, InputStream in, int count,
-			Codec codec) throws IOException, Pack200Exception {
-		return parseFlags(name, in, count, codec, true);
+			Codec codec, boolean hasHi) throws IOException, Pack200Exception {
+		return parseFlags(name, in, 1, new int[] { count }, (hasHi ? codec
+				: null), codec)[0];
 	}
 
-	private long[] parseFlags(String name, InputStream in, int count,
-			Codec codec, boolean hasHi) throws IOException, Pack200Exception {
-		return parseFlags(name, in, count, (hasHi ? codec : null), codec);
+	private long[][] parseFlags(String name, InputStream in, int count,
+			int counts[], Codec codec, boolean hasHi) throws IOException,
+			Pack200Exception {
+		return parseFlags(name, in, count, counts, (hasHi ? codec : null),
+				codec);
 	}
 
-	private long[] parseFlags(String name, InputStream in, int count,
-			Codec hiCodec, Codec loCodec) throws IOException, Pack200Exception {
-		long[] result = new long[count];
-		// TODO Refactor into band parsing
-		long last = 0;
-		for (int i = 0; i < count && hiCodec != null; i++) {
-			last = hiCodec.decode(in, last);
-			result[i] = last << 32;
+	private long[][] parseFlags(String name, InputStream in, int count,
+			int counts[], Codec hiCodec, Codec loCodec) throws IOException,
+			Pack200Exception {
+		// TODO Move away from decoding into a parseBand type structure
+		if (count == 0) {
+			return new long[][] { {} };
 		}
-		for (int i = 0; i < count; i++) {
-			last = loCodec.decode(in, last);
-			result[i] = result[i] | last;
+		long[][] result = new long[count][];
+		// TODO What happens when the decode here indicates a different
+		// encoding?
+		// TODO Move this to a decodeBandInt
+		long last = 0;
+		for (int j = 0; j < count; j++) {
+			result[j] = new long[counts[j]];
+			for (int i = 0; i < counts[j] && hiCodec != null; i++) {
+				last = hiCodec.decode(in, last);
+				result[j][i] = last << 32;
+			}
 		}
+		last = 0;
+		for (int j = 0; j < count; j++)
+			for (int i = 0; i < counts[j]; i++) {
+				last = loCodec.decode(in, last);
+				result[j][i] = result[j][i] | last;
+			}
 		// TODO Remove debugging code
 		debug("Parsed *" + name + " (" + result.length + ")");
 		return result;
@@ -1175,17 +1325,10 @@
 
 	private void parseMethodBands(InputStream in) throws IOException,
 			Pack200Exception {
-		methodDescr = new String[classCount][];
-		for (int i = 0; i < classCount; i++) {
-			methodDescr[i] = parseReferences("method_descr", in, Codec.MDELTA5,
-					classMethodCount[i], cpDescriptor);
-		}
-		methodFlags = new long[classCount][];
-		for (int i = 0; i < classCount; i++) {
-			methodFlags[i] = parseFlags("method_flags", in,
-					classMethodCount[i], Codec.UNSIGNED5, options
-							.hasMethodFlagsHi());
-		}
+		methodDescr = parseReferences("method_descr", in, Codec.MDELTA5,
+				classCount, classMethodCount, cpDescriptor);
+		methodFlags = parseFlags("method_flags", in, classCount,
+				classMethodCount, Codec.UNSIGNED5, options.hasMethodFlagsHi());
 		for (int i = 0; i < classCount; i++) {
 			for (int j = 0; j < methodFlags[i].length; j++) {
 				long flag = methodFlags[i][j];
@@ -1199,9 +1342,16 @@
 		debug("unimplemented method_attr_count");
 		debug("unimplemented method_attr_indexes");
 		debug("unimplemented method_attr_calls");
-		debug("unimplemented method_Exceptions_N");
-		debug("unimplemented method_Exceptions_RC");
-		debug("unimplemented method_Signature_RS");
+		// assign empty method attributes
+		methodAttributes = new ArrayList[classCount][];
+		for (int i = 0; i < classCount; i++) {
+			methodAttributes[i] = new ArrayList[methodFlags[i].length];
+			for (int j = 0; j < methodFlags[i].length; j++) {
+				methodAttributes[i][j] = new ArrayList();
+			}
+		}
+		parseAttributeMethodExceptions(in);
+		parseAttributeMethodSignature(in);
 		parseMetadataBands("method");
 	}
 
@@ -1210,7 +1360,8 @@
 	 * using <code>codec</code> to decode the values as indexes into
 	 * <code>reference</code> (which is populated prior to this call). An
 	 * exception is thrown if a decoded index falls outside the range
-	 * [0..reference.length-1].
+	 * [0..reference.length-1]. Unlike the other parseReferences, this
+	 * post-processes the result into an array of results.
 	 * 
 	 * @param name
 	 *            TODO
@@ -1230,22 +1381,73 @@
 	 *             if a problem occurs with an unexpected value or unsupported
 	 *             codec
 	 */
-	private String[] parseReferences(String name, InputStream in,
-			BHSDCodec codec, int count, String[] reference) throws IOException,
-			Pack200Exception {
-		String[] result = new String[count];
-		int[] decode = decodeBandInt(name, in, codec, count);
+	private String[][] parseReferences(String name, InputStream in,
+			BHSDCodec codec, int count, int counts[], String[] reference)
+			throws IOException, Pack200Exception {
+		if (count == 0) {
+			return new String[][] { {} };
+		}
+		String[][] result = new String[count][];
+		int sum = 0;
 		for (int i = 0; i < count; i++) {
-			int index = decode[i];
+			result[i] = new String[counts[i]];
+			sum += counts[i];
+		}
+		// TODO Merge the decode and parsing of a multiple structure into one
+		String[] result1 = new String[sum];
+		int[] decode = decodeBandInt(name, in, codec, sum);
+		for (int i1 = 0; i1 < sum; i1++) {
+			int index = decode[i1];
 			if (index < 0 || index >= reference.length)
 				throw new Pack200Exception(
 						"Something has gone wrong during parsing references");
-			result[i] = reference[index];
+			result1[i1] = reference[index];
+		}
+		String[] refs = result1;
+		// TODO Merge the decode and parsing of a multiple structure into one
+		int pos = 0;
+		for (int i = 0; i < count; i++) {
+			int num = counts[i];
+			result[i] = new String[num];
+			System.arraycopy(refs, pos, result[i], 0, num);
+			pos += num;
 		}
 		return result;
 	}
 
 	/**
+	 * Helper method to parse <i>count</i> references from <code>in</code>,
+	 * using <code>codec</code> to decode the values as indexes into
+	 * <code>reference</code> (which is populated prior to this call). An
+	 * exception is thrown if a decoded index falls outside the range
+	 * [0..reference.length-1].
+	 * 
+	 * @param name
+	 *            TODO
+	 * @param in
+	 *            the input stream to read from
+	 * @param codec
+	 *            the codec to use for decoding
+	 * @param count
+	 *            the number of references to decode
+	 * @param reference
+	 *            the array of values to use for the indexes; often
+	 *            {@link #cpUTF8}
+	 * 
+	 * @throws IOException
+	 *             if a problem occurs during reading from the underlying stream
+	 * @throws Pack200Exception
+	 *             if a problem occurs with an unexpected value or unsupported
+	 *             codec
+	 */
+	private String[] parseReferences(String name, InputStream in,
+			BHSDCodec codec, int count, String[] reference) throws IOException,
+			Pack200Exception {
+		return parseReferences(name, in, codec, 1, new int[] { count },
+				reference)[0];
+	}
+
+	/**
 	 * This performs the actual work of parsing against a non-static instance of
 	 * Segment.
 	 * 
@@ -1282,7 +1484,6 @@
 		parseIcBands(in);
 		parseClassBands(in);
 		parseBcBands(in);
-		// TODO Re-enable these after completing class/bytecode bands
 		parseFileBands(in);
 	}
 
@@ -1321,6 +1522,34 @@
 		}
 	}
 
+	/**
+	 * Sets the major version of this archive.
+	 * 
+	 * @param version
+	 *            the minor version of the archive
+	 * @throws Pack200Exception
+	 *             if the major version is not 150
+	 */
+	private void setArchiveMajorVersion(int version) throws Pack200Exception {
+		if (version != 150)
+			throw new Pack200Exception("Invalid segment major version");
+		archiveMajor = version;
+	}
+
+	/**
+	 * Sets the minor version of this archive
+	 * 
+	 * @param version
+	 *            the minor version of the archive
+	 * @throws Pack200Exception
+	 *             if the minor version is not 7
+	 */
+	private void setArchiveMinorVersion(int version) throws Pack200Exception {
+		if (version != 7)
+			throw new Pack200Exception("Invalid segment minor version");
+		archiveMinor = version;
+	}
+
 	public void setArchiveModtime(long archiveModtime) {
 		this.archiveModtime = archiveModtime;
 	}
@@ -1405,34 +1634,6 @@
 		innerClassCount = (int) value;
 	}
 
-	/**
-	 * Sets the major version of this archive.
-	 * 
-	 * @param version
-	 *            the minor version of the archive
-	 * @throws Pack200Exception
-	 *             if the major version is not 150
-	 */
-	private void setArchiveMajorVersion(int version) throws Pack200Exception {
-		if (version != 150)
-			throw new Pack200Exception("Invalid segment major version");
-		archiveMajor = version;
-	}
-
-	/**
-	 * Sets the minor version of this archive
-	 * 
-	 * @param version
-	 *            the minor version of the archive
-	 * @throws Pack200Exception
-	 *             if the minor version is not 7
-	 */
-	private void setArchiveMinorVersion(int version) throws Pack200Exception {
-		if (version != 7)
-			throw new Pack200Exception("Invalid segment minor version");
-		archiveMinor = version;
-	}
-
 	public void setNumberOfFiles(long value) {
 		numberOfFiles = (int) value;
 	}
@@ -1443,5 +1644,79 @@
 
 	public void setSegmentsRemaining(long value) {
 		segmentsRemaining = (int) value;
+	}
+
+	/**
+	 * This is only here to provide a mechanism to turn off the warnings (and to
+	 * prevent anyone from accidentally removing them from the file)
+	 * 
+	 * @deprecated this will be deleted in the future, once I've started to use
+	 *             them
+	 * 
+	 */
+	int shutUpAboutTheStupidNotReadVariablesYetIHaventImplementedIt() {
+		return archiveMajor + archiveMinor + cpLong.hashCode()
+				+ icName.hashCode() + icOuterClass.hashCode()
+				+ icThisClass.hashCode();
+	}
+
+	/**
+	 * Writes the segment to an output stream. The output stream should be
+	 * pre-buffered for efficiency. Also takes the same input stream for
+	 * reading, since the file bits may not be loaded and thus just copied from
+	 * one stream to another. Doesn't close the output stream when finished, in
+	 * case there are more entries (e.g. further segments) to be written.
+	 * 
+	 * @param out
+	 *            the JarOutputStream to write data to
+	 * @param in
+	 *            the same InputStream that was used to parse the segment
+	 * @throws IOException
+	 *             if an error occurs whilst reading or writing to the streams
+	 * @throws Pack200Exception
+	 *             if an error occurs whilst unpacking data
+	 */
+	public void writeJar(JarOutputStream out, InputStream in)
+			throws IOException, Pack200Exception {
+		processFileBits(in);
+		DataOutputStream dos = new DataOutputStream(out);
+		// out.setLevel(JarEntry.DEFLATED)
+		// now write the files out
+		int classNum = 0;
+		for (int i = 0; i < numberOfFiles; i++) {
+			String name = fileName[i];
+			long modtime = archiveModtime + fileModtime[i];
+			boolean deflate = (fileOptions[i] & 1) == 1
+					|| options.shouldDeflate();
+			boolean isClass = (fileOptions[i] & 2) == 2 || name == null
+					|| name.equals("");
+			if (isClass) {
+				// pull from headers
+				if (name == null || name.equals(""))
+					name = classThis[classNum] + ".class";
+			}
+			JarEntry entry = new JarEntry(name);
+			if (deflate)
+				entry.setMethod(JarEntry.DEFLATED);
+			entry.setTime(modtime);
+			out.putNextEntry(entry);
+
+			if (isClass) {
+				// write to dos
+				ClassFile classFile = buildClassFile(classNum);
+				classFile.write(dos);
+				dos.flush();
+				classNum++;
+			} else {
+				long size = fileSize[i];
+				entry.setSize(size);
+				// TODO pull from in
+				byte[] data = fileBits[i];
+				out.write(data);
+			}
+		}
+		dos.flush();
+		out.finish();
+		out.flush();
 	}
 }

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/Attribute.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/Attribute.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/Attribute.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/Attribute.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,78 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+
+public abstract class Attribute extends ClassFileEntry {
+	private CPUTF8 attributeName;
+
+	private int attributeNameIndex;
+
+	public Attribute(String attributeName) {
+		this.attributeName = new CPUTF8(attributeName);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (this.getClass() != obj.getClass())
+			return false;
+		final Attribute other = (Attribute) obj;
+		if (attributeName == null) {
+			if (other.attributeName != null)
+				return false;
+		} else if (!attributeName.equals(other.attributeName))
+			return false;
+		return true;
+	}
+
+	protected CPUTF8 getAttributeName() {
+		return attributeName;
+	}
+
+	protected abstract int getLength();
+
+	@Override
+	public int hashCode() {
+		final int PRIME = 31;
+		int result = 1;
+		result = PRIME * result
+				+ ((attributeName == null) ? 0 : attributeName.hashCode());
+		return result;
+	}
+
+	protected void resolve(ClassConstantPool pool) {
+		super.resolve(pool);
+		attributeNameIndex = pool.indexOf(attributeName);
+	}
+
+	protected void doWrite(DataOutputStream dos) throws IOException {
+		dos.writeShort(attributeNameIndex);
+		dos.writeInt(getLength());
+		writeBody(dos);
+	}
+
+	protected abstract void writeBody(DataOutputStream dos)
+			throws IOException;
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPClass.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPClass.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPClass.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPClass.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,83 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+
+public class CPClass extends ConstantPoolEntry {
+	private int index;
+
+	public String name;
+
+	private CPUTF8 utf8;
+
+	public   CPClass(String name) {
+		super(ConstantPoolEntry.CP_Class);
+		this.name = name;
+		this.utf8 = new CPUTF8(name);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (this.getClass() != obj.getClass())
+			return false;
+		final CPClass other = (CPClass) obj;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		if (utf8 == null) {
+			if (other.utf8 != null)
+				return false;
+		} else if (!utf8.equals(other.utf8))
+			return false;
+		return true;
+	}
+
+	protected ClassFileEntry[] getNestedClassFileEntries() {
+		return new ClassFileEntry[] { utf8, };
+	}
+
+	@Override
+	public int hashCode() {
+		final int PRIME = 31;
+		int result = 1;
+		result = PRIME * result + ((name == null) ? 0 : name.hashCode());
+		result = PRIME * result + ((utf8 == null) ? 0 : utf8.hashCode());
+		return result;
+	}
+
+	protected void resolve(ClassConstantPool pool) {
+		super.resolve(pool);
+		index = pool.indexOf(utf8);
+	}
+
+	public String toString() {
+		return "Class: " + name;
+	}
+
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		dos.writeShort(index);
+	}
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstant.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstant.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstant.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstant.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,43 @@
+package org.apache.harmony.archive.internal.pack200.bytecode;
+
+
+public abstract class CPConstant extends ConstantPoolEntry {
+
+	private Object value;
+
+	public CPConstant(byte tag, Object value) {
+		super(tag);
+		this.value = value;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (this.getClass() != obj.getClass())
+			return false;
+		final CPConstant other = (CPConstant) obj;
+		if (value == null) {
+			if (other.value != null)
+				return false;
+		} else if (!value.equals(other.value))
+			return false;
+		return true;
+	}
+
+	@Override
+	public int hashCode() {
+		final int PRIME = 31;
+		int result = 1;
+		result = PRIME * result + ((value == null) ? 0 : value.hashCode());
+		return result;
+	}
+	protected Object getValue() {
+		return value;
+	}
+
+
+
+}

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstantNumber.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstantNumber.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstantNumber.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPConstantNumber.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,15 @@
+package org.apache.harmony.archive.internal.pack200.bytecode;
+
+
+public abstract class CPConstantNumber extends CPConstant {
+
+	public CPConstantNumber(byte tag, Object value) {
+		super(tag, value);
+	}
+
+	protected Number getNumber() {
+		return (Number)getValue();
+	}
+
+
+}

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPDouble.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPDouble.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPDouble.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPDouble.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,37 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class CPDouble extends CPConstantNumber {
+	public CPDouble(java.lang.Double value) {
+		super(ConstantPoolEntry.CP_Double,value);
+	}
+
+	@Override
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		dos.writeDouble(getNumber().doubleValue());
+	}
+
+	@Override
+	public String toString() {
+		return "Double: " + getValue();
+	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPField.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPField.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPField.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPField.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,11 @@
+package org.apache.harmony.archive.internal.pack200.bytecode;
+
+import java.util.List;
+
+public class CPField extends CPMember {
+
+	public CPField(String descriptor, long flags, List attributes) {
+		super(descriptor, flags, attributes);
+	}
+
+}

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFieldRef.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFieldRef.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFieldRef.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFieldRef.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,97 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+
+public class CPFieldRef extends ConstantPoolEntry {
+
+	CPClass className;
+	transient int classNameIndex;
+
+
+	private CPNameAndType nameAndType;
+	transient int nameAndTypeIndex;
+	public CPFieldRef(String className, String descriptor) {
+		super(ConstantPoolEntry.CP_Fieldref);
+		this.className = new CPClass(className);
+		this.nameAndType = new CPNameAndType(descriptor);
+	}
+
+
+	@Override
+	protected ClassFileEntry[] getNestedClassFileEntries() {
+		ClassFileEntry[] entries = new ClassFileEntry[2];
+		entries[0] = className;
+		entries[1] = nameAndType;
+		return entries;
+	}
+
+
+	@Override
+	protected void resolve(ClassConstantPool pool) {
+		super.resolve(pool);
+		nameAndTypeIndex = pool.indexOf(nameAndType);
+		classNameIndex = pool.indexOf(className);
+	}
+
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		dos.writeShort(classNameIndex);
+		dos.writeShort(nameAndTypeIndex);
+	}
+
+	@Override
+	public String toString() {
+		return "FieldRef: " + className + "#" + nameAndType;
+	}
+
+
+	@Override
+	public int hashCode() {
+		final int PRIME = 31;
+		int result = 1;
+		result = PRIME * result + ((className == null) ? 0 : className.hashCode());
+		result = PRIME * result + ((nameAndType == null) ? 0 : nameAndType.hashCode());
+		return result;
+	}
+
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		final CPFieldRef other = (CPFieldRef) obj;
+		if (className == null) {
+			if (other.className != null)
+				return false;
+		} else if (!className.equals(other.className))
+			return false;
+		if (nameAndType == null) {
+			if (other.nameAndType != null)
+				return false;
+		} else if (!nameAndType.equals(other.nameAndType))
+			return false;
+		return true;
+	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFloat.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFloat.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFloat.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPFloat.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,37 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class CPFloat extends CPConstantNumber {
+	public CPFloat(java.lang.Float value) {
+		super(ConstantPoolEntry.CP_Float,value);
+	}
+
+	@Override
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		dos.writeFloat(getNumber().floatValue());
+	}
+
+	@Override
+	public String toString() {
+		return "Float: " + getValue();
+	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPInteger.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPInteger.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPInteger.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPInteger.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,38 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class CPInteger extends CPConstantNumber {
+
+	public CPInteger(java.lang.Integer value) {
+		super(ConstantPoolEntry.CP_Integer,value);
+	}
+
+	@Override
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		dos.writeInt(getNumber().intValue());
+	}
+
+	@Override
+	public String toString() {
+		return "Integer: " + getValue();
+	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPLong.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPLong.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPLong.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPLong.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,38 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class CPLong extends CPConstantNumber {
+
+	public CPLong(java.lang.Long value) {
+		super(ConstantPoolEntry.CP_Long,value);
+	}
+
+	@Override
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		dos.writeLong(getNumber().longValue());
+	}
+
+	@Override
+	public String toString() {
+		return "Long: " + getValue();
+	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMember.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMember.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMember.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMember.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,133 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class CPMember extends ClassFileEntry {
+
+	List attributes;
+
+
+	short flags;
+
+	CPUTF8 name;
+	transient int nameIndex;
+
+
+	private CPUTF8 descriptor;
+	transient int descriptorIndex;
+	public CPMember(String descriptor, long flags, List attributes) {
+		int colon = descriptor.indexOf(':');
+		this.name = new CPUTF8(descriptor.substring(0,colon));
+		this.descriptor = new CPUTF8(descriptor.substring(colon+1));
+		this.flags = (short) flags;
+		this.attributes = (attributes == null ? new ArrayList() : attributes);
+	}
+
+
+	@Override
+	protected ClassFileEntry[] getNestedClassFileEntries() {
+		int attributeCount = attributes.size();
+		ClassFileEntry[] entries = new ClassFileEntry[attributeCount+2];
+		entries[0] = name;
+		entries[1] = descriptor;
+		for (int i = 0; i < attributeCount; i++) {
+			entries[i+2] = (Attribute) attributes.get(i);
+		}
+		return entries;
+	}
+
+
+	@Override
+	protected void resolve(ClassConstantPool pool) {
+		super.resolve(pool);
+		nameIndex = pool.indexOf(name);
+		descriptorIndex = pool.indexOf(descriptor);
+		for (Iterator it = attributes.iterator(); it.hasNext();) {
+			Attribute attribute = (Attribute) it.next();
+			attribute.resolve(pool);
+		}
+	}
+
+	@Override
+	public String toString() {
+		return "Field: " + name + "(" + descriptor + ")";
+	}
+
+	@Override
+	public int hashCode() {
+		final int PRIME = 31;
+		int result = 1;
+		result = PRIME * result + ((attributes == null) ? 0 : attributes.hashCode());
+		result = PRIME * result + ((descriptor == null) ? 0 : descriptor.hashCode());
+		result = PRIME * result + flags;
+		result = PRIME * result + ((name == null) ? 0 : name.hashCode());
+		return result;
+	}
+
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		final CPMember other = (CPMember) obj;
+		if (attributes == null) {
+			if (other.attributes != null)
+				return false;
+		} else if (!attributes.equals(other.attributes))
+			return false;
+		if (descriptor == null) {
+			if (other.descriptor != null)
+				return false;
+		} else if (!descriptor.equals(other.descriptor))
+			return false;
+		if (flags != other.flags)
+			return false;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		return true;
+	}
+
+
+	@Override
+	protected void doWrite(DataOutputStream dos) throws IOException {
+		dos.writeShort(flags);
+		dos.writeShort(nameIndex);
+		dos.writeShort(descriptorIndex);
+    	int attributeCount = attributes.size();
+		dos.writeShort(attributeCount);
+		for (int i = 0; i < attributeCount; i++) {
+			Attribute attribute = (Attribute) attributes.get(i);
+			attribute.doWrite(dos);
+		}
+		
+	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMethod.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMethod.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMethod.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPMethod.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,11 @@
+package org.apache.harmony.archive.internal.pack200.bytecode;
+
+import java.util.List;
+
+public class CPMethod extends CPMember {
+
+	public CPMethod(String descriptor, long flags, List attributes) {
+		super(descriptor, flags, attributes);
+	}
+
+}

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPNameAndType.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPNameAndType.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPNameAndType.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPNameAndType.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,93 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+
+public class CPNameAndType extends ConstantPoolEntry {
+
+	CPUTF8 descriptor;
+
+	transient int descriptorIndex;
+
+	CPUTF8 name;
+
+	transient int nameIndex;
+
+	public CPNameAndType(String descriptor) {
+		super(ConstantPoolEntry.CP_NameAndType);
+		int colon = descriptor.indexOf(':');
+		this.name = new CPUTF8(descriptor.substring(0,colon));
+		this.descriptor = new CPUTF8(descriptor.substring(colon+1));
+	}
+
+	@Override
+	protected void resolve(ClassConstantPool pool) {
+		super.resolve(pool);
+		descriptorIndex = pool.indexOf(descriptor);
+		nameIndex = pool.indexOf(name);
+	}
+
+	/*
+	 * field_info { u2 access_flags; u2 name_index; u2 descriptor_index; u2
+	 * attributes_count; attribute_info attributes[attributes_count]; }
+	 */
+	@Override
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		dos.writeShort(nameIndex);
+		dos.writeShort(descriptorIndex);
+	}
+
+	@Override
+	public String toString() {
+		return "NameAndType: " + name + "(" + descriptor + ")";
+	}
+
+	@Override
+	public int hashCode() {
+		final int PRIME = 31;
+		int result = 1;
+		result = PRIME * result + ((descriptor == null) ? 0 : descriptor.hashCode());
+		result = PRIME * result + ((name == null) ? 0 : name.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		final CPNameAndType other = (CPNameAndType) obj;
+		if (descriptor == null) {
+			if (other.descriptor != null)
+				return false;
+		} else if (!descriptor.equals(other.descriptor))
+			return false;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		return true;
+	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPString.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPString.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPString.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPString.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,56 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+
+public class CPString extends CPConstant {
+	private transient int nameIndex;
+	private CPUTF8 name;
+
+	public CPString(java.lang.String value) {
+		super(ConstantPoolEntry.CP_String,value);
+		this.name = new CPUTF8((String) getValue());
+
+	}
+
+	@Override
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		dos.writeShort(nameIndex);
+	}
+
+	@Override
+	public String toString() {
+		return "String: " + getValue();
+	}
+
+	/**
+	 * Allows the constant pool entries to resolve their nested entries
+	 * 
+	 * @param pool
+	 */
+	protected void resolve(ClassConstantPool pool) {
+		super.resolve(pool);
+		nameIndex = pool.indexOf(name);
+	}
+
+	protected ClassFileEntry[] getNestedClassFileEntries() {
+		return new ClassFileEntry[] { name };
+ 	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPUTF8.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPUTF8.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPUTF8.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/CPUTF8.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,77 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+
+public class CPUTF8 extends ConstantPoolEntry {
+	private String utf8;
+
+	public CPUTF8(String utf8) {
+		super(ConstantPoolEntry.CP_UTF8);
+		this.utf8 = utf8;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (this.getClass() != obj.getClass())
+			return false;
+		final CPUTF8 other = (CPUTF8) obj;
+		if (utf8 == null) {
+			if (other.utf8 != null)
+				return false;
+		} else if (!utf8.equals(other.utf8))
+			return false;
+		return true;
+	}
+
+	@Override
+	public int hashCode() {
+		final int PRIME = 31;
+		int result = 1;
+		result = PRIME * result + ((utf8 == null) ? 0 : utf8.hashCode());
+		return result;
+	}
+
+	public String toString() {
+		return "UTF8: " + utf8;
+	}
+
+	protected void writeBody(DataOutputStream dos) throws IOException {
+		byte[] bytes;
+		try {
+			// TODO Check that this is the right UTF-8 for bytes
+			if (utf8 == null) {
+				bytes = new byte[0];
+			} else {
+				bytes = utf8.getBytes("UTF-8");
+			}
+		} catch (UnsupportedEncodingException e) {
+			throw new RuntimeException("Couldn't convert string " + utf8
+					+ " to UTF-8");
+		}
+		dos.writeShort(bytes.length);
+		dos.write(bytes);
+	}
+
+}
\ No newline at end of file

Added: harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ClassConstantPool.java
URL: http://svn.apache.org/viewvc/harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ClassConstantPool.java?view=auto&rev=478907
==============================================================================
--- harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ClassConstantPool.java (added)
+++ harmony/enhanced/classlib/trunk/modules/archive/src/main/java/org/apache/harmony/archive/internal/pack200/bytecode/ClassConstantPool.java Fri Nov 24 08:28:57 2006
@@ -0,0 +1,90 @@
+/*
+ *  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.archive.internal.pack200.bytecode;
+
+// NOTE: Do not use generics in this code; it needs to run on JVMs < 1.5
+// NOTE: Do not extract strings as messages; this code is still a
+// work-in-progress
+// NOTE: Also, don't get rid of 'else' statements for the hell of it ...
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+
+public class ClassConstantPool {
+	public String toString() {
+		return entries.toString();
+	}
+	private List others = new ArrayList();
+
+	private List entries = new ArrayList();
+
+	private boolean resolved;
+
+	public ClassFileEntry add(ClassFileEntry entry) {
+		// TODO this should be a set - we don't want duplicates
+		// Only add in constant pools, but resolve all types since they may
+		// introduce new constant pool entries
+		if (entry instanceof ConstantPoolEntry) {
+			if (!entries.contains(entry)) {
+				entries.add(entry);
+				// TODO This will be a bugger when they're sorted.
+				if (entry instanceof CPLong ||entry instanceof CPDouble)
+					entries.add(entry); //these get 2 slots because of their size
+			}
+		} else {
+			if (!others.contains(entry))
+				others.add(entry);
+		}
+		ClassFileEntry[] nestedEntries = entry.getNestedClassFileEntries();
+		for (int i = 0; i < nestedEntries.length; i++) {
+			add(nestedEntries[i]);
+		}
+		return entry;
+	}
+
+	public int indexOf(ClassFileEntry entry) {
+		if (!resolved)
+			throw new IllegalStateException("Constant pool is not yet resolved; this does not make any sense");
+		return entries.indexOf(entry) + 1;
+	}
+
+	public int size() {
+		return entries.size();
+	}
+
+	public ClassFileEntry get(int i) {
+		if (!resolved)
+			throw new IllegalStateException("Constant pool is not yet resolved; this does not make any sense");
+		return (ClassFileEntry) entries.get(--i);
+	}
+
+	public void resolve() {
+		resolved= true;
+		Iterator it = entries.iterator();
+		while (it.hasNext()) {
+			ClassFileEntry entry = (ClassFileEntry) it.next();
+			entry.resolve(this);
+		}
+		it = others.iterator();
+		while (it.hasNext()) {
+			ClassFileEntry entry = (ClassFileEntry) it.next();
+			entry.resolve(this);
+		}
+	}
+
+}