removed Makefile; lifted repo/org.ibex.tool/src/ to src/
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ClassFile.java
diff --git a/src/org/eclipse/jdt/internal/compiler/ClassFile.java b/src/org/eclipse/jdt/internal/compiler/ClassFile.java
new file mode 100644 (file)
index 0000000..e575af5
--- /dev/null
@@ -0,0 +1,2621 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2004 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials 
+ * are made available under the terms of the Common Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/cpl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler;
+
+import java.io.*;
+import java.util.StringTokenizer;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.internal.compiler.ast.*;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.codegen.*;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
+import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.StringConstant;
+import org.eclipse.jdt.internal.compiler.lookup.*;
+import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
+import org.eclipse.jdt.internal.compiler.util.Util;
+
+/**
+ * Represents a class file wrapper on bytes, it is aware of its actual
+ * type name.
+ *
+ * Public APIs are listed below:
+ *
+ * byte[] getBytes();
+ *             Answer the actual bytes of the class file
+ *
+ * char[][] getCompoundName();
+ *             Answer the compound name of the class file.
+ *             For example, {{java}, {util}, {Hashtable}}.
+ *
+ * byte[] getReducedBytes();
+ *             Answer a smaller byte format, which is only contains some structural 
+ *      information. Those bytes are decodable with a regular class file reader, 
+ *      such as DietClassFileReader
+ */
+public class ClassFile
+       implements AttributeNamesConstants, CompilerModifiers, TypeConstants, TypeIds {
+       public SourceTypeBinding referenceBinding;
+       public ConstantPool constantPool;
+       public ClassFile enclosingClassFile;
+       // used to generate private access methods
+       public int produceDebugAttributes;
+       public ReferenceBinding[] innerClassesBindings;
+       public int numberOfInnerClasses;
+       public byte[] header;
+       // the header contains all the bytes till the end of the constant pool
+       public byte[] contents;
+       // that collection contains all the remaining bytes of the .class file
+       public int headerOffset;
+       public int contentsOffset;
+       public int constantPoolOffset;
+       public int methodCountOffset;
+       public int methodCount;
+       protected boolean creatingProblemType;
+       public static final int INITIAL_CONTENTS_SIZE = 400;
+       public static final int INITIAL_HEADER_SIZE = 1500;
+       public boolean ownSharedArrays = false; // flag set when header/contents are set to shared arrays
+       public static final int INNER_CLASSES_SIZE = 5;
+       public CodeStream codeStream;
+       protected int problemLine;      // used to create line number attributes for problem methods
+       public long targetJDK;
+       
+       /**
+        * INTERNAL USE-ONLY
+        * This methods creates a new instance of the receiver.
+        */
+       public ClassFile() {
+               // default constructor for subclasses
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods creates a new instance of the receiver.
+        *
+        * @param aType org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding
+        * @param enclosingClassFile org.eclipse.jdt.internal.compiler.ClassFile
+        * @param creatingProblemType <CODE>boolean</CODE>
+        */
+       public ClassFile(
+               SourceTypeBinding aType,
+               ClassFile enclosingClassFile,
+               boolean creatingProblemType) {
+           
+               referenceBinding = aType;
+               initByteArrays();
+
+               // generate the magic numbers inside the header
+               header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
+               header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
+               header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
+               header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
+               
+               this.targetJDK = referenceBinding.scope.environment().options.targetJDK;
+               header[headerOffset++] = (byte) (this.targetJDK >> 8); // minor high
+               header[headerOffset++] = (byte) (this.targetJDK >> 0); // minor low
+               header[headerOffset++] = (byte) (this.targetJDK >> 24); // major high
+               header[headerOffset++] = (byte) (this.targetJDK >> 16); // major low
+
+               constantPoolOffset = headerOffset;
+               headerOffset += 2;
+               constantPool = new ConstantPool(this);
+               
+               // Modifier manipulations for classfile
+               int accessFlags = aType.getAccessFlags();
+               if (aType.isPrivate()) { // rewrite private to non-public
+                       accessFlags &= ~AccPublic;
+               }
+               if (aType.isProtected()) { // rewrite protected into public
+                       accessFlags |= AccPublic;
+               }
+               // clear all bits that are illegal for a class or an interface
+               accessFlags
+                       &= ~(
+                               AccStrictfp
+                                       | AccProtected
+                                       | AccPrivate
+                                       | AccStatic
+                                       | AccSynchronized
+                                       | AccNative);
+                                       
+               // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
+               if (aType.isClass()) {
+                       accessFlags |= AccSuper;
+               }
+               
+               this.enclosingClassFile = enclosingClassFile;
+               // innerclasses get their names computed at code gen time
+
+               // now we continue to generate the bytes inside the contents array
+               contents[contentsOffset++] = (byte) (accessFlags >> 8);
+               contents[contentsOffset++] = (byte) accessFlags;
+               int classNameIndex = constantPool.literalIndex(aType);
+               contents[contentsOffset++] = (byte) (classNameIndex >> 8);
+               contents[contentsOffset++] = (byte) classNameIndex;
+               int superclassNameIndex;
+               if (aType.isInterface()) {
+                       superclassNameIndex = constantPool.literalIndexForJavaLangObject();
+               } else {
+                       superclassNameIndex =
+                               (aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
+               }
+               contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
+               contents[contentsOffset++] = (byte) superclassNameIndex;
+               ReferenceBinding[] superInterfacesBinding = aType.superInterfaces();
+               int interfacesCount = superInterfacesBinding.length;
+               contents[contentsOffset++] = (byte) (interfacesCount >> 8);
+               contents[contentsOffset++] = (byte) interfacesCount;
+               for (int i = 0; i < interfacesCount; i++) {
+                       int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+                       contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
+                       contents[contentsOffset++] = (byte) interfaceIndex;
+               }
+               produceDebugAttributes = referenceBinding.scope.environment().options.produceDebugAttributes;
+               innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
+               this.creatingProblemType = creatingProblemType;
+               codeStream = new CodeStream(this);
+
+               // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
+               // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
+               ClassFile outermostClassFile = this.outerMostEnclosingClassFile();
+               if (this == outermostClassFile) {
+                       codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
+               } else {
+                       codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus method.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        */
+       public void addAbstractMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding) {
+
+               // force the modifiers to be public and abstract
+               methodBinding.modifiers = AccPublic | AccAbstract;
+
+               this.generateMethodInfoHeader(methodBinding);
+               int methodAttributeOffset = this.contentsOffset;
+               int attributeNumber = this.generateMethodInfoAttribute(methodBinding);
+               this.completeMethodInfo(methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the attributes for the receiver.
+        * For a class they could be:
+        * - source file attribute
+        * - inner classes attribute
+        * - deprecated attribute
+        */
+       public void addAttributes() {
+               // update the method count
+               contents[methodCountOffset++] = (byte) (methodCount >> 8);
+               contents[methodCountOffset] = (byte) methodCount;
+
+               int attributeNumber = 0;
+               // leave two bytes for the number of attributes and store the current offset
+               int attributeOffset = contentsOffset;
+               contentsOffset += 2;
+
+               // source attribute
+               if ((produceDebugAttributes & CompilerOptions.Source) != 0) {
+                       String fullFileName =
+                               new String(referenceBinding.scope.referenceCompilationUnit().getFileName());
+                       fullFileName = fullFileName.replace('\\', '/');
+                       int lastIndex = fullFileName.lastIndexOf('/');
+                       if (lastIndex != -1) {
+                               fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length());
+                       }
+                       // check that there is enough space to write all the bytes for the field info corresponding
+                       // to the @fieldBinding
+                       if (contentsOffset + 8 >= contents.length) {
+                               resizeContents(8);
+                       }
+                       int sourceAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.SourceName);
+                       contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
+                       // The length of a source file attribute is 2. This is a fixed-length
+                       // attribute
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 2;
+                       // write the source file name
+                       int fileNameIndex = constantPool.literalIndex(fullFileName.toCharArray());
+                       contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) fileNameIndex;
+                       attributeNumber++;
+               }
+               // Deprecated attribute
+               if (referenceBinding.isDeprecated()) {
+                       // check that there is enough space to write all the bytes for the field info corresponding
+                       // to the @fieldBinding
+                       if (contentsOffset + 6 >= contents.length) {
+                               resizeContents(6);
+                       }
+                       int deprecatedAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+                       contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+                       // the length of a deprecated attribute is equals to 0
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       attributeNumber++;
+               }
+               // Inner class attribute
+               if (numberOfInnerClasses != 0) {
+                       // Generate the inner class attribute
+                       int exSize = 8 * numberOfInnerClasses + 8;
+                       if (exSize + contentsOffset >= this.contents.length) {
+                               resizeContents(exSize);
+                       }
+                       // Now we now the size of the attribute and the number of entries
+                       // attribute name
+                       int attributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.InnerClassName);
+                       contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) attributeNameIndex;
+                       int value = (numberOfInnerClasses << 3) + 2;
+                       contents[contentsOffset++] = (byte) (value >> 24);
+                       contents[contentsOffset++] = (byte) (value >> 16);
+                       contents[contentsOffset++] = (byte) (value >> 8);
+                       contents[contentsOffset++] = (byte) value;
+                       contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
+                       contents[contentsOffset++] = (byte) numberOfInnerClasses;
+                       for (int i = 0; i < numberOfInnerClasses; i++) {
+                               ReferenceBinding innerClass = innerClassesBindings[i];
+                               int accessFlags = innerClass.getAccessFlags();
+                               int innerClassIndex = constantPool.literalIndex(innerClass);
+                               // inner class index
+                               contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
+                               contents[contentsOffset++] = (byte) innerClassIndex;
+                               // outer class index: anonymous and local have no outer class index
+                               if (innerClass.isMemberType()) {
+                                       // member or member of local
+                                       int outerClassIndex = constantPool.literalIndex(innerClass.enclosingType());
+                                       contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
+                                       contents[contentsOffset++] = (byte) outerClassIndex;
+                               } else {
+                                       // equals to 0 if the innerClass is not a member type
+                                       contents[contentsOffset++] = 0;
+                                       contents[contentsOffset++] = 0;
+                               }
+                               // name index
+                               if (!innerClass.isAnonymousType()) {
+                                       int nameIndex = constantPool.literalIndex(innerClass.sourceName());
+                                       contents[contentsOffset++] = (byte) (nameIndex >> 8);
+                                       contents[contentsOffset++] = (byte) nameIndex;
+                               } else {
+                                       // equals to 0 if the innerClass is an anonymous type
+                                       contents[contentsOffset++] = 0;
+                                       contents[contentsOffset++] = 0;
+                               }
+                               // access flag
+                               if (innerClass.isAnonymousType()) {
+                                       accessFlags |= AccPrivate;
+                               } else
+                                       if (innerClass.isLocalType() && !innerClass.isMemberType()) {
+                                               accessFlags |= AccPrivate;
+                                       }
+                               contents[contentsOffset++] = (byte) (accessFlags >> 8);
+                               contents[contentsOffset++] = (byte) accessFlags;
+                       }
+                       attributeNumber++;
+               }
+               // update the number of attributes
+               if (attributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[attributeOffset] = (byte) attributeNumber;
+
+               // resynchronize all offsets of the classfile
+               header = constantPool.poolContent;
+               headerOffset = constantPool.currentOffset;
+               int constantPoolCount = constantPool.currentIndex;
+               header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
+               header[constantPoolOffset] = (byte) constantPoolCount;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the default abstract method infos that correpond to
+        * the abstract methods inherited from superinterfaces.
+        */
+       public void addDefaultAbstractMethods() { // default abstract methods
+               MethodBinding[] defaultAbstractMethods =
+                       referenceBinding.getDefaultAbstractMethods();
+               for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+                       generateMethodInfoHeader(defaultAbstractMethods[i]);
+                       int methodAttributeOffset = contentsOffset;
+                       int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
+                       completeMethodInfo(methodAttributeOffset, attributeNumber);
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generates the bytes for the field binding passed like a parameter
+        * @param fieldBinding org.eclipse.jdt.internal.compiler.lookup.FieldBinding
+        */
+       public void addFieldInfo(FieldBinding fieldBinding) {
+               int attributeNumber = 0;
+               // check that there is enough space to write all the bytes for the field info corresponding
+               // to the @fieldBinding
+               if (contentsOffset + 30 >= contents.length) {
+                       resizeContents(30);
+               }
+               // Generate two attribute: constantValueAttribute and SyntheticAttribute
+               // Now we can generate all entries into the byte array
+               // First the accessFlags
+               int accessFlags = fieldBinding.getAccessFlags();
+               contents[contentsOffset++] = (byte) (accessFlags >> 8);
+               contents[contentsOffset++] = (byte) accessFlags;
+               // Then the nameIndex
+               int nameIndex = constantPool.literalIndex(fieldBinding.name);
+               contents[contentsOffset++] = (byte) (nameIndex >> 8);
+               contents[contentsOffset++] = (byte) nameIndex;
+               // Then the descriptorIndex
+               int descriptorIndex = constantPool.literalIndex(fieldBinding.type.signature());
+               contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+               contents[contentsOffset++] = (byte) descriptorIndex;
+               // leave some space for the number of attributes
+               int fieldAttributeOffset = contentsOffset;
+               contentsOffset += 2;
+               // 4.7.2 only static constant fields get a ConstantAttribute
+               if (fieldBinding.constant != Constant.NotAConstant){
+                       // Now we generate the constant attribute corresponding to the fieldBinding
+                       int constantValueNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
+                       contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) constantValueNameIndex;
+                       // The attribute length = 2 in case of a constantValue attribute
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 2;
+                       attributeNumber++;
+                       // Need to add the constant_value_index
+                       switch (fieldBinding.constant.typeID()) {
+                               case T_boolean :
+                                       int booleanValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
+                                       contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) booleanValueIndex;
+                                       break;
+                               case T_byte :
+                               case T_char :
+                               case T_int :
+                               case T_short :
+                                       int integerValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.intValue());
+                                       contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) integerValueIndex;
+                                       break;
+                               case T_float :
+                                       int floatValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.floatValue());
+                                       contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) floatValueIndex;
+                                       break;
+                               case T_double :
+                                       int doubleValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.doubleValue());
+                                       contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) doubleValueIndex;
+                                       break;
+                               case T_long :
+                                       int longValueIndex =
+                                               constantPool.literalIndex(fieldBinding.constant.longValue());
+                                       contents[contentsOffset++] = (byte) (longValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) longValueIndex;
+                                       break;
+                               case T_String :
+                                       int stringValueIndex =
+                                               constantPool.literalIndex(
+                                                       ((StringConstant) fieldBinding.constant).stringValue());
+                                       if (stringValueIndex == -1) {
+                                               if (!creatingProblemType) {
+                                                       // report an error and abort: will lead to a problem type classfile creation
+                                                       TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+                                                       FieldDeclaration[] fieldDecls = typeDeclaration.fields;
+                                                       for (int i = 0, max = fieldDecls.length; i < max; i++) {
+                                                               if (fieldDecls[i].binding == fieldBinding) {
+                                                                       // problem should abort
+                                                                       typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(
+                                                                               fieldDecls[i]);
+                                                               }
+                                                       }
+                                               } else {
+                                                       // already inside a problem type creation : no constant for this field
+                                                       contentsOffset = fieldAttributeOffset + 2;
+                                                       // +2 is necessary to keep the two byte space for the attribute number
+                                                       attributeNumber--;
+                                               }
+                                       } else {
+                                               contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
+                                               contents[contentsOffset++] = (byte) stringValueIndex;
+                                       }
+                       }
+               }
+               if (fieldBinding.isSynthetic()) {
+                       int syntheticAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+                       contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+                       // the length of a synthetic attribute is equals to 0
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       attributeNumber++;
+               }
+               if (fieldBinding.isDeprecated()) {
+                       int deprecatedAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+                       contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+                       // the length of a deprecated attribute is equals to 0
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       attributeNumber++;
+               }
+               contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[fieldAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generate all the fields infos for the receiver.
+        * This includes:
+        * - a field info for each defined field of that class
+        * - a field info for each synthetic field (e.g. this$0)
+        */
+       public void addFieldInfos() {
+               SourceTypeBinding currentBinding = referenceBinding;
+               FieldBinding[] syntheticFields = currentBinding.syntheticFields();
+               int fieldCount =
+                       currentBinding.fieldCount()
+                               + (syntheticFields == null ? 0 : syntheticFields.length);
+
+               // write the number of fields
+               if (fieldCount > 0xFFFF) {
+                       referenceBinding.scope.problemReporter().tooManyFields(referenceBinding.scope.referenceType());
+               }
+               contents[contentsOffset++] = (byte) (fieldCount >> 8);
+               contents[contentsOffset++] = (byte) fieldCount;
+
+               FieldBinding[] fieldBindings = currentBinding.fields();
+               for (int i = 0, max = fieldBindings.length; i < max; i++) {
+                       addFieldInfo(fieldBindings[i]);
+               }
+               if (syntheticFields != null) {
+                       for (int i = 0, max = syntheticFields.length; i < max; i++) {
+                               addFieldInfo(syntheticFields[i]);
+                       }
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods stores the bindings for each inner class. They will be used to know which entries
+        * have to be generated for the inner classes attributes.
+        * @param refBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
+        */
+       public void addInnerClasses(ReferenceBinding refBinding) {
+               // check first if that reference binding is there
+               for (int i = 0; i < numberOfInnerClasses; i++) {
+                       if (innerClassesBindings[i] == refBinding)
+                               return;
+               }
+               int length = innerClassesBindings.length;
+               if (numberOfInnerClasses == length) {
+                       System.arraycopy(
+                               innerClassesBindings,
+                               0,
+                               innerClassesBindings = new ReferenceBinding[length * 2],
+                               0,
+                               length);
+               }
+               innerClassesBindings[numberOfInnerClasses++] = refBinding;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem clinit method info that correspond to a boggus method.
+        *
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemClinit(IProblem[] problems) {
+               generateMethodInfoHeaderForClinit();
+               // leave two spaces for the number of attributes
+               contentsOffset -= 2;
+               int attributeOffset = contentsOffset;
+               contentsOffset += 2;
+               int attributeNumber = 0;
+
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.resetForProblemClinit(this);
+               String problemString = "" ; //$NON-NLS-1$
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               IProblem problem = problems[i];
+                               if ((problem != null) && (problem.isError())) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                                       problems[i] = null;
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
+                       } else {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               codeStream.generateCodeAttributeForProblemMethod(problemString);
+               attributeNumber++; // code attribute
+               completeCodeAttributeForClinit(
+                       codeAttributeOffset,
+                       referenceBinding
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               contents[attributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[attributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus constructor.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemConstructor(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               IProblem[] problems) {
+
+               // always clear the strictfp/native/abstract bit for a problem method
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
+               int methodAttributeOffset = contentsOffset;
+               int attributeNumber = generateMethodInfoAttribute(methodBinding);
+               
+               // Code attribute
+               attributeNumber++;
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.reset(method, this);
+               String problemString = "" ; //$NON-NLS-1$
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               IProblem problem = problems[i];
+                               if ((problem != null) && (problem.isError())) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
+                       } else {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               codeStream.generateCodeAttributeForProblemMethod(problemString);
+               completeCodeAttributeForProblemMethod(
+                       method,
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               completeMethodInfo(methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus constructor.
+        * Reset the position inside the contents byte array to the savedOffset.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        * @param savedOffset <CODE>int</CODE>
+        */
+       public void addProblemConstructor(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               IProblem[] problems,
+               int savedOffset) {
+               // we need to move back the contentsOffset to the value at the beginning of the method
+               contentsOffset = savedOffset;
+               methodCount--; // we need to remove the method that causes the problem
+               addProblemConstructor(method, methodBinding, problems);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus method.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        */
+       public void addProblemMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               IProblem[] problems) {
+               if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) {
+                       method.abort(ProblemSeverities.AbortType, null);
+               }
+               // always clear the strictfp/native/abstract bit for a problem method
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
+               int methodAttributeOffset = contentsOffset;
+               int attributeNumber = generateMethodInfoAttribute(methodBinding);
+               
+               // Code attribute
+               attributeNumber++;
+               
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.reset(method, this);
+               String problemString = "" ; //$NON-NLS-1$
+               if (problems != null) {
+                       int max = problems.length;
+                       StringBuffer buffer = new StringBuffer(25);
+                       int count = 0;
+                       for (int i = 0; i < max; i++) {
+                               IProblem problem = problems[i];
+                               if ((problem != null)
+                                       && (problem.isError())
+                                       && (problem.getSourceStart() >= method.declarationSourceStart)
+                                       && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
+                                       buffer.append("\t"  +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+                                       count++;
+                                       if (problemLine == 0) {
+                                               problemLine = problem.getSourceLineNumber();
+                                       }
+                                       problems[i] = null;
+                               }
+                       } // insert the top line afterwards, once knowing how many problems we have to consider
+                       if (count > 1) {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblems" )); //$NON-NLS-1$
+                       } else {
+                               buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+                       }
+                       problemString = buffer.toString();
+               }
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               codeStream.generateCodeAttributeForProblemMethod(problemString);
+               completeCodeAttributeForProblemMethod(
+                       method,
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               completeMethodInfo(methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a boggus method.
+        * Reset the position inside the contents byte array to the savedOffset.
+        *
+        * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
+        * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
+        * @param savedOffset <CODE>int</CODE>
+        */
+       public void addProblemMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding methodBinding,
+               IProblem[] problems,
+               int savedOffset) {
+               // we need to move back the contentsOffset to the value at the beginning of the method
+               contentsOffset = savedOffset;
+               methodCount--; // we need to remove the method that causes the problem
+               addProblemMethod(method, methodBinding, problems);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for all the special method infos.
+        * They are:
+        * - synthetic access methods
+        * - default abstract methods
+        */
+       public void addSpecialMethods() {
+               // add all methods (default abstract methods and synthetic)
+
+               // default abstract methods
+               SourceTypeBinding currentBinding = referenceBinding;
+               MethodBinding[] defaultAbstractMethods =
+                       currentBinding.getDefaultAbstractMethods();
+               for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
+                       generateMethodInfoHeader(defaultAbstractMethods[i]);
+                       int methodAttributeOffset = contentsOffset;
+                       int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
+                       completeMethodInfo(methodAttributeOffset, attributeNumber);
+               }
+               // add synthetic methods infos
+               SyntheticAccessMethodBinding[] syntheticAccessMethods =
+                       currentBinding.syntheticAccessMethods();
+               if (syntheticAccessMethods != null) {
+                       for (int i = 0, max = syntheticAccessMethods.length; i < max; i++) {
+                               SyntheticAccessMethodBinding accessMethodBinding = syntheticAccessMethods[i];
+                               switch (accessMethodBinding.accessType) {
+                                       case SyntheticAccessMethodBinding.FieldReadAccess :
+                                               // generate a method info to emulate an reading access to
+                                               // a non-accessible field
+                                               addSyntheticFieldReadAccessMethod(syntheticAccessMethods[i]);
+                                               break;
+                                       case SyntheticAccessMethodBinding.FieldWriteAccess :
+                                               // generate a method info to emulate an writing access to
+                                               // a non-accessible field
+                                               addSyntheticFieldWriteAccessMethod(syntheticAccessMethods[i]);
+                                               break;
+                                       case SyntheticAccessMethodBinding.MethodAccess :
+                                       case SyntheticAccessMethodBinding.SuperMethodAccess :
+                                               // generate a method info to emulate an access to a non-accessible method / super-method
+                                               addSyntheticMethodAccessMethod(syntheticAccessMethods[i]);
+                                               break;
+                                       case SyntheticAccessMethodBinding.ConstructorAccess :
+                                               // generate a method info to emulate an access to a non-accessible constructor
+                                               addSyntheticConstructorAccessMethod(syntheticAccessMethods[i]);
+                               }
+                       }
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for problem method infos that correspond to missing abstract methods.
+        * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
+        *
+        * @param methodDeclarations Array of all missing abstract methods
+        */
+       public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) {
+               if (methodDeclarations != null) {
+                       for (int i = 0, max = methodDeclarations.length; i < max; i++) {
+                               MethodDeclaration methodDeclaration = methodDeclarations[i];
+                               MethodBinding methodBinding = methodDeclaration.binding;
+                               String readableName = new String(methodBinding.readableName());
+                               IProblem[] problems = compilationResult.problems;
+                               int problemsCount = compilationResult.problemCount;
+                               for (int j = 0; j < problemsCount; j++) {
+                                       IProblem problem = problems[j];
+                                       if (problem != null
+                                               && problem.getID() == IProblem.AbstractMethodMustBeImplemented
+                                               && problem.getMessage().indexOf(readableName) != -1) {
+                                                       // we found a match
+                                                       addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult);
+                                               }
+                               }
+                       }
+               }
+       }
+       
+       private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, IProblem problem, CompilationResult compilationResult) {
+               // always clear the strictfp/native/abstract bit for a problem method
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(AccStrictfp | AccNative | AccAbstract));
+               int methodAttributeOffset = contentsOffset;
+               int attributeNumber = generateMethodInfoAttribute(methodBinding);
+               
+               // Code attribute
+               attributeNumber++;
+               
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               StringBuffer buffer = new StringBuffer(25);
+               buffer.append("\t"  + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$
+               buffer.insert(0, Util.bind("compilation.unresolvedProblem" )); //$NON-NLS-1$
+               String problemString = buffer.toString();
+               this.problemLine = problem.getSourceLineNumber();
+               
+               codeStream.init(this);
+               codeStream.preserveUnusedLocals = true;
+               codeStream.initializeMaxLocals(methodBinding);
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               codeStream.generateCodeAttributeForProblemMethod(problemString);
+                               
+               completeCodeAttributeForMissingAbstractProblemMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       compilationResult.lineSeparatorPositions);
+                       
+               completeMethodInfo(methodAttributeOffset, attributeNumber);
+       }
+
+       /**
+        * 
+        */
+       public void completeCodeAttributeForMissingAbstractProblemMethod(
+               MethodBinding binding,
+               int codeAttributeOffset,
+               int[] startLineIndexes) {
+               // reinitialize the localContents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+               int max_stack = codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               int code_length = codeStream.position;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+               // write the exception table
+               if (localContentsOffset + 50 >= this.contents.length) {
+                       resizeContents(50);
+               }
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributeNumber = 0; // leave two bytes for the attribute_length
+               localContentsOffset += 2; // first we handle the linenumber attribute
+
+               if (codeStream.generateLineNumberAttributes) {
+                       /* Create and add the line number attribute (used for debugging) 
+                           * Build the pairs of:
+                           * (bytecodePC lineNumber)
+                           * according to the table of start line indexes and the pcToSourceMap table
+                           * contained into the codestream
+                           */
+                       int lineNumberNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                       this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 6;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 1;
+                       if (problemLine == 0) {
+                               problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+                       }
+                       // first entry at pc = 0
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
+                       this.contents[localContentsOffset++] = (byte) problemLine;
+                       // now we change the size of the line number attribute
+                       attributeNumber++;
+               }
+               
+               // then we do the local variable attribute
+               // update the number of attributes// ensure first that there is enough space available inside the localContents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+               // update the attribute length
+               int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+               contentsOffset = localContentsOffset;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a synthetic method that
+        * generate an access to a private constructor.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 2;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
+               completeCodeAttributeForSyntheticAccessMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               // add the synthetic attribute
+               int syntheticAttributeNameIndex =
+                       constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+               contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+               contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+               // the length of a synthetic attribute is equals to 0
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a synthetic method that
+        * generate an read access to a private field.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticFieldReadAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 2;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
+               completeCodeAttributeForSyntheticAccessMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               // add the synthetic attribute
+               int syntheticAttributeNameIndex =
+                       constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+               contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+               contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+               // the length of a synthetic attribute is equals to 0
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a synthetic method that
+        * generate an write access to a private field.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 2;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
+               completeCodeAttributeForSyntheticAccessMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               // add the synthetic attribute
+               int syntheticAttributeNameIndex =
+                       constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+               contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+               contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+               // the length of a synthetic attribute is equals to 0
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Generate the byte for a problem method info that correspond to a synthetic method that
+        * generate an access to a private method.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */
+       public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 2;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
+               completeCodeAttributeForSyntheticAccessMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       ((SourceTypeBinding) methodBinding.declaringClass)
+                               .scope
+                               .referenceCompilationUnit()
+                               .compilationResult
+                               .lineSeparatorPositions);
+               // add the synthetic attribute
+               int syntheticAttributeNameIndex =
+                       constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+               contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+               contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+               // the length of a synthetic attribute is equals to 0
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 0;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Build all the directories and subdirectories corresponding to the packages names
+        * into the directory specified in parameters.
+        *
+        * outputPath is formed like:
+        *         c:\temp\ the last character is a file separator
+        * relativeFileName is formed like:
+        *     java\lang\String.class *
+        * 
+        * @param outputPath java.lang.String
+        * @param relativeFileName java.lang.String
+        * @return java.lang.String
+        */
+       public static String buildAllDirectoriesInto(
+               String outputPath,
+               String relativeFileName)
+               throws IOException {
+               char fileSeparatorChar = File.separatorChar;
+               String fileSeparator = File.separator;
+               File f;
+               // First we ensure that the outputPath exists
+               outputPath = outputPath.replace('/', fileSeparatorChar);
+               // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+               if (outputPath.endsWith(fileSeparator)) {
+                       outputPath = outputPath.substring(0, outputPath.length() - 1);
+               }
+               f = new File(outputPath);
+               if (f.exists()) {
+                       if (!f.isDirectory()) {
+                               System.out.println(Util.bind("output.isFile" , f.getAbsolutePath())); //$NON-NLS-1$
+                               throw new IOException(Util.bind("output.isFileNotDirectory" )); //$NON-NLS-1$
+                       }
+               } else {
+                       // we have to create that directory
+                       if (!f.mkdirs()) {
+                               System.out.println(Util.bind("output.dirName" , f.getAbsolutePath())); //$NON-NLS-1$
+                               throw new IOException(Util.bind("output.notValidAll" )); //$NON-NLS-1$
+                       }
+               }
+               StringBuffer outDir = new StringBuffer(outputPath);
+               outDir.append(fileSeparator);
+               StringTokenizer tokenizer =
+                       new StringTokenizer(relativeFileName, fileSeparator);
+               String token = tokenizer.nextToken();
+               while (tokenizer.hasMoreTokens()) {
+                       f = new File(outDir.append(token).append(fileSeparator).toString());
+                       if (f.exists()) {
+                               // The outDir already exists, so we proceed the next entry
+                               // System.out.println("outDir: " + outDir + " already exists.");
+                       } else {
+                               // Need to add the outDir
+                               if (!f.mkdir()) {
+                                       System.out.println(Util.bind("output.fileName" , f.getName())); //$NON-NLS-1$
+                                       throw new IOException(Util.bind("output.notValid" )); //$NON-NLS-1$
+                               }
+                       }
+                       token = tokenizer.nextToken();
+               }
+               // token contains the last one
+               return outDir.append(token).toString();
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttribute(int codeAttributeOffset) {
+               // reinitialize the localContents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside localContents byte array before we started to write
+               // any information about the codeAttribute
+               // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+               // to get the right position, 6 for the max_stack etc...
+               int code_length = codeStream.position;
+               if (code_length > 65535) {
+                       codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+                               codeStream.methodDeclaration);
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int max_stack = codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+
+               // write the exception table
+               int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+               ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+               int exSize = exceptionHandlersNumber * 8 + 2;
+               if (exSize + localContentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               // there is no exception table, so we need to offset by 2 the current offset and move 
+               // on the attribute generation
+               this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+               this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+               for (int i = 0; i < exceptionHandlersNumber; i++) {
+                       ExceptionLabel exceptionHandler = exceptionHandlers[i];
+                       int start = exceptionHandler.start;
+                       this.contents[localContentsOffset++] = (byte) (start >> 8);
+                       this.contents[localContentsOffset++] = (byte) start;
+                       int end = exceptionHandler.end;
+                       this.contents[localContentsOffset++] = (byte) (end >> 8);
+                       this.contents[localContentsOffset++] = (byte) end;
+                       int handlerPC = exceptionHandler.position;
+                       this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+                       this.contents[localContentsOffset++] = (byte) handlerPC;
+                       if (exceptionHandler.exceptionType == null) {
+                               // any exception handler
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = 0;
+                       } else {
+                               int nameIndex;
+                               if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
+                                       /* represents ClassNotFoundException, see class literal access*/
+                                       nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+                               } else {
+                                       nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                       }
+               }
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributeNumber = 0;
+               // leave two bytes for the attribute_length
+               localContentsOffset += 2;
+
+               // first we handle the linenumber attribute
+               if (codeStream.generateLineNumberAttributes) {
+                       /* Create and add the line number attribute (used for debugging) 
+                        * Build the pairs of:
+                        *      (bytecodePC lineNumber)
+                        * according to the table of start line indexes and the pcToSourceMap table
+                        * contained into the codestream
+                        */
+                       int[] pcToSourceMapTable;
+                       if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
+                               && (codeStream.pcToSourceMapSize != 0)) {
+                               int lineNumberNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                               if (localContentsOffset + 8 >= this.contents.length) {
+                                       resizeContents(8);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                               int lineNumberTableOffset = localContentsOffset;
+                               localContentsOffset += 6;
+                               // leave space for attribute_length and line_number_table_length
+                               int numberOfEntries = 0;
+                               int length = codeStream.pcToSourceMapSize;
+                               for (int i = 0; i < length;) {
+                                       // write the entry
+                                       if (localContentsOffset + 4 >= this.contents.length) {
+                                               resizeContents(4);
+                                       }
+                                       int pc = pcToSourceMapTable[i++];
+                                       this.contents[localContentsOffset++] = (byte) (pc >> 8);
+                                       this.contents[localContentsOffset++] = (byte) pc;
+                                       int lineNumber = pcToSourceMapTable[i++];
+                                       this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
+                                       this.contents[localContentsOffset++] = (byte) lineNumber;
+                                       numberOfEntries++;
+                               }
+                               // now we change the size of the line number attribute
+                               int lineNumberAttr_length = numberOfEntries * 4 + 2;
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+                               this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+                               this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+                               this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
+                               attributeNumber++;
+                       }
+               }
+               // then we do the local variable attribute
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       int localVariableTableOffset = localContentsOffset;
+                       int numberOfEntries = 0;
+                       int localVariableNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
+                       localContentsOffset += 6;
+                       // leave space for attribute_length and local_variable_table_length
+                       int nameIndex;
+                       int descriptorIndex;
+                       if (!codeStream.methodDeclaration.isStatic()) {
+                               numberOfEntries++;
+                               if (localContentsOffset + 10 >= this.contents.length) {
+                                       resizeContents(10);
+                               }
+                               this.contents[localContentsOffset++] = 0; // the startPC for this is always 0
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                               this.contents[localContentsOffset++] = (byte) code_length;
+                               nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                               descriptorIndex =
+                                       constantPool.literalIndex(
+                                               codeStream.methodDeclaration.binding.declaringClass.signature());
+                               this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                               this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0
+                               this.contents[localContentsOffset++] = 0;
+                       }
+                       for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+                               LocalVariableBinding localVariable = codeStream.locals[i];
+                               for (int j = 0; j < localVariable.initializationCount; j++) {
+                                       int startPC = localVariable.initializationPCs[j << 1];
+                                       int endPC = localVariable.initializationPCs[(j << 1) + 1];
+                                       if (startPC != endPC) { // only entries for non zero length
+                                               if (endPC == -1) {
+                                                       localVariable.declaringScope.problemReporter().abortDueToInternalError(
+                                                               Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
+                                                               (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
+                                               }
+                                               if (localContentsOffset + 10 >= this.contents.length) {
+                                                       resizeContents(10);
+                                               }
+                                               // now we can safely add the local entry
+                                               numberOfEntries++;
+                                               this.contents[localContentsOffset++] = (byte) (startPC >> 8);
+                                               this.contents[localContentsOffset++] = (byte) startPC;
+                                               int length = endPC - startPC;
+                                               this.contents[localContentsOffset++] = (byte) (length >> 8);
+                                               this.contents[localContentsOffset++] = (byte) length;
+                                               nameIndex = constantPool.literalIndex(localVariable.name);
+                                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                                               descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                               this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                                               int resolvedPosition = localVariable.resolvedPosition;
+                                               this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                               this.contents[localContentsOffset++] = (byte) resolvedPosition;
+                                       }
+                               }
+                       }
+                       int value = numberOfEntries * 10 + 2;
+                       localVariableTableOffset += 2;
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 24);
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 16);
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 8);
+                       this.contents[localVariableTableOffset++] = (byte) value;
+                       this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                       this.contents[localVariableTableOffset] = (byte) numberOfEntries;
+                       attributeNumber++;
+               }
+               // update the number of attributes
+               // ensure first that there is enough space available inside the localContents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+
+               // update the attribute length
+               int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+               contentsOffset = localContentsOffset;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForClinit(int codeAttributeOffset) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents byte array before we started to write
+               // any information about the codeAttribute
+               // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+               // to get the right position, 6 for the max_stack etc...
+               int code_length = codeStream.position;
+               if (code_length > 65535) {
+                       codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+                               codeStream.methodDeclaration.scope.referenceType());
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int max_stack = codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+
+               // write the exception table
+               int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+               ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
+               int exSize = exceptionHandlersNumber * 8 + 2;
+               if (exSize + localContentsOffset >= this.contents.length) {
+                       resizeContents(exSize);
+               }
+               // there is no exception table, so we need to offset by 2 the current offset and move 
+               // on the attribute generation
+               this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
+               this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
+               for (int i = 0; i < exceptionHandlersNumber; i++) {
+                       ExceptionLabel exceptionHandler = exceptionHandlers[i];
+                       int start = exceptionHandler.start;
+                       this.contents[localContentsOffset++] = (byte) (start >> 8);
+                       this.contents[localContentsOffset++] = (byte) start;
+                       int end = exceptionHandler.end;
+                       this.contents[localContentsOffset++] = (byte) (end >> 8);
+                       this.contents[localContentsOffset++] = (byte) end;
+                       int handlerPC = exceptionHandler.position;
+                       this.contents[localContentsOffset++] = (byte) (handlerPC >> 8);
+                       this.contents[localContentsOffset++] = (byte) handlerPC;
+                       if (exceptionHandler.exceptionType == null) {
+                               // any exception handler
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = 0;
+                       } else {
+                               int nameIndex;
+                               if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
+                                       /* represents denote ClassNotFoundException, see class literal access*/
+                                       nameIndex = constantPool.literalIndexForJavaLangClassNotFoundException();
+                               } else {
+                                       nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                       }
+               }
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributeNumber = 0;
+               // leave two bytes for the attribute_length
+               localContentsOffset += 2;
+
+               // first we handle the linenumber attribute
+               if (codeStream.generateLineNumberAttributes) {
+                       /* Create and add the line number attribute (used for debugging) 
+                        * Build the pairs of:
+                        *      (bytecodePC lineNumber)
+                        * according to the table of start line indexes and the pcToSourceMap table
+                        * contained into the codestream
+                        */
+                       int[] pcToSourceMapTable;
+                       if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
+                               && (codeStream.pcToSourceMapSize != 0)) {
+                               int lineNumberNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                               if (localContentsOffset + 8 >= this.contents.length) {
+                                       resizeContents(8);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                               int lineNumberTableOffset = localContentsOffset;
+                               localContentsOffset += 6;
+                               // leave space for attribute_length and line_number_table_length
+                               int numberOfEntries = 0;
+                               int length = codeStream.pcToSourceMapSize;
+                               for (int i = 0; i < length;) {
+                                       // write the entry
+                                       if (localContentsOffset + 4 >= this.contents.length) {
+                                               resizeContents(4);
+                                       }
+                                       int pc = pcToSourceMapTable[i++];
+                                       this.contents[localContentsOffset++] = (byte) (pc >> 8);
+                                       this.contents[localContentsOffset++] = (byte) pc;
+                                       int lineNumber = pcToSourceMapTable[i++];
+                                       this.contents[localContentsOffset++] = (byte) (lineNumber >> 8);
+                                       this.contents[localContentsOffset++] = (byte) lineNumber;
+                                       numberOfEntries++;
+                               }
+                               // now we change the size of the line number attribute
+                               int lineNumberAttr_length = numberOfEntries * 4 + 2;
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
+                               this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
+                               this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
+                               this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
+                               this.contents[lineNumberTableOffset++] = (byte) numberOfEntries;
+                               attributeNumber++;
+                       }
+               }
+               // then we do the local variable attribute
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       int localVariableTableOffset = localContentsOffset;
+                       int numberOfEntries = 0;
+                       //              codeAttribute.addLocalVariableTableAttribute(this);
+                       if ((codeStream.pcToSourceMap != null)
+                               && (codeStream.pcToSourceMapSize != 0)) {
+                               int localVariableNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                               if (localContentsOffset + 8 >= this.contents.length) {
+                                       resizeContents(8);
+                               }
+                               this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
+                               localContentsOffset += 6;
+                               // leave space for attribute_length and local_variable_table_length
+                               int nameIndex;
+                               int descriptorIndex;
+                               for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+                                       LocalVariableBinding localVariable = codeStream.locals[i];
+                                       for (int j = 0; j < localVariable.initializationCount; j++) {
+                                               int startPC = localVariable.initializationPCs[j << 1];
+                                               int endPC = localVariable.initializationPCs[(j << 1) + 1];
+                                               if (startPC != endPC) { // only entries for non zero length
+                                                       if (endPC == -1) {
+                                                               localVariable.declaringScope.problemReporter().abortDueToInternalError(
+                                                                       Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
+                                                                       (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
+                                                       }
+                                                       if (localContentsOffset + 10 >= this.contents.length) {
+                                                               resizeContents(10);
+                                                       }
+                                                       // now we can safely add the local entry
+                                                       numberOfEntries++;
+                                                       this.contents[localContentsOffset++] = (byte) (startPC >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) startPC;
+                                                       int length = endPC - startPC;
+                                                       this.contents[localContentsOffset++] = (byte) (length >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) length;
+                                                       nameIndex = constantPool.literalIndex(localVariable.name);
+                                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                                       descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                                       this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                                                       int resolvedPosition = localVariable.resolvedPosition;
+                                                       this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) resolvedPosition;
+                                               }
+                                       }
+                               }
+                               int value = numberOfEntries * 10 + 2;
+                               localVariableTableOffset += 2;
+                               this.contents[localVariableTableOffset++] = (byte) (value >> 24);
+                               this.contents[localVariableTableOffset++] = (byte) (value >> 16);
+                               this.contents[localVariableTableOffset++] = (byte) (value >> 8);
+                               this.contents[localVariableTableOffset++] = (byte) value;
+                               this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                               this.contents[localVariableTableOffset] = (byte) numberOfEntries;
+                               attributeNumber++;
+                       }
+               }
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+               // update the attribute length
+               int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+               contentsOffset = localContentsOffset;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        * @param startLineIndexes int[]
+        */
+       public void completeCodeAttributeForClinit(
+               int codeAttributeOffset,
+               int[] startLineIndexes) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents byte array before we started to write
+               // any information about the codeAttribute
+               // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+               // to get the right position, 6 for the max_stack etc...
+               int code_length = codeStream.position;
+               if (code_length > 65535) {
+                       codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(
+                               codeStream.methodDeclaration.scope.referenceType());
+               }
+               if (localContentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int max_stack = codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+
+               // write the exception table
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributeNumber = 0; // leave two bytes for the attribute_length
+               localContentsOffset += 2; // first we handle the linenumber attribute
+
+               // first we handle the linenumber attribute
+               if (codeStream.generateLineNumberAttributes) {
+                       if (localContentsOffset + 20 >= this.contents.length) {
+                               resizeContents(20);
+                       }                       
+                       /* Create and add the line number attribute (used for debugging) 
+                           * Build the pairs of:
+                           * (bytecodePC lineNumber)
+                           * according to the table of start line indexes and the pcToSourceMap table
+                           * contained into the codestream
+                           */
+                       int lineNumberNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                       this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 6;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 1;
+                       // first entry at pc = 0
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
+                       this.contents[localContentsOffset++] = (byte) problemLine;
+                       // now we change the size of the line number attribute
+                       attributeNumber++;
+               }
+               // then we do the local variable attribute
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       int localVariableNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 2;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       attributeNumber++;
+               }
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+               // update the attribute length
+               int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+               contentsOffset = localContentsOffset;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForProblemMethod(
+               AbstractMethodDeclaration method,
+               MethodBinding binding,
+               int codeAttributeOffset,
+               int[] startLineIndexes) {
+               // reinitialize the localContents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc...
+               int max_stack = codeStream.stackMax;
+               this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               this.contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = codeStream.maxLocals;
+               this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               this.contents[codeAttributeOffset + 9] = (byte) max_locals;
+               int code_length = codeStream.position;
+               this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               this.contents[codeAttributeOffset + 13] = (byte) code_length;
+               // write the exception table
+               if (localContentsOffset + 50 >= this.contents.length) {
+                       resizeContents(50);
+               }
+
+               // write the exception table
+               this.contents[localContentsOffset++] = 0;
+               this.contents[localContentsOffset++] = 0;
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributeNumber = 0; // leave two bytes for the attribute_length
+               localContentsOffset += 2; // first we handle the linenumber attribute
+
+               if (codeStream.generateLineNumberAttributes) {
+                       if (localContentsOffset + 20 >= this.contents.length) {
+                               resizeContents(20);
+                       }
+                       /* Create and add the line number attribute (used for debugging) 
+                           * Build the pairs of:
+                           * (bytecodePC lineNumber)
+                           * according to the table of start line indexes and the pcToSourceMap table
+                           * contained into the codestream
+                           */
+                       int lineNumberNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                       this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 6;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 1;
+                       if (problemLine == 0) {
+                               problemLine = searchLineNumber(startLineIndexes, binding.sourceStart());
+                       }
+                       // first entry at pc = 0
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = 0;
+                       this.contents[localContentsOffset++] = (byte) (problemLine >> 8);
+                       this.contents[localContentsOffset++] = (byte) problemLine;
+                       // now we change the size of the line number attribute
+                       attributeNumber++;
+               }
+               // then we do the local variable attribute
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       // compute the resolved position for the arguments of the method
+                       int argSize;
+                       int localVariableTableOffset = localContentsOffset;
+                       int numberOfEntries = 0;
+                       //              codeAttribute.addLocalVariableTableAttribute(this);
+                       int localVariableNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                       this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
+                       localContentsOffset += 6;
+                       // leave space for attribute_length and local_variable_table_length
+                       int descriptorIndex;
+                       if (!codeStream.methodDeclaration.isStatic()) {
+                               numberOfEntries++;
+                               if (localContentsOffset + 10 >= this.contents.length) {
+                                       resizeContents(10);
+                               }
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                               this.contents[localContentsOffset++] = (byte) code_length;
+                               int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                               descriptorIndex =
+                                       constantPool.literalIndex(
+                                               codeStream.methodDeclaration.binding.declaringClass.signature());
+                               this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                               // the resolved position for this is always 0
+                               this.contents[localContentsOffset++] = 0;
+                               this.contents[localContentsOffset++] = 0;
+                       }
+                       if (binding.isConstructor()) {
+                               ReferenceBinding declaringClass = binding.declaringClass;
+                               if (declaringClass.isNestedType()) {
+                                       NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
+                                       argSize = methodDeclaringClass.enclosingInstancesSlotSize;
+                                       SyntheticArgumentBinding[] syntheticArguments;
+                                       if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances())
+                                               != null) {
+                                               for (int i = 0, max = syntheticArguments.length; i < max; i++) {
+                                                       LocalVariableBinding localVariable = syntheticArguments[i];
+                                                       if (localContentsOffset + 10 >= this.contents.length) {
+                                                               resizeContents(10);
+                                                       }
+                                                       // now we can safely add the local entry
+                                                       numberOfEntries++;
+                                                       this.contents[localContentsOffset++] = 0;
+                                                       this.contents[localContentsOffset++] = 0;
+                                                       this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) code_length;
+                                                       int nameIndex = constantPool.literalIndex(localVariable.name);
+                                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                                       descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                                       this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                                                       int resolvedPosition = localVariable.resolvedPosition;
+                                                       this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                                       this.contents[localContentsOffset++] = (byte) resolvedPosition;
+                                               }
+                                       }
+                               } else {
+                                       argSize = 1;
+                               }
+                       } else {
+                               argSize = binding.isStatic() ? 0 : 1;
+                       }
+                       if (method.binding != null) {
+                               TypeBinding[] parameters = method.binding.parameters;
+                               Argument[] arguments = method.arguments;
+                               if ((parameters != null) && (arguments != null)) {
+                                       for (int i = 0, max = parameters.length; i < max; i++) {
+                                               TypeBinding argumentBinding = parameters[i];
+                                               if (localContentsOffset + 10 >= this.contents.length) {
+                                                       resizeContents(10);
+                                               }
+                                               // now we can safely add the local entry
+                                               numberOfEntries++;
+                                               this.contents[localContentsOffset++] = 0;
+                                               this.contents[localContentsOffset++] = 0;
+                                               this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                                               this.contents[localContentsOffset++] = (byte) code_length;
+                                               int nameIndex = constantPool.literalIndex(arguments[i].name);
+                                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) nameIndex;
+                                               descriptorIndex = constantPool.literalIndex(argumentBinding.signature());
+                                               this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                               this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                                               int resolvedPosition = argSize;
+                                               if ((argumentBinding == BaseTypes.LongBinding)
+                                                       || (argumentBinding == BaseTypes.DoubleBinding))
+                                                       argSize += 2;
+                                               else
+                                                       argSize++;
+                                               this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                               this.contents[localContentsOffset++] = (byte) resolvedPosition;
+                                       }
+                               }
+                       }
+                       int value = numberOfEntries * 10 + 2;
+                       localVariableTableOffset += 2;
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 24);
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 16);
+                       this.contents[localVariableTableOffset++] = (byte) (value >> 8);
+                       this.contents[localVariableTableOffset++] = (byte) value;
+                       this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                       this.contents[localVariableTableOffset] = (byte) numberOfEntries;
+                       attributeNumber++;
+               }
+               // update the number of attributes// ensure first that there is enough space available inside the localContents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               this.contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+               this.contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+               // update the attribute length
+               int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+               this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+               contentsOffset = localContentsOffset;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method completes the creation of the code attribute by setting
+        * - the attribute_length
+        * - max_stack
+        * - max_locals
+        * - code_length
+        * - exception table
+        * - and debug attributes if necessary.
+        *
+        * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
+        * @param codeAttributeOffset <CODE>int</CODE>
+        */
+       public void completeCodeAttributeForSyntheticAccessMethod(
+               SyntheticAccessMethodBinding binding,
+               int codeAttributeOffset,
+               int[] startLineIndexes) {
+               // reinitialize the contents with the byte modified by the code stream
+               this.contents = codeStream.bCodeStream;
+               int localContentsOffset = codeStream.classFileOffset;
+               // codeAttributeOffset is the position inside contents byte array before we started to write
+               // any information about the codeAttribute
+               // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
+               // to get the right position, 6 for the max_stack etc...
+               int max_stack = codeStream.stackMax;
+               contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
+               contents[codeAttributeOffset + 7] = (byte) max_stack;
+               int max_locals = codeStream.maxLocals;
+               contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
+               contents[codeAttributeOffset + 9] = (byte) max_locals;
+               int code_length = codeStream.position;
+               contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
+               contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
+               contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
+               contents[codeAttributeOffset + 13] = (byte) code_length;
+               if ((localContentsOffset + 40) >= this.contents.length) {
+                       resizeContents(40);
+               }
+               // there is no exception table, so we need to offset by 2 the current offset and move 
+               // on the attribute generation
+               contents[localContentsOffset++] = 0;
+               contents[localContentsOffset++] = 0;
+               // debug attributes
+               int codeAttributeAttributeOffset = localContentsOffset;
+               int attributeNumber = 0;
+               // leave two bytes for the attribute_length
+               localContentsOffset += 2;
+
+               // first we handle the linenumber attribute
+               if (codeStream.generateLineNumberAttributes) {
+                       int index = 0;
+                       int lineNumberNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName);
+                       contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
+                       contents[localContentsOffset++] = (byte) lineNumberNameIndex;
+                       int lineNumberTableOffset = localContentsOffset;
+                       localContentsOffset += 6;
+                       // leave space for attribute_length and line_number_table_length
+                       // Seems like do would be better, but this preserves the existing behavior.
+                       index = searchLineNumber(startLineIndexes, binding.sourceStart);
+                       contents[localContentsOffset++] = 0;
+                       contents[localContentsOffset++] = 0;
+                       contents[localContentsOffset++] = (byte) (index >> 8);
+                       contents[localContentsOffset++] = (byte) index;
+                       // now we change the size of the line number attribute
+                       contents[lineNumberTableOffset++] = 0;
+                       contents[lineNumberTableOffset++] = 0;
+                       contents[lineNumberTableOffset++] = 0;
+                       contents[lineNumberTableOffset++] = 6;
+                       contents[lineNumberTableOffset++] = 0;
+                       contents[lineNumberTableOffset++] = 1;
+                       attributeNumber++;
+               }
+               // then we do the local variable attribute
+               if (codeStream.generateLocalVariableTableAttributes) {
+                       int localVariableTableOffset = localContentsOffset;
+                       int numberOfEntries = 0;
+                       int localVariableNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
+                       if (localContentsOffset + 8 > this.contents.length) {
+                               resizeContents(8);
+                       }
+                       contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
+                       contents[localContentsOffset++] = (byte) localVariableNameIndex;
+                       localContentsOffset += 6;
+                       // leave space for attribute_length and local_variable_table_length
+                       int nameIndex;
+                       int descriptorIndex;
+                       for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+                               LocalVariableBinding localVariable = codeStream.locals[i];
+                               for (int j = 0; j < localVariable.initializationCount; j++) {
+                                       int startPC = localVariable.initializationPCs[j << 1];
+                                       int endPC = localVariable.initializationPCs[(j << 1) + 1];
+                                       if (startPC != endPC) { // only entries for non zero length
+                                               if (endPC == -1) {
+                                                       localVariable.declaringScope.problemReporter().abortDueToInternalError(
+                                                               Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
+                                                               (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
+                                               }
+                                               if (localContentsOffset + 10 > this.contents.length) {
+                                                       resizeContents(10);
+                                               }
+                                               // now we can safely add the local entry
+                                               numberOfEntries++;
+                                               contents[localContentsOffset++] = (byte) (startPC >> 8);
+                                               contents[localContentsOffset++] = (byte) startPC;
+                                               int length = endPC - startPC;
+                                               contents[localContentsOffset++] = (byte) (length >> 8);
+                                               contents[localContentsOffset++] = (byte) length;
+                                               nameIndex = constantPool.literalIndex(localVariable.name);
+                                               contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                               contents[localContentsOffset++] = (byte) nameIndex;
+                                               descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                               contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                               contents[localContentsOffset++] = (byte) descriptorIndex;
+                                               int resolvedPosition = localVariable.resolvedPosition;
+                                               contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                               contents[localContentsOffset++] = (byte) resolvedPosition;
+                                       }
+                               }
+                       }
+                       int value = numberOfEntries * 10 + 2;
+                       localVariableTableOffset += 2;
+                       contents[localVariableTableOffset++] = (byte) (value >> 24);
+                       contents[localVariableTableOffset++] = (byte) (value >> 16);
+                       contents[localVariableTableOffset++] = (byte) (value >> 8);
+                       contents[localVariableTableOffset++] = (byte) value;
+                       contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
+                       contents[localVariableTableOffset] = (byte) numberOfEntries;
+                       attributeNumber++;
+               }
+               // update the number of attributes
+               // ensure first that there is enough space available inside the contents array
+               if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
+                       resizeContents(2);
+               }
+               contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
+
+               // update the attribute length
+               int codeAttributeLength = localContentsOffset - (codeAttributeOffset + 6);
+               contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
+               contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
+               contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
+               contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
+               contentsOffset = localContentsOffset;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Complete the creation of a method info by setting up the number of attributes at the right offset.
+        *
+        * @param methodAttributeOffset <CODE>int</CODE>
+        * @param attributeNumber <CODE>int</CODE> 
+        */
+       public void completeMethodInfo(
+               int methodAttributeOffset,
+               int attributeNumber) {
+               // update the number of attributes
+               contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
+               contents[methodAttributeOffset] = (byte) attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Request the creation of a ClassFile compatible representation of a problematic type
+        *
+        * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
+        * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+        */
+       public static void createProblemType(
+               TypeDeclaration typeDeclaration,
+               CompilationResult unitResult) {
+               SourceTypeBinding typeBinding = typeDeclaration.binding;
+               ClassFile classFile = new ClassFile(typeBinding, null, true);
+
+               // TODO (olivier) handle cases where a field cannot be generated (name too long)
+               // TODO (olivier) handle too many methods
+               // inner attributes
+               if (typeBinding.isMemberType())
+                       classFile.recordEnclosingTypeAttributes(typeBinding);
+
+               // add its fields
+               FieldBinding[] fields = typeBinding.fields;
+               if ((fields != null) && (fields != NoFields)) {
+                       for (int i = 0, max = fields.length; i < max; i++) {
+                               if (fields[i].constant == null) {
+                                       FieldReference.getConstantFor(fields[i], null, false, null);
+                               }
+                       }
+                       classFile.addFieldInfos();
+               } else {
+                       // we have to set the number of fields to be equals to 0
+                       classFile.contents[classFile.contentsOffset++] = 0;
+                       classFile.contents[classFile.contentsOffset++] = 0;
+               }
+               // leave some space for the methodCount
+               classFile.setForMethodInfos();
+               // add its user defined methods
+               MethodBinding[] methods = typeBinding.methods;
+               AbstractMethodDeclaration[] methodDeclarations = typeDeclaration.methods;
+               int maxMethodDecl = methodDeclarations == null ? 0 : methodDeclarations.length;
+               int problemsLength;
+               IProblem[] problems = unitResult.getErrors();
+               if (problems == null) {
+                       problems = new IProblem[0];
+               }
+               IProblem[] problemsCopy = new IProblem[problemsLength = problems.length];
+               System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
+               if (methods != null) {
+                       if (typeBinding.isInterface()) {
+                               // we cannot create problem methods for an interface. So we have to generate a clinit
+                               // which should contain all the problem
+                               classFile.addProblemClinit(problemsCopy);
+                               for (int i = 0, max = methods.length; i < max; i++) {
+                                       MethodBinding methodBinding;
+                                       if ((methodBinding = methods[i]) != null) {
+                                               // find the corresponding method declaration
+                                               for (int j = 0; j < maxMethodDecl; j++) {
+                                                       if ((methodDeclarations[j] != null)
+                                                               && (methodDeclarations[j].binding == methods[i])) {
+                                                               if (!methodBinding.isConstructor()) {
+                                                                       classFile.addAbstractMethod(methodDeclarations[j], methodBinding);
+                                                               }
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       } else {
+                               for (int i = 0, max = methods.length; i < max; i++) {
+                                       MethodBinding methodBinding;
+                                       if ((methodBinding = methods[i]) != null) {
+                                               // find the corresponding method declaration
+                                               for (int j = 0; j < maxMethodDecl; j++) {
+                                                       if ((methodDeclarations[j] != null)
+                                                               && (methodDeclarations[j].binding == methods[i])) {
+                                                               AbstractMethodDeclaration methodDecl;
+                                                               if ((methodDecl = methodDeclarations[j]).isConstructor()) {
+                                                                       classFile.addProblemConstructor(methodDecl, methodBinding, problemsCopy);
+                                                               } else {
+                                                                       classFile.addProblemMethod(methodDecl, methodBinding, problemsCopy);
+                                                               }
+                                                               break;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       // add abstract methods
+                       classFile.addDefaultAbstractMethods();
+               }
+               // propagate generation of (problem) member types
+               if (typeDeclaration.memberTypes != null) {
+                       for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
+                               TypeDeclaration memberType = typeDeclaration.memberTypes[i];
+                               if (memberType.binding != null) {
+                                       classFile.recordNestedMemberAttribute(memberType.binding);
+                                       ClassFile.createProblemType(memberType, unitResult);
+                               }
+                       }
+               }
+               classFile.addAttributes();
+               unitResult.record(typeBinding.constantPoolName(), classFile);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods returns a char[] representing the file name of the receiver
+        *
+        * @return char[]
+        */
+       public char[] fileName() {
+               return constantPool.UTF8Cache.returnKeyFor(1);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a code attribute.
+        * - the index inside the constant pool for the attribute name ("Code")
+        * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
+        */
+       public void generateCodeAttributeHeader() {
+               if (contentsOffset + 20 >= this.contents.length) {
+                       resizeContents(20);
+               }
+               int constantValueNameIndex =
+                       constantPool.literalIndex(AttributeNamesConstants.CodeName);
+               contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
+               contents[contentsOffset++] = (byte) constantValueNameIndex;
+               // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
+               contentsOffset += 12;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the attributes of a code attribute.
+        * They could be:
+        * - an exception attribute for each try/catch found inside the method
+        * - a deprecated attribute
+        * - a synthetic attribute for synthetic access methods
+        *
+        * It returns the number of attributes created for the code attribute.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        * @return <CODE>int</CODE>
+        */
+       public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+               // leave two bytes for the attribute_number
+               contentsOffset += 2;
+               // now we can handle all the attribute for that method info:
+               // it could be:
+               // - a CodeAttribute
+               // - a ExceptionAttribute
+               // - a DeprecatedAttribute
+               // - a SyntheticAttribute
+
+               // Exception attribute
+               ReferenceBinding[] thrownsExceptions;
+               int attributeNumber = 0;
+               if ((thrownsExceptions = methodBinding.thrownExceptions) != NoExceptions) {
+                       // The method has a throw clause. So we need to add an exception attribute
+                       // check that there is enough space to write all the bytes for the exception attribute
+                       int length = thrownsExceptions.length;
+                       int exSize = 8 + length * 2;
+                       if (exSize + contentsOffset >= this.contents.length) {
+                               resizeContents(exSize);
+                       }
+                       int exceptionNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.ExceptionsName);
+                       contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) exceptionNameIndex;
+                       // The attribute length = length * 2 + 2 in case of a exception attribute
+                       int attributeLength = length * 2 + 2;
+                       contents[contentsOffset++] = (byte) (attributeLength >> 24);
+                       contents[contentsOffset++] = (byte) (attributeLength >> 16);
+                       contents[contentsOffset++] = (byte) (attributeLength >> 8);
+                       contents[contentsOffset++] = (byte) attributeLength;
+                       contents[contentsOffset++] = (byte) (length >> 8);
+                       contents[contentsOffset++] = (byte) length;
+                       for (int i = 0; i < length; i++) {
+                               int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+                               contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
+                               contents[contentsOffset++] = (byte) exceptionIndex;
+                       }
+                       attributeNumber++;
+               }
+               if (methodBinding.isDeprecated()) {
+                       // Deprecated attribute
+                       // Check that there is enough space to write the deprecated attribute
+                       if (contentsOffset + 6 >= this.contents.length) {
+                               resizeContents(6);
+                       }
+                       int deprecatedAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
+                       contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
+                       // the length of a deprecated attribute is equals to 0
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+
+                       attributeNumber++;
+               }
+               if (this.targetJDK < ClassFileConstants.JDK1_5 && methodBinding.isSynthetic()) {
+                       // Synthetic attribute
+                       // Check that there is enough space to write the deprecated attribute
+                       if (contentsOffset + 6 >= this.contents.length) {
+                               resizeContents(6);
+                       }
+                       int syntheticAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
+                       contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
+                       // the length of a synthetic attribute is equals to 0
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+
+                       attributeNumber++;
+               }
+               return attributeNumber;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a method info:
+        * The header consists in:
+        * - the access flags
+        * - the name index of the method name inside the constant pool
+        * - the descriptor index of the signature of the method inside the constant pool.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        */
+       public void generateMethodInfoHeader(MethodBinding methodBinding) {
+               generateMethodInfoHeader(methodBinding, methodBinding.modifiers);
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the header of a method info:
+        * The header consists in:
+        * - the access flags
+        * - the name index of the method name inside the constant pool
+        * - the descriptor index of the signature of the method inside the constant pool.
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
+        * @param accessFlags the access flags
+        */
+       public void generateMethodInfoHeader(MethodBinding methodBinding, int accessFlags) {
+               // check that there is enough space to write all the bytes for the method info corresponding
+               // to the @methodBinding
+               methodCount++; // add one more method
+               if (contentsOffset + 10 >= this.contents.length) {
+                       resizeContents(10);
+               }
+               if (targetJDK < ClassFileConstants.JDK1_5) {
+                   // pre 1.5, synthetic was an attribute, not a modifier
+                   accessFlags &= ~AccSynthetic;
+               }
+               if (methodBinding.isRequiredToClearPrivateModifier()) {
+                       accessFlags &= ~AccPrivate;
+               }
+               contents[contentsOffset++] = (byte) (accessFlags >> 8);
+               contents[contentsOffset++] = (byte) accessFlags;
+               int nameIndex = constantPool.literalIndex(methodBinding.selector);
+               contents[contentsOffset++] = (byte) (nameIndex >> 8);
+               contents[contentsOffset++] = (byte) nameIndex;
+               int descriptorIndex = constantPool.literalIndex(methodBinding.signature());
+               contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+               contents[contentsOffset++] = (byte) descriptorIndex;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * That method generates the method info header of a clinit:
+        * The header consists in:
+        * - the access flags (always default access + static)
+        * - the name index of the method name (always <clinit>) inside the constant pool 
+        * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
+        */
+       public void generateMethodInfoHeaderForClinit() {
+               // check that there is enough space to write all the bytes for the method info corresponding
+               // to the @methodBinding
+               methodCount++; // add one more method
+               if (contentsOffset + 10 >= this.contents.length) {
+                       resizeContents(10);
+               }
+               contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
+               contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
+               int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
+               contents[contentsOffset++] = (byte) (nameIndex >> 8);
+               contents[contentsOffset++] = (byte) nameIndex;
+               int descriptorIndex =
+                       constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
+               contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
+               contents[contentsOffset++] = (byte) descriptorIndex;
+               // We know that we won't get more than 1 attribute: the code attribute
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 1;
+       }
+
+       /**
+        * EXTERNAL API
+        * Answer the actual bytes of the class file
+        *
+        * This method encodes the receiver structure into a byte array which is the content of the classfile.
+        * Returns the byte array that represents the encoded structure of the receiver.
+        *
+        * @return byte[]
+        */
+       public byte[] getBytes() {
+               byte[] fullContents = new byte[headerOffset + contentsOffset];
+               System.arraycopy(header, 0, fullContents, 0, headerOffset);
+               System.arraycopy(contents, 0, fullContents, headerOffset, contentsOffset);
+               return fullContents;
+       }
+
+       /**
+        * EXTERNAL API
+        * Answer the compound name of the class file.
+        * @return char[][]
+        * e.g. {{java}, {util}, {Hashtable}}.
+        */
+       public char[][] getCompoundName() {
+               return CharOperation.splitOn('/', fileName());
+       }
+
+       protected void initByteArrays() {
+               LookupEnvironment env = this.referenceBinding.scope.environment();
+               synchronized (env) {
+                       if (env.sharedArraysUsed) {
+                               this.ownSharedArrays = false;
+                               int members = referenceBinding.methods().length + referenceBinding.fields().length;
+                               this.header = new byte[INITIAL_HEADER_SIZE];
+                               this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE];
+                       } else {
+                               this.ownSharedArrays = env.sharedArraysUsed = true;
+                               this.header = env.sharedClassFileHeader;
+                               this.contents = env.sharedClassFileContents;
+                       }
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
+        * for all inner types of the receiver.
+        * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
+        */
+       public ClassFile outerMostEnclosingClassFile() {
+               ClassFile current = this;
+               while (current.enclosingClassFile != null)
+                       current = current.enclosingClassFile;
+               return current;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+        * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+        *
+        * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+        */
+       public void recordEnclosingTypeAttributes(ReferenceBinding binding) {
+               // add all the enclosing types
+               ReferenceBinding enclosingType = referenceBinding.enclosingType();
+               int depth = 0;
+               while (enclosingType != null) {
+                       depth++;
+                       enclosingType = enclosingType.enclosingType();
+               }
+               enclosingType = referenceBinding;
+               ReferenceBinding enclosingTypes[];
+               if (depth >= 2) {
+                       enclosingTypes = new ReferenceBinding[depth];
+                       for (int i = depth - 1; i >= 0; i--) {
+                               enclosingTypes[i] = enclosingType;
+                               enclosingType = enclosingType.enclosingType();
+                       }
+                       for (int i = 0; i < depth; i++) {
+                               addInnerClasses(enclosingTypes[i]);
+                       }
+               } else {
+                       addInnerClasses(referenceBinding);
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+        * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+        *
+        * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+        */
+       public void recordNestedLocalAttribute(ReferenceBinding binding) {
+               // add all the enclosing types
+               ReferenceBinding enclosingType = referenceBinding.enclosingType();
+               int depth = 0;
+               while (enclosingType != null) {
+                       depth++;
+                       enclosingType = enclosingType.enclosingType();
+               }
+               enclosingType = referenceBinding;
+               ReferenceBinding enclosingTypes[];
+               if (depth >= 2) {
+                       enclosingTypes = new ReferenceBinding[depth];
+                       for (int i = depth - 1; i >= 0; i--) {
+                               enclosingTypes[i] = enclosingType;
+                               enclosingType = enclosingType.enclosingType();
+                       }
+                       for (int i = 0; i < depth; i++)
+                               addInnerClasses(enclosingTypes[i]);
+               } else {
+                       addInnerClasses(binding);
+               }
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This is used to store a new inner class. It checks that the binding @binding doesn't already exist inside the
+        * collection of inner classes. Add all the necessary classes in the right order to fit to the specifications.
+        *
+        * @param binding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding
+        */
+       public void recordNestedMemberAttribute(ReferenceBinding binding) {
+               addInnerClasses(binding);
+       }
+       
+       /**
+        * Resize the pool contents
+        */
+       private final void resizeContents(int minimalSize) {
+               int length = this.contents.length;
+               int toAdd = length;
+               if (toAdd < minimalSize)
+                       toAdd = minimalSize;
+               System.arraycopy(this.contents, 0, this.contents = new byte[length + toAdd], 0, length);
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * Search the line number corresponding to a specific position
+        */
+       public static final int searchLineNumber(
+               int[] startLineIndexes,
+               int position) {
+               // this code is completely useless, but it is the same implementation than
+               // org.eclipse.jdt.internal.compiler.problem.ProblemHandler.searchLineNumber(int[], int)
+               // if (startLineIndexes == null)
+               //      return 1;
+               int length = startLineIndexes.length;
+               if (length == 0)
+                       return 1;
+               int g = 0, d = length - 1;
+               int m = 0;
+               while (g <= d) {
+                       m = (g + d) / 2;
+                       if (position < startLineIndexes[m]) {
+                               d = m - 1;
+                       } else
+                               if (position > startLineIndexes[m]) {
+                                       g = m + 1;
+                               } else {
+                                       return m + 1;
+                               }
+               }
+               if (position < startLineIndexes[m]) {
+                       return m + 1;
+               }
+               return m + 2;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * This methods leaves the space for method counts recording.
+        */
+       public void setForMethodInfos() {
+               // leave some space for the methodCount
+               methodCountOffset = contentsOffset;
+               contentsOffset += 2;
+       }
+
+       /**
+        * INTERNAL USE-ONLY
+        * outputPath is formed like:
+        *         c:\temp\ the last character is a file separator
+        * relativeFileName is formed like:
+        *     java\lang\String.class
+        * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
+        * @param outputPath the output directory
+        * @param relativeFileName java.lang.String
+        * @param contents byte[]
+        * 
+        */
+       public static void writeToDisk(
+               boolean generatePackagesStructure,
+               String outputPath,
+               String relativeFileName,
+               byte[] contents)
+               throws IOException {
+                       
+               BufferedOutputStream output = null;
+               if (generatePackagesStructure) {
+                       output = new BufferedOutputStream(
+                               new FileOutputStream(
+                                               new File(buildAllDirectoriesInto(outputPath, relativeFileName))));
+               } else {
+                       String fileName = null;
+                       char fileSeparatorChar = File.separatorChar;
+                       String fileSeparator = File.separator;
+                       // First we ensure that the outputPath exists
+                       outputPath = outputPath.replace('/', fileSeparatorChar);
+                       // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
+                       int indexOfPackageSeparator = relativeFileName.lastIndexOf(fileSeparatorChar);
+                       if (indexOfPackageSeparator == -1) {
+                               if (outputPath.endsWith(fileSeparator)) {
+                                       fileName = outputPath + relativeFileName;
+                               } else {
+                                       fileName = outputPath + fileSeparator + relativeFileName;
+                               }
+                       } else {
+                               int length = relativeFileName.length();
+                               if (outputPath.endsWith(fileSeparator)) {
+                                       fileName = outputPath + relativeFileName.substring(indexOfPackageSeparator + 1, length);
+                               } else {
+                                       fileName = outputPath + fileSeparator + relativeFileName.substring(indexOfPackageSeparator + 1, length);
+                               }
+                       }
+                       output = new BufferedOutputStream(
+                               new FileOutputStream(
+                                               new File(fileName)));
+               }
+               try {
+                       output.write(contents);
+               } finally {
+                       output.flush();
+                       output.close();
+               }
+       }
+}