import eclipse 3.1 M4 compiler
[org.ibex.tool.git] / src / org / eclipse / jdt / internal / compiler / ClassFile.java
index e575af5..dbed323 100644 (file)
@@ -20,6 +20,7 @@ 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.ReferenceContext;
 import org.eclipse.jdt.internal.compiler.impl.StringConstant;
 import org.eclipse.jdt.internal.compiler.lookup.*;
 import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
@@ -45,29 +46,285 @@ import org.eclipse.jdt.internal.compiler.util.Util;
  */
 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;
+       public static final int INITIAL_CONTENTS_SIZE = 400;
+       public static final int INITIAL_HEADER_SIZE = 1500;
+       public static final int INNER_CLASSES_SIZE = 5;
+
+       /**
+        * 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
+        * 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
+        * 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
+        * 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();
+               }
+       }
+       public CodeStream codeStream;
+       public ConstantPool constantPool;
+       public int constantPoolOffset;
        // the header contains all the bytes till the end of the constant pool
        public byte[] contents;
+       public int contentsOffset;
+       protected boolean creatingProblemType;
+       public ClassFile enclosingClassFile;
+       public byte[] header;
        // that collection contains all the remaining bytes of the .class file
        public int headerOffset;
-       public int contentsOffset;
-       public int constantPoolOffset;
-       public int methodCountOffset;
+       public ReferenceBinding[] innerClassesBindings;
        public int methodCount;
-       protected boolean creatingProblemType;
-       public static final int INITIAL_CONTENTS_SIZE = 400;
-       public static final int INITIAL_HEADER_SIZE = 1500;
+       public int methodCountOffset;
+       public int numberOfInnerClasses;
        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
+       // used to generate private access methods
+       public int produceDebugAttributes;
+       public SourceTypeBinding referenceBinding;
        public long targetJDK;
        
        /**
@@ -91,7 +348,7 @@ public class ClassFile
                ClassFile enclosingClassFile,
                boolean creatingProblemType) {
            
-               referenceBinding = aType;
+               this.referenceBinding = aType;
                initByteArrays();
 
                // generate the magic numbers inside the header
@@ -100,7 +357,8 @@ public class ClassFile
                header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
                header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
                
-               this.targetJDK = referenceBinding.scope.environment().options.targetJDK;
+               final CompilerOptions options = aType.scope.environment().options;
+               this.targetJDK = 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
@@ -139,15 +397,15 @@ public class ClassFile
                // 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);
+               int classNameIndex = constantPool.literalIndexForType(aType.constantPoolName());
                contents[contentsOffset++] = (byte) (classNameIndex >> 8);
                contents[contentsOffset++] = (byte) classNameIndex;
                int superclassNameIndex;
                if (aType.isInterface()) {
-                       superclassNameIndex = constantPool.literalIndexForJavaLangObject();
+                       superclassNameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
                } else {
                        superclassNameIndex =
-                               (aType.superclass == null ? 0 : constantPool.literalIndex(aType.superclass));
+                               (aType.superclass == null ? 0 : constantPool.literalIndexForType(aType.superclass.constantPoolName()));
                }
                contents[contentsOffset++] = (byte) (superclassNameIndex >> 8);
                contents[contentsOffset++] = (byte) superclassNameIndex;
@@ -156,14 +414,14 @@ public class ClassFile
                contents[contentsOffset++] = (byte) (interfacesCount >> 8);
                contents[contentsOffset++] = (byte) interfacesCount;
                for (int i = 0; i < interfacesCount; i++) {
-                       int interfaceIndex = constantPool.literalIndex(superInterfacesBinding[i]);
+                       int interfaceIndex = constantPool.literalIndexForType(superInterfacesBinding[i].constantPoolName());
                        contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
                        contents[contentsOffset++] = (byte) interfaceIndex;
                }
-               produceDebugAttributes = referenceBinding.scope.environment().options.produceDebugAttributes;
+               produceDebugAttributes = options.produceDebugAttributes;
                innerClassesBindings = new ReferenceBinding[INNER_CLASSES_SIZE];
                this.creatingProblemType = creatingProblemType;
-               codeStream = new CodeStream(this);
+               codeStream = new CodeStream(this, this.targetJDK);
 
                // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
                // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
@@ -284,14 +542,14 @@ public class ClassFile
                        for (int i = 0; i < numberOfInnerClasses; i++) {
                                ReferenceBinding innerClass = innerClassesBindings[i];
                                int accessFlags = innerClass.getAccessFlags();
-                               int innerClassIndex = constantPool.literalIndex(innerClass);
+                               int innerClassIndex = constantPool.literalIndexForType(innerClass.constantPoolName());
                                // 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());
+                                       int outerClassIndex = constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName());
                                        contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
                                        contents[contentsOffset++] = (byte) outerClassIndex;
                                } else {
@@ -312,15 +570,86 @@ public class ClassFile
                                // access flag
                                if (innerClass.isAnonymousType()) {
                                        accessFlags |= AccPrivate;
-                               } else
-                                       if (innerClass.isLocalType() && !innerClass.isMemberType()) {
-                                               accessFlags |= AccPrivate;
-                                       }
+                               } else if (innerClass.isLocalType() && !innerClass.isMemberType()) {
+                                       accessFlags |= AccPrivate;
+                               } else if (innerClass.isMemberType() && (innerClass.isInterface() || innerClass.isAnnotationType())) {
+                                       accessFlags |= AccStatic; // implicitely static
+                               }
                                contents[contentsOffset++] = (byte) (accessFlags >> 8);
                                contents[contentsOffset++] = (byte) accessFlags;
                        }
                        attributeNumber++;
                }
+               // add signature attribute
+               char[] genericSignature = referenceBinding.genericSignature();
+               if (genericSignature != null) {
+                       // 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 signatureAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+                       contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+                       // the length of a signature attribute is equals to 2
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 2;
+                       int signatureIndex =
+                               constantPool.literalIndex(genericSignature);
+                       contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+                       contents[contentsOffset++] = (byte) signatureIndex;
+                       attributeNumber++;
+               }
+               if (targetJDK >= ClassFileConstants.JDK1_5
+                               && (this.referenceBinding.isAnonymousType() || this.referenceBinding.isLocalType())) {
+                       // add enclosing method attribute (1.5 mode only)
+                       if (contentsOffset + 10 >= contents.length) {
+                               resizeContents(10);
+                       }
+                       int enclosingMethodAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName);
+                       contents[contentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) enclosingMethodAttributeNameIndex;
+                       // the length of a signature attribute is equals to 2
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 4;
+                       
+                       int enclosingTypeIndex = constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName());
+                       contents[contentsOffset++] = (byte) (enclosingTypeIndex >> 8);
+                       contents[contentsOffset++] = (byte) enclosingTypeIndex;
+                       byte methodIndexByte1 = 0;
+                       byte methodIndexByte2 = 0;
+                       if (this.referenceBinding.scope != null) {
+                               MethodScope methodScope = this.referenceBinding.scope.methodScope();
+                               if (methodScope != null) {
+                                       ReferenceContext referenceContext = methodScope.referenceContext;
+                                       if (referenceContext instanceof AbstractMethodDeclaration) {
+                                               AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) referenceContext;
+                                               MethodBinding methodBinding = methodDeclaration.binding;
+                                               int enclosingMethodIndex = constantPool.literalIndexForMethod(methodBinding.selector, methodBinding.signature());
+                                               methodIndexByte1 = (byte) (enclosingMethodIndex >> 8);
+                                               methodIndexByte2 = (byte) enclosingMethodIndex;
+                                       }
+                               }
+                       }
+                       contents[contentsOffset++] = methodIndexByte1;
+                       contents[contentsOffset++] = methodIndexByte2;
+                       attributeNumber++;                      
+               }
+               if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
+                       TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+                       if (typeDeclaration != null) {
+                               final Annotation[] annotations = typeDeclaration.annotations;
+                               if (annotations != null) {
+                                       attributeNumber += generateRuntimeAnnotations(annotations);
+                               }
+                       }
+               }
                // update the number of attributes
                if (attributeOffset + 2 >= this.contents.length) {
                        resizeContents(2);
@@ -335,7 +664,7 @@ public class ClassFile
                header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
                header[constantPoolOffset] = (byte) constantPoolCount;
        }
-
+       
        /**
         * INTERNAL USE-ONLY
         * This methods generate all the default abstract method infos that correpond to
@@ -352,37 +681,14 @@ public class ClassFile
                }
        }
 
-       /**
-        * 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;
+       private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) {
+               int attributesNumber = 0;
                // 4.7.2 only static constant fields get a ConstantAttribute
-               if (fieldBinding.constant != Constant.NotAConstant){
+               // Generate the constantValueAttribute
+               if (fieldBinding.isConstantValue()){
+                       if (contentsOffset + 8 >= contents.length) {
+                               resizeContents(8);
+                       }
                        // Now we generate the constant attribute corresponding to the fieldBinding
                        int constantValueNameIndex =
                                constantPool.literalIndex(AttributeNamesConstants.ConstantValueName);
@@ -393,12 +699,13 @@ public class ClassFile
                        contents[contentsOffset++] = 0;
                        contents[contentsOffset++] = 0;
                        contents[contentsOffset++] = 2;
-                       attributeNumber++;
+                       attributesNumber++;
                        // Need to add the constant_value_index
-                       switch (fieldBinding.constant.typeID()) {
+                       Constant fieldConstant = fieldBinding.constant();
+                       switch (fieldConstant.typeID()) {
                                case T_boolean :
                                        int booleanValueIndex =
-                                               constantPool.literalIndex(fieldBinding.constant.booleanValue() ? 1 : 0);
+                                               constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0);
                                        contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
                                        contents[contentsOffset++] = (byte) booleanValueIndex;
                                        break;
@@ -407,32 +714,32 @@ public class ClassFile
                                case T_int :
                                case T_short :
                                        int integerValueIndex =
-                                               constantPool.literalIndex(fieldBinding.constant.intValue());
+                                               constantPool.literalIndex(fieldConstant.intValue());
                                        contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
                                        contents[contentsOffset++] = (byte) integerValueIndex;
                                        break;
                                case T_float :
                                        int floatValueIndex =
-                                               constantPool.literalIndex(fieldBinding.constant.floatValue());
+                                               constantPool.literalIndex(fieldConstant.floatValue());
                                        contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
                                        contents[contentsOffset++] = (byte) floatValueIndex;
                                        break;
                                case T_double :
                                        int doubleValueIndex =
-                                               constantPool.literalIndex(fieldBinding.constant.doubleValue());
+                                               constantPool.literalIndex(fieldConstant.doubleValue());
                                        contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
                                        contents[contentsOffset++] = (byte) doubleValueIndex;
                                        break;
                                case T_long :
                                        int longValueIndex =
-                                               constantPool.literalIndex(fieldBinding.constant.longValue());
+                                               constantPool.literalIndex(fieldConstant.longValue());
                                        contents[contentsOffset++] = (byte) (longValueIndex >> 8);
                                        contents[contentsOffset++] = (byte) longValueIndex;
                                        break;
-                               case T_String :
+                               case T_JavaLangString :
                                        int stringValueIndex =
                                                constantPool.literalIndex(
-                                                       ((StringConstant) fieldBinding.constant).stringValue());
+                                                       ((StringConstant) fieldConstant).stringValue());
                                        if (stringValueIndex == -1) {
                                                if (!creatingProblemType) {
                                                        // report an error and abort: will lead to a problem type classfile creation
@@ -447,9 +754,7 @@ public class ClassFile
                                                        }
                                                } 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--;
+                                                       contentsOffset = fieldAttributeOffset;
                                                }
                                        } else {
                                                contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
@@ -457,7 +762,10 @@ public class ClassFile
                                        }
                        }
                }
-               if (fieldBinding.isSynthetic()) {
+               if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) {
+                       if (contentsOffset + 6 >= contents.length) {
+                               resizeContents(6);
+                       }
                        int syntheticAttributeNameIndex =
                                constantPool.literalIndex(AttributeNamesConstants.SyntheticName);
                        contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
@@ -467,9 +775,12 @@ public class ClassFile
                        contents[contentsOffset++] = 0;
                        contents[contentsOffset++] = 0;
                        contents[contentsOffset++] = 0;
-                       attributeNumber++;
+                       attributesNumber++;
                }
                if (fieldBinding.isDeprecated()) {
+                       if (contentsOffset + 6 >= contents.length) {
+                               resizeContents(6);
+                       }
                        int deprecatedAttributeNameIndex =
                                constantPool.literalIndex(AttributeNamesConstants.DeprecatedName);
                        contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
@@ -479,8 +790,75 @@ public class ClassFile
                        contents[contentsOffset++] = 0;
                        contents[contentsOffset++] = 0;
                        contents[contentsOffset++] = 0;
-                       attributeNumber++;
+                       attributesNumber++;
+               }
+               // add signature attribute
+               char[] genericSignature = fieldBinding.genericSignature();
+               if (genericSignature != null) {
+                       // 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 signatureAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+                       contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+                       // the length of a signature attribute is equals to 2
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 2;
+                       int signatureIndex =
+                               constantPool.literalIndex(genericSignature);
+                       contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+                       contents[contentsOffset++] = (byte) signatureIndex;
+                       attributesNumber++;
+               }
+               if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType) {
+                       FieldDeclaration fieldDeclaration = fieldBinding.sourceField();
+                       if (fieldDeclaration != null) {
+                               Annotation[] annotations = fieldDeclaration.annotations;
+                               if (annotations != null) {
+                                       attributesNumber += generateRuntimeAnnotations(annotations);
+                               }
+                       }
+               }
+               return attributesNumber;
+       }
+       /**
+        * INTERNAL USE-ONLY
+        * This methods generates the bytes for the given field binding
+        * @param fieldBinding the given field binding
+        */
+       private void addFieldInfo(FieldBinding fieldBinding) {
+               // 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);
                }
+               // Now we can generate all entries into the byte array
+               // First the accessFlags
+               int accessFlags = fieldBinding.getAccessFlags();
+               if (targetJDK < ClassFileConstants.JDK1_5) {
+                   // pre 1.5, synthetic was an attribute, not a modifier
+                   accessFlags &= ~AccSynthetic;
+               }               
+               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;
+               int fieldAttributeOffset = contentsOffset;
+               int attributeNumber = 0;
+               // leave some space for the number of attributes
+               contentsOffset += 2;
+               attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset);
                contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
                contents[fieldAttributeOffset] = (byte) attributeNumber;
        }
@@ -492,6 +870,13 @@ public class ClassFile
         * - a field info for each defined field of that class
         * - a field info for each synthetic field (e.g. this$0)
         */
+       /**
+        * 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();
@@ -523,7 +908,7 @@ public class ClassFile
         * have to be generated for the inner classes attributes.
         * @param refBinding org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding 
         */
-       public void addInnerClasses(ReferenceBinding refBinding) {
+       private void addInnerClasses(ReferenceBinding refBinding) {
                // check first if that reference binding is there
                for (int i = 0; i < numberOfInnerClasses; i++) {
                        if (innerClassesBindings[i] == refBinding)
@@ -540,6 +925,38 @@ public class ClassFile
                }
                innerClassesBindings[numberOfInnerClasses++] = refBinding;
        }
+       
+       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();
+               
+               codeStream.init(this);
+               codeStream.preserveUnusedLocals = true;
+               codeStream.initializeMaxLocals(methodBinding);
+
+               // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
+               codeStream.generateCodeAttributeForProblemMethod(problemString);
+                               
+               completeCodeAttributeForMissingAbstractProblemMethod(
+                       methodBinding,
+                       codeAttributeOffset,
+                       compilationResult.lineSeparatorPositions,
+                       problem.getSourceLineNumber());
+                       
+               completeMethodInfo(methodAttributeOffset, attributeNumber);
+       }
 
        /**
         * INTERNAL USE-ONLY
@@ -559,6 +976,7 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.resetForProblemClinit(this);
                String problemString = "" ; //$NON-NLS-1$
+               int problemLine = 0;
                if (problems != null) {
                        int max = problems.length;
                        StringBuffer buffer = new StringBuffer(25);
@@ -591,7 +1009,8 @@ public class ClassFile
                                .scope
                                .referenceCompilationUnit()
                                .compilationResult
-                               .lineSeparatorPositions);
+                               .lineSeparatorPositions,
+                       problemLine);
                contents[attributeOffset++] = (byte) (attributeNumber >> 8);
                contents[attributeOffset] = (byte) attributeNumber;
        }
@@ -612,7 +1031,7 @@ public class ClassFile
                // 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);
+               int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
                
                // Code attribute
                attributeNumber++;
@@ -620,6 +1039,7 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.reset(method, this);
                String problemString = "" ; //$NON-NLS-1$
+               int problemLine = 0;
                if (problems != null) {
                        int max = problems.length;
                        StringBuffer buffer = new StringBuffer(25);
@@ -652,7 +1072,8 @@ public class ClassFile
                                .scope
                                .referenceCompilationUnit()
                                .compilationResult
-                               .lineSeparatorPositions);
+                               .lineSeparatorPositions,
+                       problemLine);
                completeMethodInfo(methodAttributeOffset, attributeNumber);
        }
 
@@ -695,7 +1116,7 @@ public class ClassFile
                // 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);
+               int attributeNumber = generateMethodInfoAttribute(methodBinding, true);
                
                // Code attribute
                attributeNumber++;
@@ -704,6 +1125,7 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.reset(method, this);
                String problemString = "" ; //$NON-NLS-1$
+               int problemLine = 0;
                if (problems != null) {
                        int max = problems.length;
                        StringBuffer buffer = new StringBuffer(25);
@@ -740,7 +1162,8 @@ public class ClassFile
                                .scope
                                .referenceCompilationUnit()
                                .compilationResult
-                               .lineSeparatorPositions);
+                               .lineSeparatorPositions,
+                       problemLine);
                completeMethodInfo(methodAttributeOffset, attributeNumber);
        }
 
@@ -761,206 +1184,77 @@ public class ClassFile
                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);
+               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 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
+       public void addSpecialMethods() {
+           
+               // add all methods (default abstract methods and synthetic)
 
-               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++;
+               // default abstract methods
+               generateMissingAbstractMethods(referenceBinding.scope.referenceType().missingAbstractMethods, referenceBinding.scope.referenceCompilationUnit().compilationResult);
+
+               MethodBinding[] defaultAbstractMethods = this.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);
                }
-               
-               // 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);
+               // add synthetic methods infos
+               SyntheticMethodBinding[] syntheticMethods = this.referenceBinding.syntheticMethods();
+               if (syntheticMethods != null) {
+                       for (int i = 0, max = syntheticMethods.length; i < max; i++) {
+                               SyntheticMethodBinding syntheticMethod = syntheticMethods[i];
+                               switch (syntheticMethod.kind) {
+                                       case SyntheticMethodBinding.FieldReadAccess :
+                                               // generate a method info to emulate an reading access to
+                                               // a non-accessible field
+                                               addSyntheticFieldReadAccessMethod(syntheticMethod);
+                                               break;
+                                       case SyntheticMethodBinding.FieldWriteAccess :
+                                               // generate a method info to emulate an writing access to
+                                               // a non-accessible field
+                                               addSyntheticFieldWriteAccessMethod(syntheticMethod);
+                                               break;
+                                       case SyntheticMethodBinding.MethodAccess :
+                                       case SyntheticMethodBinding.SuperMethodAccess :
+                                       case SyntheticMethodBinding.BridgeMethod :
+                                               // generate a method info to emulate an access to a non-accessible method / super-method or bridge method
+                                               addSyntheticMethodAccessMethod(syntheticMethod);
+                                               break;
+                                       case SyntheticMethodBinding.ConstructorAccess :
+                                               // generate a method info to emulate an access to a non-accessible constructor
+                                               addSyntheticConstructorAccessMethod(syntheticMethod);
+                                               break;
+                                       case SyntheticMethodBinding.EnumValues :
+                                               // generate a method info to define <enum>#values()
+                                               addSyntheticEnumValuesMethod(syntheticMethod);
+                                               break;
+                                       case SyntheticMethodBinding.EnumValueOf :
+                                               // generate a method info to define <enum>#valueOf(String)
+                                               addSyntheticEnumValueOfMethod(syntheticMethod);
+                                               break;
+                               }
+                       }
                }
-               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.
+        * Generate the bytes for a synthetic method that provides an access to a private constructor.
         *
         * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
         */
-       public void addSyntheticConstructorAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+       public void addSyntheticConstructorAccessMethod(SyntheticMethodBinding methodBinding) {
                generateMethodInfoHeader(methodBinding);
                // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
                contents[contentsOffset++] = 0;
@@ -970,7 +1264,7 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.init(this);
                codeStream.generateSyntheticBodyForConstructorAccess(methodBinding);
-               completeCodeAttributeForSyntheticAccessMethod(
+               completeCodeAttributeForSyntheticMethod(
                        methodBinding,
                        codeAttributeOffset,
                        ((SourceTypeBinding) methodBinding.declaringClass)
@@ -992,12 +1286,88 @@ public class ClassFile
 
        /**
         * INTERNAL USE-ONLY
+        *  Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */     
+       public void addSyntheticEnumValueOfMethod(SyntheticMethodBinding methodBinding) {
+
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 1 attribute: the code attribute 
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 1;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForEnumValueOf(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       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 bytes for a synthetic method that implements Enum#values() for a given enum type
+        *
+        * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
+        */     
+       public void addSyntheticEnumValuesMethod(SyntheticMethodBinding methodBinding) {
+
+               generateMethodInfoHeader(methodBinding);
+               // We know that we won't get more than 1 attribute: the code attribute 
+               contents[contentsOffset++] = 0;
+               contents[contentsOffset++] = 1;
+               // Code attribute
+               int codeAttributeOffset = contentsOffset;
+               generateCodeAttributeHeader();
+               codeStream.init(this);
+               codeStream.generateSyntheticBodyForEnumValues(methodBinding);
+               completeCodeAttributeForSyntheticMethod(
+                       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) {
+       public void addSyntheticFieldReadAccessMethod(SyntheticMethodBinding methodBinding) {
                generateMethodInfoHeader(methodBinding);
                // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
                contents[contentsOffset++] = 0;
@@ -1007,7 +1377,7 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.init(this);
                codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding);
-               completeCodeAttributeForSyntheticAccessMethod(
+               completeCodeAttributeForSyntheticMethod(
                        methodBinding,
                        codeAttributeOffset,
                        ((SourceTypeBinding) methodBinding.declaringClass)
@@ -1034,7 +1404,7 @@ public class ClassFile
         *
         * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
         */
-       public void addSyntheticFieldWriteAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+       public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) {
                generateMethodInfoHeader(methodBinding);
                // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
                contents[contentsOffset++] = 0;
@@ -1044,7 +1414,7 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.init(this);
                codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding);
-               completeCodeAttributeForSyntheticAccessMethod(
+               completeCodeAttributeForSyntheticMethod(
                        methodBinding,
                        codeAttributeOffset,
                        ((SourceTypeBinding) methodBinding.declaringClass)
@@ -1066,12 +1436,11 @@ public class ClassFile
 
        /**
         * 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.
+        * Generate the bytes for a synthetic method that provides access to a private method.
         *
         * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
         */
-       public void addSyntheticMethodAccessMethod(SyntheticAccessMethodBinding methodBinding) {
+       public void addSyntheticMethodAccessMethod(SyntheticMethodBinding methodBinding) {
                generateMethodInfoHeader(methodBinding);
                // We know that we won't get more than 2 attribute: the code attribute + synthetic attribute
                contents[contentsOffset++] = 0;
@@ -1081,7 +1450,7 @@ public class ClassFile
                generateCodeAttributeHeader();
                codeStream.init(this);
                codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
-               completeCodeAttributeForSyntheticAccessMethod(
+               completeCodeAttributeForSyntheticMethod(
                        methodBinding,
                        codeAttributeOffset,
                        ((SourceTypeBinding) methodBinding.declaringClass)
@@ -1103,69 +1472,6 @@ public class ClassFile
 
        /**
         * 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
@@ -1204,7 +1510,7 @@ public class ClassFile
                this.contents[codeAttributeOffset + 13] = (byte) code_length;
 
                // write the exception table
-               int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+               int exceptionHandlersNumber = codeStream.exceptionHandlersCounter;
                ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
                int exSize = exceptionHandlersNumber * 8 + 2;
                if (exSize + localContentsOffset >= this.contents.length) {
@@ -1214,31 +1520,33 @@ public class ClassFile
                // on the attribute generation
                this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
                this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
-               for (int i = 0; i < exceptionHandlersNumber; i++) {
+               for (int i = 0, max = codeStream.exceptionHandlersIndex; i < max; 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();
+                       if (exceptionHandler != null) {
+                               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 {
-                                       nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+                                       int nameIndex;
+                                       if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
+                                               /* represents ClassNotFoundException, see class literal access*/
+                                               nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+                                       } else {
+                                               nameIndex = constantPool.literalIndexForType(exceptionHandler.exceptionType.constantPoolName());
+                                       }
+                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) nameIndex;
                                }
-                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
-                               this.contents[localContentsOffset++] = (byte) nameIndex;
                        }
                }
                // debug attributes
@@ -1300,8 +1608,14 @@ public class ClassFile
                        int numberOfEntries = 0;
                        int localVariableNameIndex =
                                constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName);
-                       if (localContentsOffset + 8 >= this.contents.length) {
-                               resizeContents(8);
+                       final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
+                       int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1);
+                       for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+                               maxOfEntries += 10 * codeStream.locals[i].initializationCount;
+                       }
+                       // reserve enough space
+                       if (localContentsOffset + maxOfEntries >= this.contents.length) {
+                               resizeContents(maxOfEntries);
                        }
                        this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
                        this.contents[localContentsOffset++] = (byte) localVariableNameIndex;
@@ -1309,28 +1623,41 @@ public class ClassFile
                        // leave space for attribute_length and local_variable_table_length
                        int nameIndex;
                        int descriptorIndex;
-                       if (!codeStream.methodDeclaration.isStatic()) {
+                       SourceTypeBinding declaringClassBinding = null;
+                       if (!methodDeclarationIsStatic) {
                                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);
+                               nameIndex = constantPool.literalIndex(ConstantPool.This);
                                this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                this.contents[localContentsOffset++] = (byte) nameIndex;
+                               declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
                                descriptorIndex =
                                        constantPool.literalIndex(
-                                               codeStream.methodDeclaration.binding.declaringClass.signature());
+                                               declaringClassBinding.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++) {
+                       // used to remember the local variable with a generic type
+                       int genericLocalVariablesCounter = 0;
+                       LocalVariableBinding[] genericLocalVariables = null;
+                       int numberOfGenericEntries = 0;
+                       
+                       for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
                                LocalVariableBinding localVariable = codeStream.locals[i];
+                               final TypeBinding localVariableTypeBinding = localVariable.type;
+                               boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+                               if (localVariable.initializationCount != 0 && isParameterizedType) {
+                                       if (genericLocalVariables == null) {
+                                               // we cannot have more than max locals
+                                               genericLocalVariables = new LocalVariableBinding[max];
+                                       }
+                                       genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+                               }
                                for (int j = 0; j < localVariable.initializationCount; j++) {
                                        int startPC = localVariable.initializationPCs[j << 1];
                                        int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -1340,8 +1667,8 @@ public class ClassFile
                                                                Util.bind("abort.invalidAttribute" , new String(localVariable.name)), //$NON-NLS-1$
                                                                (ASTNode) localVariable.declaringScope.methodScope().referenceContext);
                                                }
-                                               if (localContentsOffset + 10 >= this.contents.length) {
-                                                       resizeContents(10);
+                                               if (isParameterizedType) {
+                                                       numberOfGenericEntries++;
                                                }
                                                // now we can safely add the local entry
                                                numberOfEntries++;
@@ -1353,7 +1680,7 @@ public class ClassFile
                                                nameIndex = constantPool.literalIndex(localVariable.name);
                                                this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                                this.contents[localContentsOffset++] = (byte) nameIndex;
-                                               descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                               descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
                                                this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                                this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                                int resolvedPosition = localVariable.resolvedPosition;
@@ -1371,6 +1698,72 @@ public class ClassFile
                        this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
                        this.contents[localVariableTableOffset] = (byte) numberOfEntries;
                        attributeNumber++;
+                       
+                       final boolean currentInstanceIsGeneric = 
+                               !methodDeclarationIsStatic
+                               && declaringClassBinding != null 
+                               && declaringClassBinding.typeVariables != NoTypeVariables;
+                       if (genericLocalVariablesCounter != 0 || currentInstanceIsGeneric) {
+                               // add the local variable type table attribute
+                               numberOfGenericEntries += (currentInstanceIsGeneric ? 1 : 0);
+                               maxOfEntries = 8 + numberOfGenericEntries * 10;
+                               // reserve enough space
+                               if (localContentsOffset + maxOfEntries >= this.contents.length) {
+                                       resizeContents(maxOfEntries);
+                               }
+                               int localVariableTypeNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+                               this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+                               value = numberOfGenericEntries * 10 + 2;
+                               this.contents[localContentsOffset++] = (byte) (value >> 24);
+                               this.contents[localContentsOffset++] = (byte) (value >> 16);
+                               this.contents[localContentsOffset++] = (byte) (value >> 8);
+                               this.contents[localContentsOffset++] = (byte) value;
+                               this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+                               this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+                               if (currentInstanceIsGeneric) {
+                                       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(ConstantPool.This);
+                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                       descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
+                                       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 < genericLocalVariablesCounter; i++) {
+                                       LocalVariableBinding localVariable = genericLocalVariables[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
+                                                       // now we can safely add the local entry
+                                                       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.genericTypeSignature());
+                                                       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;
+                                               }
+                                       }
+                               }
+                               attributeNumber++;
+                       }
                }
                // update the number of attributes
                // ensure first that there is enough space available inside the localContents array
@@ -1429,7 +1822,7 @@ public class ClassFile
                this.contents[codeAttributeOffset + 13] = (byte) code_length;
 
                // write the exception table
-               int exceptionHandlersNumber = codeStream.exceptionHandlersNumber;
+               int exceptionHandlersNumber = codeStream.exceptionHandlersCounter;
                ExceptionLabel[] exceptionHandlers = codeStream.exceptionHandlers;
                int exSize = exceptionHandlersNumber * 8 + 2;
                if (exSize + localContentsOffset >= this.contents.length) {
@@ -1439,31 +1832,33 @@ public class ClassFile
                // on the attribute generation
                this.contents[localContentsOffset++] = (byte) (exceptionHandlersNumber >> 8);
                this.contents[localContentsOffset++] = (byte) exceptionHandlersNumber;
-               for (int i = 0; i < exceptionHandlersNumber; i++) {
+               for (int i = 0, max = codeStream.exceptionHandlersIndex; i < max; 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();
+                       if (exceptionHandler != null) {
+                               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 {
-                                       nameIndex = constantPool.literalIndex(exceptionHandler.exceptionType);
+                                       int nameIndex;
+                                       if (exceptionHandler.exceptionType == BaseTypes.NullBinding) {
+                                               /* represents denote ClassNotFoundException, see class literal access*/
+                                               nameIndex = constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
+                                       } else {
+                                               nameIndex = constantPool.literalIndexForType(exceptionHandler.exceptionType.constantPoolName());
+                                       }
+                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) nameIndex;
                                }
-                               this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
-                               this.contents[localContentsOffset++] = (byte) nameIndex;
                        }
                }
                // debug attributes
@@ -1534,11 +1929,27 @@ public class ClassFile
                                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++) {
+
+                               // used to remember the local variable with a generic type
+                               int genericLocalVariablesCounter = 0;
+                               LocalVariableBinding[] genericLocalVariables = null;
+                               int numberOfGenericEntries = 0;
+
+                               for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
                                        LocalVariableBinding localVariable = codeStream.locals[i];
+                                       final TypeBinding localVariableTypeBinding = localVariable.type;
+                                       boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+                                       if (localVariable.initializationCount != 0 && isParameterizedType) {
+                                               if (genericLocalVariables == null) {
+                                                       // we cannot have more than max locals
+                                                       genericLocalVariables = new LocalVariableBinding[max];
+                                               }
+                                               genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+                                       }
                                        for (int j = 0; j < localVariable.initializationCount; j++) {
                                                int startPC = localVariable.initializationPCs[j << 1];
                                                int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -1553,6 +1964,9 @@ public class ClassFile
                                                        }
                                                        // now we can safely add the local entry
                                                        numberOfEntries++;
+                                                       if (isParameterizedType) {
+                                                               numberOfGenericEntries++;
+                                                       }
                                                        this.contents[localContentsOffset++] = (byte) (startPC >> 8);
                                                        this.contents[localContentsOffset++] = (byte) startPC;
                                                        int length = endPC - startPC;
@@ -1561,7 +1975,7 @@ public class ClassFile
                                                        nameIndex = constantPool.literalIndex(localVariable.name);
                                                        this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                                        this.contents[localContentsOffset++] = (byte) nameIndex;
-                                                       descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                                       descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
                                                        this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                                        this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                                        int resolvedPosition = localVariable.resolvedPosition;
@@ -1579,6 +1993,52 @@ public class ClassFile
                                this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
                                this.contents[localVariableTableOffset] = (byte) numberOfEntries;
                                attributeNumber++;
+
+                               if (genericLocalVariablesCounter != 0) {
+                                       // add the local variable type table attribute
+                                       // reserve enough space
+                                       int maxOfEntries = 8 + numberOfGenericEntries * 10;
+
+                                       if (localContentsOffset + maxOfEntries >= this.contents.length) {
+                                               resizeContents(maxOfEntries);
+                                       }
+                                       int localVariableTypeNameIndex =
+                                               constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+                                       this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+                                       value = numberOfGenericEntries * 10 + 2;
+                                       this.contents[localContentsOffset++] = (byte) (value >> 24);
+                                       this.contents[localContentsOffset++] = (byte) (value >> 16);
+                                       this.contents[localContentsOffset++] = (byte) (value >> 8);
+                                       this.contents[localContentsOffset++] = (byte) value;
+                                       this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+                                       this.contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+                                       for (int i = 0; i < genericLocalVariablesCounter; i++) {
+                                               LocalVariableBinding localVariable = genericLocalVariables[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
+                                                               // now we can safely add the local entry
+                                                               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.genericTypeSignature());
+                                                               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;
+                                                       }
+                                               }
+                                       }
+                                       attributeNumber++;
+                               }
                        }
                }
                // update the number of attributes
@@ -1612,7 +2072,8 @@ public class ClassFile
         */
        public void completeCodeAttributeForClinit(
                int codeAttributeOffset,
-               int[] startLineIndexes) {
+               int[] startLineIndexes,
+               int problemLine) {
                // reinitialize the contents with the byte modified by the code stream
                this.contents = codeStream.bCodeStream;
                int localContentsOffset = codeStream.classFileOffset;
@@ -1711,6 +2172,85 @@ public class ClassFile
        }
 
        /**
+        * 
+        */
+       public void completeCodeAttributeForMissingAbstractProblemMethod(
+               MethodBinding binding,
+               int codeAttributeOffset,
+               int[] startLineIndexes,
+               int problemLine) {
+               // 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
         * That method completes the creation of the code attribute by setting
         * - the attribute_length
@@ -1726,7 +2266,8 @@ public class ClassFile
                AbstractMethodDeclaration method,
                MethodBinding binding,
                int codeAttributeOffset,
-               int[] startLineIndexes) {
+               int[] startLineIndexes,
+               int problemLine) {
                // reinitialize the localContents with the byte modified by the code stream
                this.contents = codeStream.bCodeStream;
                int localContentsOffset = codeStream.classFileOffset;
@@ -1803,7 +2344,10 @@ public class ClassFile
                        localContentsOffset += 6;
                        // leave space for attribute_length and local_variable_table_length
                        int descriptorIndex;
-                       if (!codeStream.methodDeclaration.isStatic()) {
+                       int nameIndex;
+                       SourceTypeBinding declaringClassBinding = null;
+                       final boolean methodDeclarationIsStatic = codeStream.methodDeclaration.isStatic();
+                       if (!methodDeclarationIsStatic) {
                                numberOfEntries++;
                                if (localContentsOffset + 10 >= this.contents.length) {
                                        resizeContents(10);
@@ -1812,28 +2356,41 @@ public class ClassFile
                                this.contents[localContentsOffset++] = 0;
                                this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                                this.contents[localContentsOffset++] = (byte) code_length;
-                               int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.This);
+                               nameIndex = constantPool.literalIndex(ConstantPool.This);
                                this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                this.contents[localContentsOffset++] = (byte) nameIndex;
+                               declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
                                descriptorIndex =
-                                       constantPool.literalIndex(
-                                               codeStream.methodDeclaration.binding.declaringClass.signature());
+                                       constantPool.literalIndex(declaringClassBinding.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;
                        }
+                       // used to remember the local variable with a generic type
+                       int genericLocalVariablesCounter = 0;
+                       LocalVariableBinding[] genericLocalVariables = null;
+                       int numberOfGenericEntries = 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) {
+                                       if ((syntheticArguments = methodDeclaringClass.syntheticEnclosingInstances()) != null) {
                                                for (int i = 0, max = syntheticArguments.length; i < max; i++) {
                                                        LocalVariableBinding localVariable = syntheticArguments[i];
+                                                       final TypeBinding localVariableTypeBinding = localVariable.type;
+                                                       if (localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable()) {
+                                                               if (genericLocalVariables == null) {
+                                                                       // we cannot have more than max locals
+                                                                       genericLocalVariables = new LocalVariableBinding[max];
+                                                               }
+                                                               genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+                                                               numberOfGenericEntries++;                                                               
+                                                       }
                                                        if (localContentsOffset + 10 >= this.contents.length) {
                                                                resizeContents(10);
                                                        }
@@ -1843,10 +2400,10 @@ public class ClassFile
                                                        this.contents[localContentsOffset++] = 0;
                                                        this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                                                        this.contents[localContentsOffset++] = (byte) code_length;
-                                                       int nameIndex = constantPool.literalIndex(localVariable.name);
+                                                       nameIndex = constantPool.literalIndex(localVariable.name);
                                                        this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                                        this.contents[localContentsOffset++] = (byte) nameIndex;
-                                                       descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                                       descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
                                                        this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                                        this.contents[localContentsOffset++] = (byte) descriptorIndex;
                                                        int resolvedPosition = localVariable.resolvedPosition;
@@ -1860,6 +2417,12 @@ public class ClassFile
                        } else {
                                argSize = binding.isStatic() ? 0 : 1;
                        }
+                       
+                       int genericArgumentsCounter = 0;
+                       int[] genericArgumentsNameIndexes = null;
+                       int[] genericArgumentsResolvedPositions = null;
+                       TypeBinding[] genericArgumentsTypeBindings = null;
+
                        if (method.binding != null) {
                                TypeBinding[] parameters = method.binding.parameters;
                                Argument[] arguments = method.arguments;
@@ -1875,13 +2438,24 @@ public class ClassFile
                                                this.contents[localContentsOffset++] = 0;
                                                this.contents[localContentsOffset++] = (byte) (code_length >> 8);
                                                this.contents[localContentsOffset++] = (byte) code_length;
-                                               int nameIndex = constantPool.literalIndex(arguments[i].name);
+                                               nameIndex = constantPool.literalIndex(arguments[i].name);
                                                this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                                this.contents[localContentsOffset++] = (byte) nameIndex;
+                                               int resolvedPosition = argSize;
+                                               if (argumentBinding.isParameterizedType() || argumentBinding.isTypeVariable()) {
+                                                       if (genericArgumentsCounter == 0) {
+                                                               // we cannot have more than max locals
+                                                               genericArgumentsNameIndexes = new int[max];
+                                                               genericArgumentsResolvedPositions = new int[max];
+                                                               genericArgumentsTypeBindings = new TypeBinding[max];
+                                                       }
+                                                       genericArgumentsNameIndexes[genericArgumentsCounter] = nameIndex;
+                                                       genericArgumentsResolvedPositions[genericArgumentsCounter] = resolvedPosition;
+                                                       genericArgumentsTypeBindings[genericArgumentsCounter++] = argumentBinding;
+                                               }
                                                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;
@@ -1901,6 +2475,79 @@ public class ClassFile
                        this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
                        this.contents[localVariableTableOffset] = (byte) numberOfEntries;
                        attributeNumber++;
+                       
+                       final boolean currentInstanceIsGeneric = 
+                               !methodDeclarationIsStatic
+                               && declaringClassBinding != null
+                               && declaringClassBinding.typeVariables != NoTypeVariables;
+                       if (genericLocalVariablesCounter != 0 || genericArgumentsCounter != 0 || currentInstanceIsGeneric) {
+                               // add the local variable type table attribute
+                               numberOfEntries = numberOfGenericEntries + genericArgumentsCounter + (currentInstanceIsGeneric ? 1 : 0);
+                               // reserve enough space
+                               int maxOfEntries = 8 + numberOfEntries * 10;
+                               if (localContentsOffset + maxOfEntries >= this.contents.length) {
+                                       resizeContents(maxOfEntries);
+                               }
+                               int localVariableTypeNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+                               this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+                               this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+                               value = numberOfEntries * 10 + 2;
+                               this.contents[localContentsOffset++] = (byte) (value >> 24);
+                               this.contents[localContentsOffset++] = (byte) (value >> 16);
+                               this.contents[localContentsOffset++] = (byte) (value >> 8);
+                               this.contents[localContentsOffset++] = (byte) value;
+                               this.contents[localContentsOffset++] = (byte) (numberOfEntries >> 8);
+                               this.contents[localContentsOffset++] = (byte) numberOfEntries;
+                               if (currentInstanceIsGeneric) {
+                                       numberOfEntries++;
+                                       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(ConstantPool.This);
+                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                       descriptorIndex = constantPool.literalIndex(declaringClassBinding.genericTypeSignature());
+                                       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 < genericLocalVariablesCounter; i++) {
+                                       LocalVariableBinding localVariable = genericLocalVariables[i];
+                                       this.contents[localContentsOffset++] = 0;
+                                       this.contents[localContentsOffset++] = 0;
+                                       this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                                       this.contents[localContentsOffset++] = (byte) code_length;
+                                       nameIndex = constantPool.literalIndex(localVariable.name);
+                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                       descriptorIndex = constantPool.literalIndex(localVariable.type.genericTypeSignature());
+                                       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;
+                               }
+                               for (int i = 0; i < genericArgumentsCounter; i++) {
+                                       this.contents[localContentsOffset++] = 0;
+                                       this.contents[localContentsOffset++] = 0;
+                                       this.contents[localContentsOffset++] = (byte) (code_length >> 8);
+                                       this.contents[localContentsOffset++] = (byte) code_length;
+                                       nameIndex = genericArgumentsNameIndexes[i];
+                                       this.contents[localContentsOffset++] = (byte) (nameIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) nameIndex;
+                                       descriptorIndex = constantPool.literalIndex(genericArgumentsTypeBindings[i].genericTypeSignature());
+                                       this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                       this.contents[localContentsOffset++] = (byte) descriptorIndex;
+                                       int resolvedPosition = genericArgumentsResolvedPositions[i];
+                                       this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                       this.contents[localContentsOffset++] = (byte) resolvedPosition;
+                               }                               
+                               attributeNumber++;
+                       }                       
                }
                // update the number of attributes// ensure first that there is enough space available inside the localContents array
                if (codeAttributeAttributeOffset + 2 >= this.contents.length) {
@@ -1930,8 +2577,8 @@ public class ClassFile
         * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
         * @param codeAttributeOffset <CODE>int</CODE>
         */
-       public void completeCodeAttributeForSyntheticAccessMethod(
-               SyntheticAccessMethodBinding binding,
+       public void completeCodeAttributeForSyntheticMethod(
+               SyntheticMethodBinding binding,
                int codeAttributeOffset,
                int[] startLineIndexes) {
                // reinitialize the contents with the byte modified by the code stream
@@ -2005,8 +2652,23 @@ public class ClassFile
                        // leave space for attribute_length and local_variable_table_length
                        int nameIndex;
                        int descriptorIndex;
-                       for (int i = 0; i < codeStream.allLocalsCounter; i++) {
+
+                       // used to remember the local variable with a generic type
+                       int genericLocalVariablesCounter = 0;
+                       LocalVariableBinding[] genericLocalVariables = null;
+                       int numberOfGenericEntries = 0;
+                       
+                       for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
                                LocalVariableBinding localVariable = codeStream.locals[i];
+                               final TypeBinding localVariableTypeBinding = localVariable.type;
+                               boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable();
+                               if (localVariable.initializationCount != 0 && isParameterizedType) {
+                                       if (genericLocalVariables == null) {
+                                               // we cannot have more than max locals
+                                               genericLocalVariables = new LocalVariableBinding[max];
+                                       }
+                                       genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
+                               }
                                for (int j = 0; j < localVariable.initializationCount; j++) {
                                        int startPC = localVariable.initializationPCs[j << 1];
                                        int endPC = localVariable.initializationPCs[(j << 1) + 1];
@@ -2021,6 +2683,9 @@ public class ClassFile
                                                }
                                                // now we can safely add the local entry
                                                numberOfEntries++;
+                                               if (isParameterizedType) {
+                                                       numberOfGenericEntries++;
+                                               }
                                                contents[localContentsOffset++] = (byte) (startPC >> 8);
                                                contents[localContentsOffset++] = (byte) startPC;
                                                int length = endPC - startPC;
@@ -2029,7 +2694,7 @@ public class ClassFile
                                                nameIndex = constantPool.literalIndex(localVariable.name);
                                                contents[localContentsOffset++] = (byte) (nameIndex >> 8);
                                                contents[localContentsOffset++] = (byte) nameIndex;
-                                               descriptorIndex = constantPool.literalIndex(localVariable.type.signature());
+                                               descriptorIndex = constantPool.literalIndex(localVariableTypeBinding.signature());
                                                contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
                                                contents[localContentsOffset++] = (byte) descriptorIndex;
                                                int resolvedPosition = localVariable.resolvedPosition;
@@ -2047,6 +2712,52 @@ public class ClassFile
                        contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
                        contents[localVariableTableOffset] = (byte) numberOfEntries;
                        attributeNumber++;
+
+                       if (genericLocalVariablesCounter != 0) {
+                               // add the local variable type table attribute
+                               int maxOfEntries = 8 + numberOfGenericEntries * 10;
+                               // reserve enough space
+                               if (localContentsOffset + maxOfEntries >= this.contents.length) {
+                                       resizeContents(maxOfEntries);
+                               }
+                               int localVariableTypeNameIndex =
+                                       constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
+                               contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
+                               contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
+                               value = numberOfGenericEntries * 10 + 2;
+                               contents[localContentsOffset++] = (byte) (value >> 24);
+                               contents[localContentsOffset++] = (byte) (value >> 16);
+                               contents[localContentsOffset++] = (byte) (value >> 8);
+                               contents[localContentsOffset++] = (byte) value;
+                               contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
+                               contents[localContentsOffset++] = (byte) numberOfGenericEntries;
+
+                               for (int i = 0; i < genericLocalVariablesCounter; i++) {
+                                       LocalVariableBinding localVariable = genericLocalVariables[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
+                                                       // now we can safely add the local entry
+                                                       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.genericTypeSignature());
+                                                       contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
+                                                       contents[localContentsOffset++] = (byte) descriptorIndex;
+                                                       int resolvedPosition = localVariable.resolvedPosition;
+                                                       contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
+                                                       contents[localContentsOffset++] = (byte) resolvedPosition;
+                                               }
+                                       }
+                               }
+                               attributeNumber++;
+                       }
                }
                // update the number of attributes
                // ensure first that there is enough space available inside the contents array
@@ -2082,115 +2793,74 @@ public class ClassFile
 
        /**
         * INTERNAL USE-ONLY
-        * Request the creation of a ClassFile compatible representation of a problematic type
+        * This methods returns a char[] representing the file name of the receiver
         *
-        * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
-        * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
+        * @return char[]
         */
-       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);
+       public char[] fileName() {
+               return constantPool.UTF8Cache.returnKeyFor(1);
+       }
 
-               // 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;
-                                                       }
-                                               }
+       private void generateAnnotation(Annotation annotation, int attributeOffset) {
+               if (contentsOffset + 4 >= this.contents.length) {
+                       resizeContents(4);
+               }
+               TypeBinding annotationTypeBinding = annotation.resolvedType;
+               if (annotationTypeBinding == null) {
+                       this.contentsOffset = attributeOffset;
+                       return;
+               }
+               final int typeIndex = constantPool.literalIndex(annotationTypeBinding.signature());
+               contents[contentsOffset++] = (byte) (typeIndex >> 8);
+               contents[contentsOffset++] = (byte) typeIndex;
+               if (annotation instanceof NormalAnnotation) {
+                       NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
+                       MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
+                       if (memberValuePairs != null) {
+                               final int memberValuePairsLength = memberValuePairs.length;
+                               contents[contentsOffset++] = (byte) (memberValuePairsLength >> 8);
+                               contents[contentsOffset++] = (byte) memberValuePairsLength;
+                               for (int i = 0; i < memberValuePairsLength; i++) {
+                                       MemberValuePair memberValuePair = memberValuePairs[i];
+                                       if (contentsOffset + 2 >= this.contents.length) {
+                                               resizeContents(2);
                                        }
-                               }
-                       } 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;
-                                                       }
-                                               }
+                                       final int elementNameIndex = constantPool.literalIndex(memberValuePair.name);
+                                       contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
+                                       contents[contentsOffset++] = (byte) elementNameIndex;
+                                       MethodBinding methodBinding = memberValuePair.binding;
+                                       if (methodBinding == null) {
+                                               contentsOffset = attributeOffset;
+                                       } else {
+                                               generateElementValue(memberValuePair.value, methodBinding.returnType, attributeOffset);
                                        }
                                }
+                       } else {
+                               contents[contentsOffset++] = 0;
+                               contents[contentsOffset++] = 0;
                        }
-                       // 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);
+               } else if (annotation instanceof SingleMemberAnnotation) {
+                       SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
+                       // this is a single member annotation (one member value)
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 1;
+                       if (contentsOffset + 2 >= this.contents.length) {
+                               resizeContents(2);
+                       }
+                       final int elementNameIndex = constantPool.literalIndex(VALUE);
+                       contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) elementNameIndex;
+                       MethodBinding methodBinding = singleMemberAnnotation.singlePair.binding;
+                       if (methodBinding == null) {
+                               contentsOffset = attributeOffset;
+                       } else {
+                               generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, attributeOffset);
+                       }
+               } else {
+                       // this is a marker annotation (no member value pairs)
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+               }
        }
 
        /**
@@ -2211,6 +2881,187 @@ public class ClassFile
                contentsOffset += 12;
        }
 
+       private void generateElementValue(
+                       Expression defaultValue,
+                       TypeBinding memberValuePairReturnType,
+                       int attributeOffset) {
+               Constant constant = defaultValue.constant;
+               TypeBinding defaultValueBinding = defaultValue.resolvedType;
+               if (defaultValueBinding == null) {
+                       contentsOffset = attributeOffset;
+               } else {
+                       if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) {
+                               // automatic wrapping
+                               if (contentsOffset + 3 >= this.contents.length) {
+                                       resizeContents(3);
+                               }
+                               contents[contentsOffset++] = (byte) '[';
+                               contents[contentsOffset++] = (byte) 0;
+                               contents[contentsOffset++] = (byte) 1;
+                       }
+                       if (constant != null && constant != Constant.NotAConstant) {
+                               generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType());
+                       } else {
+                               generateElementValueForNonConstantExpression(defaultValue, attributeOffset, defaultValueBinding);
+                       }
+               }
+       }
+
+       /**
+        * @param attributeOffset
+        */
+       private void generateElementValue(int attributeOffset, Expression defaultValue, Constant constant, TypeBinding binding) {
+               if (contentsOffset + 3 >= this.contents.length) {
+                       resizeContents(3);
+               }
+               switch (binding.id) {
+                       case T_boolean :
+                               contents[contentsOffset++] = (byte) 'Z';
+                               int booleanValueIndex =
+                                       constantPool.literalIndex(constant.booleanValue() ? 1 : 0);
+                               contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
+                               contents[contentsOffset++] = (byte) booleanValueIndex;
+                               break;
+                       case T_byte :
+                               contents[contentsOffset++] = (byte) 'B';
+                               int integerValueIndex =
+                                       constantPool.literalIndex(constant.intValue());
+                               contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+                               contents[contentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_char :
+                               contents[contentsOffset++] = (byte) 'C';
+                               integerValueIndex =
+                                       constantPool.literalIndex(constant.intValue());
+                               contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+                               contents[contentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_int :
+                               contents[contentsOffset++] = (byte) 'I';
+                               integerValueIndex =
+                                       constantPool.literalIndex(constant.intValue());
+                               contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+                               contents[contentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_short :
+                               contents[contentsOffset++] = (byte) 'S';
+                               integerValueIndex =
+                                       constantPool.literalIndex(constant.intValue());
+                               contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
+                               contents[contentsOffset++] = (byte) integerValueIndex;
+                               break;
+                       case T_float :
+                               contents[contentsOffset++] = (byte) 'F';
+                               int floatValueIndex =
+                                       constantPool.literalIndex(constant.floatValue());
+                               contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
+                               contents[contentsOffset++] = (byte) floatValueIndex;
+                               break;
+                       case T_double :
+                               contents[contentsOffset++] = (byte) 'D';
+                               int doubleValueIndex =
+                                       constantPool.literalIndex(constant.doubleValue());
+                               contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
+                               contents[contentsOffset++] = (byte) doubleValueIndex;
+                               break;
+                       case T_long :
+                               contents[contentsOffset++] = (byte) 'J';
+                               int longValueIndex =
+                                       constantPool.literalIndex(constant.longValue());
+                               contents[contentsOffset++] = (byte) (longValueIndex >> 8);
+                               contents[contentsOffset++] = (byte) longValueIndex;
+                               break;
+                       case T_JavaLangString :
+                               contents[contentsOffset++] = (byte) 's';
+                               int stringValueIndex =
+                                       constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray());
+                               if (stringValueIndex == -1) {
+                                       if (!creatingProblemType) {
+                                               // report an error and abort: will lead to a problem type classfile creation
+                                               TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
+                                               typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue);
+                                       } else {
+                                               // already inside a problem type creation : no attribute
+                                               contentsOffset = attributeOffset;
+                                       }
+                               } else {
+                                       contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
+                                       contents[contentsOffset++] = (byte) stringValueIndex;
+                               }
+               }
+       }
+       
+       private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) {
+               if (defaultValueBinding != null) {
+                       if (defaultValueBinding.isEnum()) {
+                               if (contentsOffset + 5 >= this.contents.length) {
+                                       resizeContents(5);
+                               }
+                               contents[contentsOffset++] = (byte) 'e';
+                               FieldBinding fieldBinding = null;
+                               if (defaultValue instanceof QualifiedNameReference) {
+                                       QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
+                                       fieldBinding = (FieldBinding) nameReference.binding;
+                               } else if (defaultValue instanceof SingleNameReference) {
+                                       SingleNameReference nameReference = (SingleNameReference) defaultValue;
+                                       fieldBinding = (FieldBinding) nameReference.binding;
+                               } else {
+                                       contentsOffset = attributeOffset;
+                               }
+                               if (fieldBinding != null) {
+                                       final int enumConstantTypeNameIndex = constantPool.literalIndex(fieldBinding.type.signature());
+                                       final int enumConstantNameIndex = constantPool.literalIndex(fieldBinding.name);
+                                       contents[contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8);
+                                       contents[contentsOffset++] = (byte) enumConstantTypeNameIndex;
+                                       contents[contentsOffset++] = (byte) (enumConstantNameIndex >> 8);
+                                       contents[contentsOffset++] = (byte) enumConstantNameIndex;
+                               }
+                       } else if (defaultValueBinding.isAnnotationType()) {
+                               if (contentsOffset + 1 >= this.contents.length) {
+                                       resizeContents(1);
+                               }
+                               contents[contentsOffset++] = (byte) '@';
+                               generateAnnotation((Annotation) defaultValue, attributeOffset);
+                       } else if (defaultValueBinding.isArrayType()) {
+                               // array type
+                               if (contentsOffset + 3 >= this.contents.length) {
+                                       resizeContents(3);
+                               }
+                               contents[contentsOffset++] = (byte) '[';
+                               if (defaultValue instanceof ArrayInitializer) {
+                                       ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
+                                       int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0;
+                                       contents[contentsOffset++] = (byte) (arrayLength >> 8);
+                                       contents[contentsOffset++] = (byte) arrayLength;
+                                       for (int i = 0; i < arrayLength; i++) {
+                                               generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset);
+                                       }
+                               } else {
+                                       contentsOffset = attributeOffset;
+                               }
+                       } else {
+                               // class type
+                               if (contentsOffset + 3 >= this.contents.length) {
+                                       resizeContents(3);
+                               }
+                               contents[contentsOffset++] = (byte) 'c';
+                               if (defaultValue instanceof ClassLiteralAccess) {
+                                       ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue;
+                                       final int classInfoIndex = constantPool.literalIndex(classLiteralAccess.targetType.signature());
+                                       contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
+                                       contents[contentsOffset++] = (byte) classInfoIndex;
+                               } else {
+                                       contentsOffset = attributeOffset;
+                               }
+                       }
+               } else {
+                       contentsOffset = attributeOffset;
+               }
+       }
+
+       public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+               return generateMethodInfoAttribute(methodBinding, false);
+       }
        /**
         * INTERNAL USE-ONLY
         * That method generates the attributes of a code attribute.
@@ -2224,7 +3075,7 @@ public class ClassFile
         * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
         * @return <CODE>int</CODE>
         */
-       public int generateMethodInfoAttribute(MethodBinding methodBinding) {
+       public int generateMethodInfoAttribute(MethodBinding methodBinding, boolean createProblemMethod) {
                // leave two bytes for the attribute_number
                contentsOffset += 2;
                // now we can handle all the attribute for that method info:
@@ -2258,7 +3109,7 @@ public class ClassFile
                        contents[contentsOffset++] = (byte) (length >> 8);
                        contents[contentsOffset++] = (byte) length;
                        for (int i = 0; i < length; i++) {
-                               int exceptionIndex = constantPool.literalIndex(thrownsExceptions[i]);
+                               int exceptionIndex = constantPool.literalIndexForType(thrownsExceptions[i].constantPoolName());
                                contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
                                contents[contentsOffset++] = (byte) exceptionIndex;
                        }
@@ -2300,9 +3151,72 @@ public class ClassFile
 
                        attributeNumber++;
                }
+               // add signature attribute
+               char[] genericSignature = methodBinding.genericSignature();
+               if (genericSignature != null) {
+                       // check that there is enough space to write all the bytes for the field info corresponding
+                       // to the @fieldBinding
+                       if (contentsOffset + 8 >= this.contents.length) {
+                               resizeContents(8);
+                       }
+                       int signatureAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.SignatureName);
+                       contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
+                       // the length of a signature attribute is equals to 2
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 0;
+                       contents[contentsOffset++] = 2;
+                       int signatureIndex =
+                               constantPool.literalIndex(genericSignature);
+                       contents[contentsOffset++] = (byte) (signatureIndex >> 8);
+                       contents[contentsOffset++] = (byte) signatureIndex;
+                       attributeNumber++;
+               }
+               if (this.targetJDK >= ClassFileConstants.JDK1_5 && !this.creatingProblemType && !createProblemMethod) {
+                       AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod();
+                       if (methodDeclaration != null) {
+                               Annotation[] annotations = methodDeclaration.annotations;
+                               if (annotations != null) {
+                                       attributeNumber += generateRuntimeAnnotations(annotations);
+                               }
+                               if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
+                                       Argument[] arguments = methodDeclaration.arguments;
+                                       if (arguments != null) {
+                                               attributeNumber += generateRuntimeAnnotationsForParameters(arguments);
+                                       }
+                               }
+                       }
+               }
                return attributeNumber;
        }
 
+       public int generateMethodInfoAttribute(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) {
+               int attributesNumber = generateMethodInfoAttribute(methodBinding);
+               int attributeOffset = contentsOffset;
+               if ((declaration.modifiers & AccAnnotationDefault) != 0) {
+                       // add an annotation default attribute
+                       int annotationDefaultNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName);
+                       contents[contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) annotationDefaultNameIndex;
+                       int attributeLengthOffset = contentsOffset;
+                       contentsOffset += 4;
+
+                       generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset);
+                       if (contentsOffset != attributeOffset) {
+                               int attributeLength = contentsOffset - attributeLengthOffset - 4;
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               contents[attributeLengthOffset++] = (byte) attributeLength;                     
+                               attributesNumber++;
+                       }
+               }
+               return attributesNumber;
+       }
+
        /**
         * INTERNAL USE-ONLY
         * That method generates the header of a method info:
@@ -2368,11 +3282,11 @@ public class ClassFile
                }
                contents[contentsOffset++] = (byte) ((AccDefault | AccStatic) >> 8);
                contents[contentsOffset++] = (byte) (AccDefault | AccStatic);
-               int nameIndex = constantPool.literalIndex(QualifiedNamesConstants.Clinit);
+               int nameIndex = constantPool.literalIndex(ConstantPool.Clinit);
                contents[contentsOffset++] = (byte) (nameIndex >> 8);
                contents[contentsOffset++] = (byte) nameIndex;
                int descriptorIndex =
-                       constantPool.literalIndex(QualifiedNamesConstants.ClinitSignature);
+                       constantPool.literalIndex(ConstantPool.ClinitSignature);
                contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
                contents[contentsOffset++] = (byte) descriptorIndex;
                // We know that we won't get more than 1 attribute: the code attribute
@@ -2381,6 +3295,264 @@ public class ClassFile
        }
 
        /**
+        * 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);
+                                               }
+                               }
+                       }
+               }
+       }
+
+       /**
+        * @param annotations
+        * @return the number of attributes created while dumping the annotations in the .class file
+        */
+       private int generateRuntimeAnnotations(final Annotation[] annotations) {
+               int attributesNumber = 0;
+               final int length = annotations.length;
+               int visibleAnnotationsCounter = 0;
+               int invisibleAnnotationsCounter = 0;
+               
+               for (int i = 0; i < length; i++) {
+                       Annotation annotation = annotations[i];
+                       if (isRuntimeInvisible(annotation)) {
+                               invisibleAnnotationsCounter++;
+                       } else if (isRuntimeVisible(annotation)) {
+                               visibleAnnotationsCounter++;
+                       }
+               }
+
+               if (invisibleAnnotationsCounter != 0) {
+                       int annotationAttributeOffset = contentsOffset;
+                       if (contentsOffset + 10 >= contents.length) {
+                               resizeContents(10);
+                       }
+                       int runtimeInvisibleAnnotationsAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName);
+                       contents[contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
+                       int attributeLengthOffset = contentsOffset;
+                       contentsOffset += 4; // leave space for the attribute length
+       
+                       int annotationsLengthOffset = contentsOffset;
+                       contentsOffset += 2; // leave space for the annotations length
+               
+                       contents[annotationsLengthOffset++] = (byte) (invisibleAnnotationsCounter >> 8);
+                       contents[annotationsLengthOffset++] = (byte) invisibleAnnotationsCounter;
+
+                       loop: for (int i = 0; i < length; i++) {
+                               if (invisibleAnnotationsCounter == 0) break loop;
+                               Annotation annotation = annotations[i];
+                               if (isRuntimeInvisible(annotation)) {
+                                       generateAnnotation(annotation, annotationAttributeOffset);
+                                       invisibleAnnotationsCounter--;
+                                       if (this.contentsOffset == annotationAttributeOffset) {
+                                               break loop;
+                                       }
+                               }
+                       }
+                       if (contentsOffset != annotationAttributeOffset) {
+                               int attributeLength = contentsOffset - attributeLengthOffset - 4;
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               contents[attributeLengthOffset++] = (byte) attributeLength;                     
+                               attributesNumber++;
+                       } else {                
+                               contentsOffset = annotationAttributeOffset;
+                       }
+               }
+       
+               if (visibleAnnotationsCounter != 0) {
+                       int annotationAttributeOffset = contentsOffset;
+                       if (contentsOffset + 10 >= contents.length) {
+                               resizeContents(10);
+                       }
+                       int runtimeVisibleAnnotationsAttributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName);
+                       contents[contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
+                       int attributeLengthOffset = contentsOffset;
+                       contentsOffset += 4; // leave space for the attribute length
+       
+                       int annotationsLengthOffset = contentsOffset;
+                       contentsOffset += 2; // leave space for the annotations length
+               
+                       contents[annotationsLengthOffset++] = (byte) (visibleAnnotationsCounter >> 8);
+                       contents[annotationsLengthOffset++] = (byte) visibleAnnotationsCounter;
+
+                       loop: for (int i = 0; i < length; i++) {
+                               if (visibleAnnotationsCounter == 0) break loop;
+                               Annotation annotation = annotations[i];
+                               if (isRuntimeVisible(annotation)) {
+                                       visibleAnnotationsCounter--;
+                                       generateAnnotation(annotation, annotationAttributeOffset);
+                                       if (this.contentsOffset == annotationAttributeOffset) {
+                                               break loop;
+                                       }
+                               }
+                       }
+                       if (contentsOffset != annotationAttributeOffset) {
+                               int attributeLength = contentsOffset - attributeLengthOffset - 4;
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               contents[attributeLengthOffset++] = (byte) attributeLength;                     
+                               attributesNumber++;
+                       } else {
+                               contentsOffset = annotationAttributeOffset;
+                       }
+               }
+               return attributesNumber;
+       }
+       
+       private int generateRuntimeAnnotationsForParameters(Argument[] arguments) {
+               final int argumentsLength = arguments.length;
+               final int VISIBLE_INDEX = 0;
+               final int INVISIBLE_INDEX = 1;
+               int invisibleParametersAnnotationsCounter = 0;
+               int visibleParametersAnnotationsCounter = 0;
+               int[][] annotationsCounters = new int[argumentsLength][2];
+               for (int i = 0; i < argumentsLength; i++) {
+                       Argument argument = arguments[i];
+                       Annotation[] annotations = argument.annotations;
+                       if (annotations != null) {
+                               for (int j = 0, max2 = annotations.length; j < max2; j++) {
+                                       Annotation annotation = annotations[j];
+                                       if (isRuntimeInvisible(annotation)) {
+                                               annotationsCounters[i][INVISIBLE_INDEX]++;
+                                               invisibleParametersAnnotationsCounter++;
+                                       } else if (isRuntimeVisible(annotation)) {
+                                               annotationsCounters[i][VISIBLE_INDEX]++;
+                                               visibleParametersAnnotationsCounter++;
+                                       }
+                               }
+                       }
+               }
+               int attributesNumber = 0;
+               int annotationAttributeOffset = contentsOffset;
+               if (invisibleParametersAnnotationsCounter != 0) {
+                       if (contentsOffset + 7 >= contents.length) {
+                               resizeContents(7);
+                       }
+                       int attributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName);
+                       contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) attributeNameIndex;
+                       int attributeLengthOffset = contentsOffset;
+                       contentsOffset += 4; // leave space for the attribute length
+
+                       contents[contentsOffset++] = (byte) argumentsLength;
+                       invisibleLoop: for (int i = 0; i < argumentsLength; i++) {
+                               if (contentsOffset + 2 >= contents.length) {
+                                       resizeContents(2);
+                               }
+                               if (invisibleParametersAnnotationsCounter == 0) {
+                                       contents[contentsOffset++] = (byte) 0;
+                                       contents[contentsOffset++] = (byte) 0;                                  
+                               } else {
+                                       final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX];
+                                       contents[contentsOffset++] = (byte) (numberOfInvisibleAnnotations >> 8);
+                                       contents[contentsOffset++] = (byte) numberOfInvisibleAnnotations;
+                                       if (numberOfInvisibleAnnotations != 0) {
+                                               Argument argument = arguments[i];
+                                               Annotation[] annotations = argument.annotations;
+                                               for (int j = 0, max = annotations.length; j < max; j++) {
+                                                       Annotation annotation = annotations[j];
+                                                       if (isRuntimeInvisible(annotation)) {
+                                                               generateAnnotation(annotation, annotationAttributeOffset);
+                                                               if (contentsOffset == annotationAttributeOffset) {
+                                                                       break invisibleLoop;
+                                                               }
+                                                               invisibleParametersAnnotationsCounter--;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       if (contentsOffset != annotationAttributeOffset) {
+                               int attributeLength = contentsOffset - attributeLengthOffset - 4;
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               contents[attributeLengthOffset++] = (byte) attributeLength;                     
+                               attributesNumber++;
+                       } else {
+                               contentsOffset = annotationAttributeOffset;
+                       }
+               }
+               if (visibleParametersAnnotationsCounter != 0) {
+                       if (contentsOffset + 7 >= contents.length) {
+                               resizeContents(7);
+                       }
+                       int attributeNameIndex =
+                               constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName);
+                       contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
+                       contents[contentsOffset++] = (byte) attributeNameIndex;
+                       int attributeLengthOffset = contentsOffset;
+                       contentsOffset += 4; // leave space for the attribute length
+
+                       contents[contentsOffset++] = (byte) argumentsLength;
+                       visibleLoop: for (int i = 0; i < argumentsLength; i++) {
+                               if (contentsOffset + 2 >= contents.length) {
+                                       resizeContents(2);
+                               }
+                               if (visibleParametersAnnotationsCounter == 0) {
+                                       contents[contentsOffset++] = (byte) 0;
+                                       contents[contentsOffset++] = (byte) 0;                                  
+                               } else {
+                                       final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX];
+                                       contents[contentsOffset++] = (byte) (numberOfVisibleAnnotations >> 8);
+                                       contents[contentsOffset++] = (byte) numberOfVisibleAnnotations;
+                                       if (numberOfVisibleAnnotations != 0) {
+                                               Argument argument = arguments[i];
+                                               Annotation[] annotations = argument.annotations;
+                                               for (int j = 0, max = annotations.length; j < max; j++) {
+                                                       Annotation annotation = annotations[j];
+                                                       if (isRuntimeVisible(annotation)) {
+                                                               generateAnnotation(annotation, annotationAttributeOffset);
+                                                               if (contentsOffset == annotationAttributeOffset) {
+                                                                       break visibleLoop;
+                                                               }
+                                                               visibleParametersAnnotationsCounter--;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+                       if (contentsOffset != annotationAttributeOffset) {
+                               int attributeLength = contentsOffset - attributeLengthOffset - 4;
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
+                               contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
+                               contents[attributeLengthOffset++] = (byte) attributeLength;                     
+                               attributesNumber++;
+                       } else {
+                               contentsOffset = annotationAttributeOffset;
+                       }
+               }
+               return attributesNumber;
+       }
+       /**
         * EXTERNAL API
         * Answer the actual bytes of the class file
         *
@@ -2422,6 +3594,31 @@ public class ClassFile
                }
        }
 
+       
+       private boolean isRuntimeInvisible(Annotation annotation) {
+               final TypeBinding annotationBinding = annotation.resolvedType;
+               if (annotationBinding == null) {
+                       return false;
+               }
+               long metaTagBits = annotationBinding.getAnnotationTagBits();
+               if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
+                       return true; // by default the retention is CLASS
+                       
+               return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention;
+       }
+
+       private boolean isRuntimeVisible(Annotation annotation) {
+               final TypeBinding annotationBinding = annotation.resolvedType;
+               if (annotationBinding == null) {
+                       return false;
+               }
+               long metaTagBits = annotationBinding.tagBits;
+               if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
+                       return false; // by default the retention is CLASS
+                       
+               return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
+       }
+
        /**
         * INTERNAL USE-ONLY
         * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
@@ -2520,39 +3717,6 @@ public class ClassFile
 
        /**
         * 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() {
@@ -2560,62 +3724,4 @@ public class ClassFile
                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();
-               }
-       }
 }