APT - patch org.eclipse.jdt.core.559521
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 73434c0..e052931 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -427,9 +427,8 @@
 		TypeBinding[] annotationTypes = new TypeBinding[length];
 		for (int i = 0; i < length; i++) {
 			Annotation annotation = annotations[i];
-			annotation.recipient = recipient;
-			annotation.compilerAnnotation = new SourceAnnotation(annotation);
-			annotationTypes[i] = annotation.resolveType(scope);
+			annotation.recipient = recipient;			
+			annotationTypes[i] = annotation.resolveType(scope);			
 		}
 		// check duplicate annotations
 		for (int i = 0; i < length; i++) {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java b/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
index a48d8fa..1053019 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/Annotation.java
@@ -19,14 +19,14 @@
  */
 public abstract class Annotation extends Expression {
 	
-	final static MemberValuePair[] NoValuePairs = new MemberValuePair[0];
+	final static MemberValuePair[] NoValuePairs = new MemberValuePair[0];	
 	public int declarationSourceEnd;
 	public Binding recipient;	
 	public TypeReference type;
 	/** 
 	 *  The representation of this annotation in the type system. 
 	 */
-	public SourceAnnotation compilerAnnotation;
+	private SourceAnnotation compilerAnnotation = null;
 	
 	public static long getRetentionPolicy(char[] policyName) {
 		if (policyName == null || policyName.length == 0)
@@ -166,15 +166,21 @@
 	
 	public TypeBinding resolveType(BlockScope scope) {
 		
+		if(this.compilerAnnotation != null)
+			return this.resolvedType;		
+		
 		this.constant = NotAConstant;
 		
 		TypeBinding typeBinding = this.type.resolveType(scope);
-		if (typeBinding == null)
+		if (typeBinding == null){	
+			this.compilerAnnotation = new SourceAnnotation(this);
 			return null;
+		}
 		this.resolvedType = typeBinding;
 		// ensure type refers to an annotation type
 		if (!typeBinding.isAnnotationType()) {
 			scope.problemReporter().typeMismatchError(typeBinding, scope.getJavaLangAnnotationAnnotation(), this.type);
+			this.compilerAnnotation = new SourceAnnotation(this);
 			return null;
 		}
 
@@ -226,7 +232,8 @@
 			if (!foundValue && (method.modifiers & AccAnnotationDefault) == 0) {
 				scope.problemReporter().missingValueForAnnotationMember(this, selector);
 			}
-		}
+		}		
+		
 		// check unused pairs
 		for (int i = 0; i < pairsLength; i++) {
 			if (pairs[i] != null) {
@@ -299,8 +306,14 @@
 				scope.problemReporter().disallowedTargetForAnnotation(this);
 			}
 		}
+		this.compilerAnnotation = new SourceAnnotation(this);
 		return this.resolvedType;
 	}	
+	
+	public SourceAnnotation getCompilerAnnotation()
+	{	
+		return this.compilerAnnotation;
+	}
 		
 	public abstract void traverse(ASTVisitor visitor, BlockScope scope);
 	public abstract void traverse(ASTVisitor visitor, CompilationUnitScope scope);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java b/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
index 363754d..9df5ca3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/CompilationUnitDeclaration.java
@@ -119,6 +119,7 @@
 			}
 		}
 		if (type.binding != null) {
+			type.binding.finish();
 			// null out the type's scope backpointers
 			type.binding.scope = null;
 		}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
index 4a4ac3d..4b2430e 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/AnnotationInfo.java
@@ -81,6 +81,10 @@
 	 * of this annotation. The data structure will not be flushed out.
 	 * 
 	 * The tag bits are derived from the following (supported) standard annotation. 
+	 * java.lang.annotation.Documented,
+	 * java.lang.annotation.Retention,
+	 * java.lang.annotation.Target, and
+	 * java.lang.Deprecated
 	 * 
 	 * @param expectRuntimeVisibleAnno <code>true</cod> to indicate that this is a runtime-visible annotation
 	 * @param toplevel <code>false</code> to indicate that an nested annotation is read. <code>true</code>
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
index aa6e090..a28a9d4 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/ClassFileReader.java
@@ -323,27 +323,54 @@
  */
 private void decodeAnnotations(int offset, boolean runtimeVisible) {
 	int numberOfAnnotations = u2At(offset + 6);
-	int readOffset = offset + 8;
-	int index = 0;
-	if( numberOfAnnotations > 0 ){		
-		if( this.annotations == null )
-			this.annotations = new AnnotationInfo[numberOfAnnotations];
-		else{
-			index = this.annotations.length;
-			int newTotal = this.annotations.length + numberOfAnnotations;
-			final AnnotationInfo[] newAnnos = new AnnotationInfo[newTotal];
-			System.arraycopy(this.annotations, 0, newAnnos, 0, this.annotations.length);
-			this.annotations = newAnnos;
+	int readOffset = offset + 8;	
+	
+	if( numberOfAnnotations >  0 ){
+		int numStandardAnnotations = 0;
+		AnnotationInfo[] annos = new AnnotationInfo[numberOfAnnotations];
+		for( int i=0; i<numberOfAnnotations; i++ ){
+			// With the last parameter being 'false', the data structure 
+			// will not be flushed out. 
+			annos[i] = new AnnotationInfo( reference, readOffset, 
+										   this.constantPoolOffsets,
+										   runtimeVisible, false );
+			readOffset = annos[i].getLength() + readOffset;
+			final long standardTagBits = annos[i].getStandardAnnotationTagBits();
+			this.tagBits |= standardTagBits;
+			// annotation that can be represented by the tag bits
+			// will drop the data structure completely for memory sake.
+			if( standardTagBits != 0 ){	
+				annos[i] = null;
+				numStandardAnnotations ++;
+			}
 		}
+		
+		if( numStandardAnnotations != 0 ){ 	
+			if( numStandardAnnotations == numberOfAnnotations )
+				return;
+			
+			// need to resize
+			AnnotationInfo[] temp = new AnnotationInfo[numberOfAnnotations - numStandardAnnotations ];
+			int tmpIndex = 0;
+			for( int i=0; i<numberOfAnnotations; i++ ){
+				if( annos[i] != null )
+					temp[tmpIndex ++] = annos[i];
+			}
+			annos = temp;
+			numberOfAnnotations = numberOfAnnotations - numStandardAnnotations;
+		}		
+		
+		if( this.annotations == null )
+			this.annotations = annos;
+		else{	
+			
+			final int newTotal = this.annotations.length + numberOfAnnotations;
+			final AnnotationInfo[] newAnnos = new AnnotationInfo[newTotal];
+			System.arraycopy(this.annotations, 0, newAnnos, 0, this.annotations.length );
+			System.arraycopy(annos, 0, newAnnos, this.annotations.length, numberOfAnnotations);
+			this.annotations = newAnnos;
+		}		
 	}	
-	for (int i = 0; i < numberOfAnnotations; i++, index++) {
-		this.annotations[index] = new AnnotationInfo(reference, 
-											    	 readOffset, 
-													 this.constantPoolOffsets, 
-													 runtimeVisible, false);
-		readOffset = this.annotations[index].getLength() + readOffset;		
-		this.tagBits |= this.annotations[index].getStandardAnnotationTagBits();		
-	}
 }
 /**
  * Answer the char array that corresponds to the class name of the constant class.
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
index da3a2e5..d6e08d8 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/FieldInfo.java
@@ -88,35 +88,55 @@
  * annotation attribute.
  */
 private void decodeAnnotations(int offset, boolean runtimeVisible) {
-/*
-int actualOffset = offset + structOffset;
-String text = runtimeVisible ?  " runtime visible " : " runtime invisible ";
-System.err.println("decoding field_info" + text + "annotation at " + actualOffset);
-*/
 	int numberOfAnnotations = u2At(offset + 6);
-	int readOffset = offset + 8;
-	int index=0;
+	int readOffset = offset + 8;	
 	if( numberOfAnnotations > 0 ){		
+		int numStandardAnnotations = 0;
+		AnnotationInfo[] annos = new AnnotationInfo[numberOfAnnotations];
+		for (int i = 0; i < numberOfAnnotations; i++) {		
+			annos[i] = new AnnotationInfo(reference, 
+								          readOffset + structOffset, 
+										  this.constantPoolOffsets, 
+										  runtimeVisible, 
+										  false);
+			readOffset = annos[i].getLength() + readOffset;		
+			final long stdAnnotationTagBits = 
+				annos[i].getStandardAnnotationTagBits();
+			this.tagBits |= stdAnnotationTagBits;
+			// the tag bits represents the annotation, don't need a separate 
+			// data structure for that.
+			if(stdAnnotationTagBits != 0){
+				annos[i] = null;
+				numStandardAnnotations ++;
+			}
+		}
+		if( numStandardAnnotations != 0 ){ 
+			// all of them are standard annotations
+			if( numStandardAnnotations == numberOfAnnotations )
+				return;
+			else{ // need to resize	
+				AnnotationInfo[] temp = new AnnotationInfo[numberOfAnnotations - numStandardAnnotations ];
+				int tmpIndex = 0;
+				for( int i=0; i<numberOfAnnotations; i++ ){
+					if( annos[i] != null )
+						temp[tmpIndex ++] = annos[i];
+				}
+				annos = temp;
+				numberOfAnnotations = numberOfAnnotations - numStandardAnnotations;
+			}
+		}	
 		if( this.annotations == null )
-			this.annotations = new AnnotationInfo[numberOfAnnotations];
+			this.annotations = annos;
 		else{
-			int curlen = this.annotations.length;
-			index = curlen;
+			int curlen = this.annotations.length;			
 			int newTotal = curlen + numberOfAnnotations;
 			final AnnotationInfo[] newAnnos = new AnnotationInfo[newTotal];
 			System.arraycopy(this.annotations, 0, newAnnos, 0, curlen);
+			System.arraycopy(annos, 0, newAnnos, curlen, numberOfAnnotations);
 			this.annotations = newAnnos;
 		}
 	}	
-	for (int i = 0; i < numberOfAnnotations; i++, index++) {		
-		this.annotations[index] = new AnnotationInfo(reference, 
-											           readOffset + structOffset, 
-													   this.constantPoolOffsets, 
-													   runtimeVisible, 
-													   false);
-		readOffset = this.annotations[index].getLength() + readOffset;		
-		this.tagBits |= this.annotations[index].getStandardAnnotationTagBits();
-	}
+	
 }
 /**
  * Return the constant of the field.
diff --git a/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java b/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
index 22a57bf..01ba4c3 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/classfmt/MethodInfo.java
@@ -150,12 +150,33 @@
  */
 private void decodeMethodAnnotations(int offset, boolean runtimeVisible){
 	int numberOfAnnotations = u2At(offset + 6);
-	final AnnotationInfo[] annos = decodeAnnotations(offset + 8, runtimeVisible, numberOfAnnotations);
+	AnnotationInfo[] annos = decodeAnnotations(offset + 8, runtimeVisible, numberOfAnnotations);
 	
 	if( numberOfAnnotations > 0 ){
 		if( runtimeVisible ){
+			int numStandardAnnotations = 0;			
 			for( int i=0; i<numberOfAnnotations; i++ ){
-				this.tagBits |= annos[i].getStandardAnnotationTagBits();
+				final long standardAnnoTagBits = annos[i].getStandardAnnotationTagBits();
+				this.tagBits |= standardAnnoTagBits;
+				if(standardAnnoTagBits != 0){
+					annos[i] = null;
+					numStandardAnnotations ++;
+				}
+			}
+			
+			if( numStandardAnnotations != 0 ){
+				if( numStandardAnnotations == numberOfAnnotations )
+					return;
+				
+				// need to resize			
+				AnnotationInfo[] temp = new AnnotationInfo[numberOfAnnotations - numStandardAnnotations ];
+				int tmpIndex = 0;
+				for( int i=0; i<numberOfAnnotations; i++ ){
+					if( annos[i] != null )
+						temp[tmpIndex ++] = annos[i];
+				}
+				annos = temp;
+				numberOfAnnotations = numberOfAnnotations - numStandardAnnotations;				
 			}
 		}
 		
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationMethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationMethodBinding.java
index baf203b..33d1eaa 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationMethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationMethodBinding.java
@@ -10,30 +10,52 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.compiler.lookup;
 
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+
 /**
- * Annotation method that came from binary.
+ * Annotation method that came from binary or source
  * @author tyeung
  *
  */
-public class AnnotationMethodBinding extends BinaryMethodBinding 
+public class AnnotationMethodBinding extends MethodBinding 
 {
-	private Object defaultValue;
+	private Object defaultValue = null;
+	/**
+	 * 
+	 * @param modifiers
+	 * @param selector
+	 * @param returnType
+	 * @param declaringClass	
+	 * @param defaultValue <code>null</code> for source method. 
+	 */
 	public AnnotationMethodBinding(int modifiers,
 								   char[] selector, 
 								   TypeBinding returnType, 
-								   ReferenceBinding declaringClass,
-								   IAnnotationInstance[] methodAnnotation,
-								   IAnnotationInstance[][] parameterAnnotations,
+								   ReferenceBinding declaringClass,								  
 								   Object defaultValue)
 	{
-		super(modifiers, selector, 
-			 returnType, NoParameters, 
-			 NoExceptions, declaringClass,
-			 methodAnnotation, parameterAnnotations );
-		
+		super(modifiers, selector, returnType, NoParameters, NoExceptions, declaringClass );
 		this.defaultValue = defaultValue;
+		setDefaultValue();	
 	}
 	
+	private void setDefaultValue()
+	{			
+		if (this.declaringClass instanceof SourceTypeBinding) {
+			TypeDeclaration typeDecl = ((SourceTypeBinding)this.declaringClass).scope.referenceContext;
+			final AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(this);
+			if( methodDecl instanceof AnnotationMethodDeclaration){
+				this.defaultValue = SourceElementValuePair.getValue(((AnnotationMethodDeclaration)methodDecl).defaultValue);
+			}
+		}
+	}
+	
+	/**
+	 * @return the default value for this annotation method.
+	 *         Return <code>null</code> if there is no default value 
+	 */
 	public Object getDefaultValue()
 	{
 		return this.defaultValue;
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationUtils.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationUtils.java
new file mode 100644
index 0000000..e645e8b
--- /dev/null
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/AnnotationUtils.java
@@ -0,0 +1,138 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    tyeung@bea.com - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.internal.compiler.lookup;
+
+class AnnotationUtils {
+	/**
+	 * Build out the data structure representing the standard annotations.
+	 * @param annotationTagBits 
+	 * @param result to be filled by this method starting from index 0
+	 * @param env
+	 * @return the number of standard annotations found 
+	 */
+	static int buildStandardAnnotations(final long annotationTagBits, 
+										final IAnnotationInstance[] result,
+										final LookupEnvironment env)
+	{
+		int index = 0;
+		if( (annotationTagBits & TagBits.AnnotationTargetMASK) != 0 )
+			result[index++] = buildTargetAnnotation(annotationTagBits, env);
+		if( (annotationTagBits & TagBits.AnnotationRetentionMASK) != 0 ) 
+			result[index++] = buildRetentionAnnotation(annotationTagBits, env);
+		if( (annotationTagBits & TagBits.AnnotationDeprecated) != 0 )
+			result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_DEPRECATED_SIG, env);
+		if( (annotationTagBits & TagBits.AnnotationDocumented) != 0 )
+			result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_DOCUMENTED_SIG, env);
+		if( (annotationTagBits & TagBits.AnnotationInherited) != 0 )
+			result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_INHERITED_SIG, env);
+		if( (annotationTagBits & TagBits.AnnotationOverride) != 0 )
+			result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_OVERRIDE_SIG, env);
+		if( (annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0 )
+			result[index++] = buildMarkerAnnotation(TypeConstants.CharArray_JAVA_LANG_SUPRESSWARNING_SIG, env);
+		return index;
+	}
+
+	static int getNumberOfStandardAnnotations(final long annotationTagBits)
+	{	
+		int count = 0;
+		if( (annotationTagBits & TagBits.AnnotationTargetMASK) != 0 ) count ++;		
+		if( (annotationTagBits & TagBits.AnnotationRetentionMASK) != 0 ) count ++;
+		if( (annotationTagBits & TagBits.AnnotationDeprecated) != 0 ) count ++;
+		if( (annotationTagBits & TagBits.AnnotationDocumented) != 0 ) count ++;
+		if( (annotationTagBits & TagBits.AnnotationInherited) != 0 ) count ++;
+		if( (annotationTagBits & TagBits.AnnotationOverride) != 0 ) count ++;
+		if( (annotationTagBits & TagBits.AnnotationSuppressWarnings) != 0 ) count ++;
+		
+		return count;	
+	}
+
+	private static IAnnotationInstance buildMarkerAnnotation(final char[] sig, final LookupEnvironment env)
+	{
+		final ReferenceBinding type = (ReferenceBinding)env.getTypeFromSignature(sig, 0, -1, false, null);
+		return new BinaryAnnotation(type, env);
+	}
+
+	private static IAnnotationInstance buildTargetAnnotation(final long bits, final LookupEnvironment env)
+	{	
+		final ReferenceBinding target = (ReferenceBinding)
+			env.getTypeFromSignature(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_TARGET_SIG, 
+									 0, -1, false, null);
+		final BinaryAnnotation anno = new BinaryAnnotation(target, env);
+		if( (bits & TagBits.AnnotationTarget) != 0 )
+			return anno;
+		
+		ReferenceBinding elementType = (ReferenceBinding)
+			env.getTypeFromSignature(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_ELEMENTTYPE_SIG, 
+					  							  0, -1, false, null);
+		int arraysize = 0;
+		if( (bits & TagBits.AnnotationForAnnotationType) != 0 ) arraysize ++;
+		if( (bits & TagBits.AnnotationForConstructor) != 0 ) arraysize ++;
+		if( (bits & TagBits.AnnotationForField) != 0 ) arraysize ++;
+		if( (bits & TagBits.AnnotationForLocalVariable) != 0 ) arraysize ++;
+		if( (bits & TagBits.AnnotationForMethod) != 0 ) arraysize ++;
+		if( (bits & TagBits.AnnotationForPackage) != 0 ) arraysize ++;
+		if( (bits & TagBits.AnnotationForParameter) != 0 ) arraysize ++;
+		if( (bits & TagBits.AnnotationForType) != 0 ) arraysize ++;
+		
+		final Object[] value = new Object[arraysize];
+		if( arraysize > 0 ){
+			elementType = BinaryTypeBinding.resolveType(elementType, env, false);
+			int index = 0;
+			if( (bits & TagBits.AnnotationForAnnotationType) != 0 ) 
+				value[index++] = elementType.getField(TypeConstants.UPPER_ANNOTATION_TYPE, true);
+			if( (bits & TagBits.AnnotationForConstructor) != 0 ) 
+				value[index++] = elementType.getField(TypeConstants.UPPER_CONSTRUCTOR, true);
+			if( (bits & TagBits.AnnotationForField) != 0 ) 
+				value[index++] = elementType.getField(TypeConstants.UPPER_FIELD, true);
+			if( (bits & TagBits.AnnotationForLocalVariable) != 0 ) 
+				value[index++] = elementType.getField(TypeConstants.UPPER_LOCAL_VARIABLE, true);
+			if( (bits & TagBits.AnnotationForMethod) != 0 ) 
+				value[index++] = elementType.getField(TypeConstants.UPPER_METHOD, true);
+			if( (bits & TagBits.AnnotationForPackage) != 0 )
+				value[index++] = elementType.getField(TypeConstants.UPPER_PACKAGE, true);
+			if( (bits & TagBits.AnnotationForParameter) != 0 ) 
+				value[index++] = elementType.getField(TypeConstants.UPPER_PARAMETER, true);
+			if( (bits & TagBits.AnnotationForType) != 0 ) 
+				value[index++] = elementType.getField(TypeConstants.TYPE, true);
+		}
+		
+		anno.pairs = new IElementValuePair[]{ new BinaryElementValuePair(anno, TypeConstants.VALUE, value) };
+		return anno;
+	}
+
+	private static IAnnotationInstance buildRetentionAnnotation(final long bits, final LookupEnvironment env)
+	{
+		final ReferenceBinding retention = (ReferenceBinding)
+		env.getTypeFromSignature(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_RETENTION_SIG, 
+											  0, -1, false, null);
+		ReferenceBinding retentionPolicy = (ReferenceBinding)
+			env.getTypeFromSignature(TypeConstants.CharArray_JAVA_LANG_ANNOTATION_RETENTIONPOLICY_SIG, 
+					  							  0, -1, false, null);
+
+		final BinaryAnnotation anno = new BinaryAnnotation(retention, env);
+		
+		Object value = null; 	
+		{
+			retentionPolicy = BinaryTypeBinding.resolveType(retentionPolicy, env, false);		
+			if( (bits & TagBits.AnnotationRuntimeRetention) != 0 ) 
+				value = retentionPolicy.getField(TypeConstants.UPPER_RUNTIME, true);		
+			else if( (bits & TagBits.AnnotationClassRetention) != 0 ) 
+				value = retentionPolicy.getField(TypeConstants.UPPER_CLASS, true);
+			else if( (bits & TagBits.AnnotationSourceRetention) != 0 ) 
+				value = retentionPolicy.getField(TypeConstants.UPPER_SOURCE, true);
+			
+		}
+		anno.pairs = new IElementValuePair[]{ new BinaryElementValuePair(anno, TypeConstants.VALUE, value) };
+		return anno;
+
+	}
+
+}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryAnnotation.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryAnnotation.java
index 067bdda..c5e8fd2 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryAnnotation.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryAnnotation.java
@@ -24,7 +24,7 @@
 	BinaryAnnotation(ReferenceBinding binding, LookupEnvironment env)
 	{ 
 		this.typeBinding = binding;
-		this.pairs = null;
+		this.pairs = TypeConstants.NoElementValuePairs;
 		this.env = env;		
 	}
 	
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
index e8a684f..615a923 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java
@@ -47,10 +47,9 @@
 private MethodBinding[] methods;
 private ReferenceBinding[] memberTypes;
 protected TypeVariableBinding[] typeVariables;
-private IAnnotationInstance[] annotations;
 
 // For the link with the principle structure
-private LookupEnvironment environment;
+LookupEnvironment environment;
 
 public static ReferenceBinding resolveType(ReferenceBinding type, LookupEnvironment environment, boolean convertGenericToRawType) {
 	if (type instanceof UnresolvedReferenceBinding)
@@ -179,8 +178,6 @@
 	return availableMethods;
 }
 
-public IAnnotationInstance[] getAnnotations(){ return this.annotations; }
-
 void cachePartsFrom(IBinaryType binaryType, boolean needFieldsAndMethods) {
 	// default initialization for super-interfaces early, in case some aborting compilation error occurs,
 	// and still want to use binaries passed that point (e.g. type hierarchy resolver, see bug 63748).
@@ -308,7 +305,7 @@
 {	
 	final int len = pairs == null ? 0 : pairs.length; 
 	anno.pairs = NoElementValuePairs;
-	if( len > 1 ){
+	if( len > 0 ){
 		anno.pairs = new IElementValuePair[len]; 
 		for( int i = 0; i < len; i++ ){
 			anno.pairs[i] = new BinaryElementValuePair(anno, 
@@ -331,7 +328,8 @@
 	
 	else if( binaryValue instanceof IEnumConstantReference ){
 		final IEnumConstantReference ref = (IEnumConstantReference)binaryValue;
-		final ReferenceBinding enumType = environment.getTypeFromConstantPoolName(ref.getTypeName(), 0, -1, false);
+		ReferenceBinding enumType = (ReferenceBinding)environment.getTypeFromSignature(ref.getTypeName(), 0, -1, false, null);
+		enumType = BinaryTypeBinding.resolveType(enumType, this.environment, false);
 		return enumType.getField(ref.getEnumConstantName(), false);
 	}
 	else if( binaryValue instanceof Object[] ){
@@ -367,13 +365,9 @@
 					: environment.getTypeFromTypeSignature(new SignatureWrapper(fieldSignature), NoTypeVariables, this);
 				IAnnotationInstance[] fieldAnnos = createAnnotations(binaryField.getAnnotations());
 				FieldBinding field = 
-					new BinaryFieldBinding(
-						binaryField.getName(), 
-						type, 
-						binaryField.getModifiers() | AccUnresolved, 
-						this, 
-						binaryField.getConstant(),
-						fieldAnnos);
+					new FieldBinding( binaryField.getName(), type, binaryField.getModifiers() | AccUnresolved, 
+						  			  this, binaryField.getConstant() );				
+				field.setAnnotations(fieldAnnos);
 				field.id = i; // ordinal
 				if (use15specifics)
 					field.tagBits |= binaryField.getTagBits();
@@ -503,31 +497,18 @@
 	
 	final MethodBinding result;
 	if( method.isConstructor() )
-		result = new BinaryMethodBinding(methodModifiers, 
-				 						 parameters, 
-										 exceptions, 
-										 this, 
-										 methodAnnos,
-										 paramAnnotations);
+		result = new MethodBinding(methodModifiers, parameters, exceptions, this); 
+		
 	else{
-		if( isAnnotationType() ){			
-			result = new AnnotationMethodBinding(methodModifiers, 
-												 method.getSelector(), 
-												 returnType,
-												 this,
-												 methodAnnos,
-												 paramAnnotations,
-												 getMemberValue(method.getDefaultValue()));
+		if( isAnnotationType() ){	
+			if( method instanceof org.eclipse.jdt.internal.compiler.classfmt.MethodInfo )
+				result = new AnnotationMethodBinding(methodModifiers, method.getSelector(), returnType, this, getMemberValue(method.getDefaultValue()));
+			else
+				throw new IllegalStateException(method.getClass().getName());
 		}
-		else result = new BinaryMethodBinding(methodModifiers, 
-											  method.getSelector(), 
-											  returnType, 
-											  parameters, 
-											  exceptions, 
-											  this,
-											  methodAnnos,
-											  paramAnnotations); 
+		else result = new MethodBinding(methodModifiers, method.getSelector(), returnType, parameters, exceptions, this);
 	}
+	result.setExtendedModifiers(methodAnnos, paramAnnotations);
 	
 	if (use15specifics)
 		result.tagBits |= method.getTagBits();
@@ -918,6 +899,24 @@
 	this.tagBits &= ~HasUnresolvedTypeVariables;
 	return this.typeVariables;
 }
+
+public IAnnotationInstance[] getAnnotations()
+{	
+	final long annotationTagBits = getAnnotationTagBits();
+	// TODO: add a flag so we don't repeat this process.
+	final int numStdAnnotations = AnnotationUtils.getNumberOfStandardAnnotations(annotationTagBits);
+	if( numStdAnnotations == 0 ) return this.annotations;	
+	
+	final int nonStandard = this.annotations == null ? 0 : this.annotations.length;
+	final int total = numStdAnnotations + nonStandard;
+	final IAnnotationInstance[] result = new BinaryAnnotation[total];
+	final int index = AnnotationUtils.buildStandardAnnotations(annotationTagBits, result, this.environment);
+	if( nonStandard != 0 ){
+		System.arraycopy(this.annotations, 0, result, index, this.annotations.length);
+	}
+	return result;
+}
+
 public String toString() {
 	String s = ""; //$NON-NLS-1$
 
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
index 258654e..a34180c 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/FieldBinding.java
@@ -24,20 +24,27 @@
 	super(null, null, 0, null);
 	// for creating problem field
 }
-public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant) {
+
+public FieldBinding(char[] name, TypeBinding type, int modifiers, ReferenceBinding declaringClass, Constant constant)
+{
 	super(name, type, modifiers, constant);
 	this.declaringClass = declaringClass;
 }
+
 public FieldBinding(FieldDeclaration field, TypeBinding type, int modifiers, ReferenceBinding declaringClass) {
 	this(field.name, type, modifiers, declaringClass, null);
 	field.binding = this; // record binding in declaration
 }
+
 // special API used to change field declaring class for runtime visibility check
 public FieldBinding(FieldBinding initialFieldBinding, ReferenceBinding declaringClass) {
-	super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, initialFieldBinding.constant());
+	super(initialFieldBinding.name, initialFieldBinding.type, initialFieldBinding.modifiers, 
+		  initialFieldBinding.constant());
 	this.declaringClass = declaringClass;
 	this.id = initialFieldBinding.id;
+	this.annotations = initialFieldBinding.annotations;
 }
+
 /* API
 * Answer the receiver's binding type from Binding.BindingID.
 */
@@ -188,11 +195,78 @@
 		TypeDeclaration typeDecl = ((SourceTypeBinding)originalField.declaringClass).scope.referenceContext;
 		FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
 		if (fieldDecl != null)
-			ASTNode.resolveAnnotations(isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope, fieldDecl.annotations, originalField);
+			ASTNode.resolveAnnotations(isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope, fieldDecl.annotations, originalField);		
 	}
 	return originalField.tagBits;
 }
 
+private boolean isBinary()
+{
+	return this.declaringClass != null && this.declaringClass.isBinaryBinding();
+}
+
+public IAnnotationInstance[] getAnnotations()
+{
+	if(this.annotations == null )
+		buildAnnotations();
+	// binary annotations can be encoded in tag bits.
+	if( isBinary() ){
+		final int current = this.annotations.length;		
+		final long annotationTagBits = getAnnotationTagBits();
+		final int numStandardAnnos = AnnotationUtils.getNumberOfStandardAnnotations(annotationTagBits);		
+		if( numStandardAnnos == 0 )
+			return this.annotations;
+		else{
+			final LookupEnvironment env = ((BinaryTypeBinding)this.declaringClass).environment;
+			final int total = current + numStandardAnnos;
+			final BinaryAnnotation[] result = new BinaryAnnotation[total];
+			final int index = AnnotationUtils.buildStandardAnnotations(annotationTagBits, result, env);
+			if( current == 0 )
+				return result;
+			else{
+				System.arraycopy(this.annotations, 0, result, index, current);
+				return result;
+			}
+		}
+	}
+	else
+		return this.annotations;
+}
+
+void buildAnnotations()
+{
+	if( this.annotations != null ) return;
+	this.annotations = NoAnnotations;
+	FieldBinding originalField = this.original();
+	// length field of an array don't have a declaring class.
+	if( originalField.declaringClass != null && originalField.declaringClass instanceof SourceTypeBinding){				
+		TypeDeclaration typeDecl = ((SourceTypeBinding)originalField.declaringClass).scope.referenceContext;
+		FieldDeclaration fieldDecl = typeDecl.declarationOf(originalField);
+		
+		if (fieldDecl != null){
+			final Annotation[] fieldAnnos = fieldDecl.annotations;
+			final int len = fieldAnnos == null ? 0 : fieldAnnos.length;
+			if( len > 0 )
+			{
+				this.annotations = new IAnnotationInstance[len];
+				for( int i = 0; i < len; i++ ){
+					final BlockScope scope = isStatic() ? typeDecl.staticInitializerScope : typeDecl.initializerScope;
+					fieldAnnos[i].resolveType(scope);
+					this.annotations[i] = fieldAnnos[i].getCompilerAnnotation();
+				}
+			}
+		}
+	}	
+}
+
+protected void setAnnotations(final IAnnotationInstance[] annos )
+{
+	if( annos == null )
+		this.annotations = NoAnnotations;
+	else
+		this.annotations = annos;
+}
+	
 /* Answer true if the receiver has default visibility
 */
 
@@ -281,28 +355,4 @@
 	}
 	return null;		
 }
-
-public IAnnotationInstance[] getAnnotations() { 	
-	// make sure we check the annotations for problems
-	getAnnotationTagBits();				
-	IAnnotationInstance[] result = NoAnnotations;
-	// length field of an array don't have a declaring class.
-	if( this.declaringClass != null && !this.declaringClass.isBinaryBinding() ){				
-		TypeDeclaration typeDecl = ((SourceTypeBinding)this.declaringClass).scope.referenceContext;
-		FieldDeclaration fieldDecl = typeDecl.declarationOf(this);
-		
-		if (fieldDecl != null){
-			final Annotation[] fieldAnnos = fieldDecl.annotations;
-			final int len = fieldAnnos == null ? 0 : fieldAnnos.length;
-			if( len > 0 )
-			{
-				result = new IAnnotationInstance[len];
-				for( int i = 0; i < len; i++ ){
-					result[i] = fieldAnnos[i].compilerAnnotation;
-				}
-			}
-		}
-	}
-	return result;
-}
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
index 1fa40ad..a9c0105 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/LocalVariableBinding.java
@@ -40,6 +40,7 @@
 	public LocalVariableBinding(char[] name, TypeBinding type, int modifiers, boolean isArgument) {
 		super(name, type, modifiers, isArgument ? Constant.NotAConstant : null);
 		this.isArgument = isArgument;
+		this.annotations = null;
 	}
 	
 	// regular local variable or argument
@@ -47,6 +48,7 @@
 
 		this(declaration.name, type, modifiers, isArgument);
 		this.declaration = declaration;
+		this.annotations = null;
 	}
 
 	/* API
@@ -132,21 +134,29 @@
 	}
 	
 	public IAnnotationInstance[] getAnnotations()
-	{		
+	{
+		if(this.annotations != null) 
+			return this.annotations;
+		buildAnnotations();
+		return this.annotations;
+	}
+	
+	private void buildAnnotations()
+	{
+		this.annotations = NoAnnotations;
 		if( this.isArgument && this.declaration != null){
 			final Annotation[] argAnnos = declaration.annotations;
 			final int numAnnotations = argAnnos == null ? 0 : argAnnos.length;
-			IAnnotationInstance[] result = NoAnnotations;
+			
 			if( numAnnotations > 0 ){
-				result = new SourceAnnotation[numAnnotations];
+				this.annotations = new SourceAnnotation[numAnnotations];
 				// check for errors
 				ASTNode.resolveAnnotations(declaringScope, argAnnos, this);
 				for( int j=0; j<numAnnotations; j++ ){
-					result[j] = new SourceAnnotation(argAnnos[j]);
+					this.annotations[j] = new SourceAnnotation(argAnnos[j]);
 				}
 			}		
 		}
-		return null;
 	}
 
 	public String toString() {
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
index aa1d252..e4ea865 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodBinding.java
@@ -14,20 +14,38 @@
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
 import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
 import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
 
-public class MethodBinding extends Binding implements BaseTypes, TypeConstants {
-	
+public class MethodBinding extends Binding implements BaseTypes, TypeConstants 
+{		
+	protected static final IAnnotationInstance[][] NoAnnotationsAtAll = new IAnnotationInstance[0][0];
 	public int modifiers;
 	public char[] selector;
 	public TypeBinding returnType;
 	public TypeBinding[] parameters;
 	public ReferenceBinding[] thrownExceptions;
 	public ReferenceBinding declaringClass;
-	public TypeVariableBinding[] typeVariables = NoTypeVariables;
+	public TypeVariableBinding[] typeVariables = NoTypeVariables;	
+	
+	/**
+	 * In the majority of the time, there will no annotations at all.
+	 * We will try to optimized the storage by packing both
+	 * method and parameter annotation into one field. 
+	 * 
+	 * If there are no annotations and no parameter annotations, 
+	 * this will be a zero-length array. 
+	 * If this is an array of size 1, then method annotations are intialized and there 
+	 * may or may not be parameter annotations. 
+	 * If there are ever any parameter annotations, this will be an array of size > 1. 
+	 * </code>null</code> in the array means not initialized.
+	 * If the field is <code>null</code> this means it is not initalized at all.
+	 * Binary types should always initialize this field;
+	 * Method annotations are always at index 0 and parameter annotations 
+	 * always start at index 1 if they are ever present.
+	 */
+	protected IAnnotationInstance[][] extendedModifiers = null;
 	char[] signature;
 	public long tagBits;
 	
@@ -35,6 +53,7 @@
 	// for creating problem or synthetic method
 }
 public MethodBinding(int modifiers, char[] selector, TypeBinding returnType, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
+
 	this.modifiers = modifiers;
 	this.selector = selector;
 	this.returnType = returnType;
@@ -49,18 +68,23 @@
 				this.modifiers |= AccStrictfp;
 	}
 }
+
+// constructor for creating binding representing constructor
 public MethodBinding(int modifiers, TypeBinding[] parameters, ReferenceBinding[] thrownExceptions, ReferenceBinding declaringClass) {
 	this(modifiers, TypeConstants.INIT, VoidBinding, parameters, thrownExceptions, declaringClass);
 }
+
 // special API used to change method declaring class for runtime visibility check
-public MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
+protected MethodBinding(MethodBinding initialMethodBinding, ReferenceBinding declaringClass) {
 	this.modifiers = initialMethodBinding.modifiers;
 	this.selector = initialMethodBinding.selector;
 	this.returnType = initialMethodBinding.returnType;
 	this.parameters = initialMethodBinding.parameters;
 	this.thrownExceptions = initialMethodBinding.thrownExceptions;
 	this.declaringClass = declaringClass;
+	this.extendedModifiers = initialMethodBinding.extendedModifiers;
 }
+
 /* Answer true if the argument types & the receiver's parameters are equal
 */
 public final boolean areParametersEqual(MethodBinding method) {
@@ -367,6 +391,165 @@
 	return modifiers & AccJustFlag;
 }
 
+void buildAnnotations()
+{
+	if( this.extendedModifiers != null ) return;
+	IAnnotationInstance[] methodAnnotations = buildMethodAnnotations();
+	IAnnotationInstance[][] paramAnnotations = buildParamAnnotations();
+	setExtendedModifiers(methodAnnotations, paramAnnotations);
+}
+
+public void setExtendedModifiers(final IAnnotationInstance[] methodAnnotations, 
+								 final IAnnotationInstance[][] parameterAnnotations )
+{
+	final int numMethodAnnos = methodAnnotations == null ?  0 : methodAnnotations.length;
+	final int numParams = parameterAnnotations == null ? 0 : parameterAnnotations.length; 
+	if( numMethodAnnos == 0 && numParams == 0 )
+		this.extendedModifiers = NoAnnotationsAtAll;
+	else if( numParams == 0 )
+		// no even going to create that spot.
+		this.extendedModifiers = new IAnnotationInstance[][]{ methodAnnotations };
+	else{
+		this.extendedModifiers = new IAnnotationInstance[numParams + 1][]; 
+		this.extendedModifiers[0] = methodAnnotations;
+		int extModIndex = 1;
+		for( int pIndex=0; pIndex<numParams; pIndex++, extModIndex ++ ){
+			this.extendedModifiers[extModIndex] = parameterAnnotations[pIndex];
+			if( this.extendedModifiers[extModIndex] == null )
+				this.extendedModifiers[extModIndex] = NoAnnotations;
+		}
+	}	
+}
+
+private IAnnotationInstance[] buildMethodAnnotations()
+{
+	IAnnotationInstance[] methodAnno = NoAnnotations;	
+	MethodBinding originalMethod = this.original();
+	if(!isBinary())
+	{
+		TypeDeclaration typeDecl = ((SourceTypeBinding)originalMethod.declaringClass).scope.referenceContext;		
+		AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);
+					
+		if (methodDecl != null){
+			final int len = methodDecl.annotations == null ? 0 : methodDecl.annotations.length;
+			if( len > 0 ){
+				methodAnno = new IAnnotationInstance[len];
+				for( int i=0; i<len; i++ ){
+					methodDecl.annotations[i].resolveType(methodDecl.scope);
+					methodAnno[i] = methodDecl.annotations[i].getCompilerAnnotation();
+				}
+			}			
+		}		
+	}
+	return methodAnno;
+}
+
+private IAnnotationInstance[][] buildParamAnnotations()
+{
+	IAnnotationInstance[][] result = null;
+	MethodBinding originalMethod = this.original();
+	if(!isBinary())
+	{
+		TypeDeclaration typeDecl = ((SourceTypeBinding)originalMethod.declaringClass).scope.referenceContext;
+		AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);		
+		if(methodDecl != null ){
+			final Argument[] args = methodDecl.arguments;
+			final int numArgs = args == null ? 0 : args.length;
+			for( int argIndex=0; argIndex<numArgs; argIndex++ )
+			{
+				final Argument arg = args[argIndex];
+				final Annotation[] argAnnos = arg.annotations;
+				final int numAnnotations = argAnnos == null ? 0 : argAnnos.length;				
+				if( numAnnotations > 0 ){
+					if( result == null ){
+						result = new IAnnotationInstance[numArgs][];
+						for( int i=0; i<numArgs; i++ )
+							result[i] = NoAnnotations;
+					}
+					result[argIndex] = new SourceAnnotation[numAnnotations];
+					// check for errors
+					ASTNode.resolveAnnotations(methodDecl.scope, argAnnos, this);
+					for( int j=0; j<numAnnotations; j++ ){
+						argAnnos[j].resolveType(methodDecl.scope);
+						result[argIndex][j] = argAnnos[j].getCompilerAnnotation();
+					}
+				}	
+			}
+		}
+	}
+	
+	return result;
+}
+
+private boolean isBinary()
+{
+	final MethodBinding originalMethod = this.original();
+	return originalMethod.declaringClass != null &&
+		   originalMethod.declaringClass.isBinaryBinding();
+}
+
+/**
+ * @return the annotations annotating this method.
+ *         Return a zero-length array if none is found.
+ */
+public IAnnotationInstance[] getAnnotations()
+{	
+	if( this.extendedModifiers == null )
+		buildAnnotations();
+	final boolean isBinary = isBinary();	
+	// part of the binary annotations are in the tag bits
+	if( isBinary ){
+		final long stdAnnoTagBits = getAnnotationTagBits();
+		final int numStandardAnnotations = AnnotationUtils.getNumberOfStandardAnnotations(stdAnnoTagBits);
+		final int current = this.extendedModifiers.length == 0 ? 0 : 
+							this.extendedModifiers[0].length;		
+		if( numStandardAnnotations == 0 ){
+			if(this.extendedModifiers.length == 0) 
+				return NoAnnotations;
+			else
+				return this.extendedModifiers[0];
+		}
+		else{			
+			final LookupEnvironment env = ((BinaryTypeBinding)this.declaringClass).environment;
+			final int total = numStandardAnnotations + current;
+			final BinaryAnnotation[] result = new BinaryAnnotation[total];
+			final int index = AnnotationUtils.buildStandardAnnotations(stdAnnoTagBits, result, env);
+			if( current == 0 )
+				return result;
+			else{
+				System.arraycopy(this.extendedModifiers[0], 0, result, index, current);
+				return result;
+			}
+		}
+	}
+	else{
+		if( this.extendedModifiers.length == 0 )
+			return NoAnnotations;
+		else
+			return this.extendedModifiers[0];
+	}
+}
+
+/**
+ * @param index the index of the parameter of interest
+ * @return the annotations on the <code>index</code>th parameter
+ * @throws ArrayIndexOutOfBoundsException when <code>index</code> is not valid 
+ */
+public IAnnotationInstance[] getParameterAnnotations(final int index)
+{
+	getAnnotationTagBits();
+	final int len = this.extendedModifiers.length;
+	if( len < 2 )
+		return NoAnnotations;
+	else{
+		final int extModIndex = index + 1;
+		if( extModIndex < 1 || extModIndex >= len )
+			throw new ArrayIndexOutOfBoundsException("length = " + len + " index = " + index );   //$NON-NLS-1$ //$NON-NLS-2$
+		return this.extendedModifiers[extModIndex];
+	}
+}
+
+
 /**
  * Compute the tagbits for standard annotations. For source types, these could require
  * lazily resolving corresponding annotation nodes, in case of forward references.
@@ -378,93 +561,11 @@
 		TypeDeclaration typeDecl = ((SourceTypeBinding)originalMethod.declaringClass).scope.referenceContext;
 		AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(originalMethod);
 		if (methodDecl != null)
-			ASTNode.resolveAnnotations(methodDecl.scope, methodDecl.annotations, originalMethod);
+			ASTNode.resolveAnnotations(methodDecl.scope, methodDecl.annotations, originalMethod);		
 	}
 	return originalMethod.tagBits;
 }
 
-/**
- * @return the annotations annotating this method.
- *         Return a zero-length array if none is found.
- */
-public IAnnotationInstance[] getAnnotations() 
-{	
-	// make sure they are checked for problems/
-	// this call will also initialize the 'compilerAnnotation' field.
-	getAnnotationTagBits();
-	IAnnotationInstance[] methodAnno = NoAnnotations;	
-	if(this.declaringClass != null && this.declaringClass instanceof SourceTypeBinding )
-	{
-		TypeDeclaration typeDecl = ((SourceTypeBinding)declaringClass).scope.referenceContext;		
-		AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(this);
-					
-		if (methodDecl != null){
-			final int len = methodDecl.annotations == null ? 0 : methodDecl.annotations.length;
-			if( len > 0 ){
-				methodAnno = new IAnnotationInstance[len];
-				for( int i=0; i<len; i++ ){
-					methodAnno[i] = methodDecl.annotations[i].compilerAnnotation;
-				}
-			}			
-		}		
-	}
-	return methodAnno;
-}
-
-/**
- * @param index the index of the parameter of interest
- * @return the annotations on the <code>index</code>th parameter
- * @throws ArrayIndexOutOfBoundsException when <code>index</code> is not valid 
- */
-public IAnnotationInstance[] getParameterAnnotations(final int index)
-{	
-	IAnnotationInstance[] result = NoAnnotations;
-	if(this.declaringClass != null && this.declaringClass instanceof SourceTypeBinding )
-	{
-		TypeDeclaration typeDecl = ((SourceTypeBinding)this.declaringClass).scope.referenceContext;
-		AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(this);
-		if(methodDecl != null ){
-			final Argument[] args = methodDecl.arguments;
-			final int numArgs = args == null ? 0 : args.length;
-			if( numArgs == 0 || index < 0 || index >= numArgs )
-				throw new IllegalArgumentException("number of parameters = " + numArgs + //$NON-NLS-1$ 
-						   						   " index = " + index ); //$NON-NLS-1$	
-			final Argument arg = args[index];
-			final Annotation[] argAnnos = arg.annotations;
-			final int numAnnotations = argAnnos == null ? 0 : argAnnos.length;
-			
-			if( numAnnotations > 0 ){
-				result = new SourceAnnotation[numAnnotations];
-				// check for errors
-				ASTNode.resolveAnnotations(methodDecl.scope, argAnnos, this);
-				for( int j=0; j<numAnnotations; j++ ){
-					result[j] = argAnnos[j].compilerAnnotation;
-				}
-			}	
-		}
-	}
-	
-	return result;
-}
-
-/**
- * @return the default value iff this is an annotation method.
- *         Return <code>null</code> if there is no default value or 
- *         if this is not an annotaion method. 
- */
-public Object getDefaultValue()
-{
-	if(this.declaringClass != null && this.declaringClass instanceof SourceTypeBinding )
-	{
-		TypeDeclaration typeDecl = ((SourceTypeBinding)this.declaringClass).scope.referenceContext;
-		final AbstractMethodDeclaration methodDecl = typeDecl.declarationOf(this);
-		if( methodDecl instanceof AnnotationMethodDeclaration){
-			return SourceElementValuePair.getValue(((AnnotationMethodDeclaration)methodDecl).defaultValue);
-		}
-	}
-	return null;
-}
-
 public TypeVariableBinding getTypeVariable(char[] variableName) {
 	for (int i = this.typeVariables.length; --i >= 0;)
 		if (CharOperation.equals(this.typeVariables[i].sourceName, variableName))
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
index 1114282..715795f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/MethodScope.java
@@ -293,12 +293,10 @@
 			if (declaringClass.isInterface()) // interface or annotation type
 				modifiers |= AccPublic | AccAbstract;		
 			
-			method.binding = new MethodBinding(modifiers, 
-											   method.selector, 
-											   null, 
-											   null, 
-											   null, 
-											   declaringClass);
+			if( declaringClass.isAnnotationType() )
+				method.binding = new AnnotationMethodBinding(modifiers, method.selector, null, declaringClass, null);
+			else
+				method.binding = new MethodBinding(modifiers, method.selector, null, null, null, declaringClass);
 			checkAndSetModifiersForMethod(method.binding);
 		}
 		this.isStatic = method.binding.isStatic();
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
index 734662a..47deacd 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ParameterizedMethodBinding.java
@@ -154,9 +154,4 @@
 	{
 		return original().getParameterAnnotations(index);
 	}
-	
-	public Object getDefaultValue()
-	{
-		return original().getDefaultValue();
-	}
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
index d534a2f..db4f742 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java
@@ -36,6 +36,7 @@
 	char[] fileName;
 	char[] constantPoolName;
 	char[] signature;
+	protected IAnnotationInstance[] annotations;
 
 public FieldBinding[] availableFields() {
 	return fields();
@@ -861,6 +862,6 @@
  */
 public IAnnotationInstance[] getAnnotations()
 {
-	return NoAnnotations;
+	return this.annotations;
 }
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceAnnotation.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceAnnotation.java
index 80398a1..3ccbb33 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceAnnotation.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceAnnotation.java
@@ -2,6 +2,8 @@
 
 import org.eclipse.jdt.internal.compiler.ast.Annotation;
 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
+import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
 
 /**
  * Annotation that came from source.
@@ -9,27 +11,38 @@
  *
  */
 public class SourceAnnotation implements IAnnotationInstance, TypeConstants
-{
-	private final Annotation astAnnotation;
+{	
+	private ReferenceBinding type;
 	private final IElementValuePair[] pairs;
 	
 	public SourceAnnotation(Annotation astAnnotation)
-	{
-		this.astAnnotation = astAnnotation;
-		final MemberValuePair[] astPairs = astAnnotation.memberValuePairs();
-		int numberOfPairs = astPairs == null ? 0 : astPairs.length;
-		if( numberOfPairs == 0 )
-			this.pairs = NoElementValuePairs;
-		else{
-			this.pairs = new SourceElementValuePair[numberOfPairs];
-			for( int i=0; i<numberOfPairs; i++ ){
-				this.pairs[i] = new SourceElementValuePair(astPairs[i]);
+	{	
+		this.type = (ReferenceBinding)astAnnotation.resolvedType;
+		if( astAnnotation instanceof NormalAnnotation ){
+			final MemberValuePair[] astPairs = ((NormalAnnotation)astAnnotation).memberValuePairs;
+			final int numberOfPairs = astPairs == null ? 0 : astPairs.length;			
+			if( numberOfPairs > 0 ){
+				this.pairs = new SourceElementValuePair[numberOfPairs];
+				for( int i=0; i<numberOfPairs; i++ ){
+					this.pairs[i] = new SourceElementValuePair(astPairs[i]);
+				}				
 			}
-		}	
+			else
+				this.pairs = NoElementValuePairs;
+		}
+		else if( astAnnotation instanceof SingleMemberAnnotation ){
+			final MemberValuePair astPair = ((SingleMemberAnnotation)astAnnotation).singlePair;
+			if( astPair != null )
+				this.pairs = new SourceElementValuePair[]{ new SourceElementValuePair(astPair) };
+			else
+				this.pairs = NoElementValuePairs;
+		}
+		else 
+			this.pairs = NoElementValuePairs;
 	}
 	
 	public ReferenceBinding getAnnotationType() {	
-		return (ReferenceBinding)this.astAnnotation.resolvedType;
+		return this.type;
 	}
 	
 	public IElementValuePair[] getElementValuePairs() { return this.pairs; }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceElementValuePair.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceElementValuePair.java
index 3c0e84b..8fab89b 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceElementValuePair.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceElementValuePair.java
@@ -4,37 +4,40 @@
 import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
 import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
 import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
+import org.eclipse.jdt.internal.compiler.ast.NameReference;
+import org.eclipse.jdt.internal.compiler.ast.Reference;
+import org.eclipse.jdt.internal.compiler.env.IConstants;
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 
 public class SourceElementValuePair implements IElementValuePair 
-{
-	private final MemberValuePair astPair;
-	private Object value = null;
+{	
+	private final char[] name;	
+	private final MethodBinding binding;
+	private final Object value;
 	
 	SourceElementValuePair(final MemberValuePair pair)
 	{
-		this.astPair = pair;
+		this.name = pair.name;
+		this.binding = pair.binding;
+		this.value = getValue(pair.value);		
 	}
 	
 	public char[] getMemberName()
-	{ return this.astPair.name; }
+	{ return this.name; }
 	
 	public MethodBinding getMethodBinding() {
-		return this.astPair.binding;
+		return this.binding;
 	}
 	
 	public TypeBinding getType() {
-		if(this.astPair.binding == null) return null;
-		return this.astPair.binding.returnType;
+		if(this.binding == null) return null;
+		return this.binding.returnType;
 	}
 	
 	public Object getValue() {
-		if( this.value != null ) return this.value;
-		
-		final Expression expression = this.astPair.value;
-		this.value = getValue(expression);
-		return this.value;
+		return this.value;	
 	}
 	
 	static Object getValue(Expression expression)
@@ -42,10 +45,24 @@
 		if( expression == null ) return null;
 		Constant constant = expression.constant;
 		// literals would hit this case.
-		if( constant != null ) return constant;
+		if( constant != null && constant != Constant.NotAConstant) return constant;
 			
 		if( expression instanceof Annotation )
-			return new SourceAnnotation( (Annotation)expression );            
+			return new SourceAnnotation( (Annotation)expression );      
+		else if(expression instanceof Reference){
+            FieldBinding fieldBinding = null;
+            if(expression instanceof FieldReference )
+                fieldBinding = ((FieldReference)expression).fieldBinding();
+            else if(expression instanceof NameReference ){
+                final Binding binding = ((NameReference)expression).binding;
+                if( binding != null && binding.kind() == Binding.FIELD )
+                    fieldBinding = (FieldBinding)binding;
+            }
+
+            if( fieldBinding != null && (fieldBinding.modifiers & IConstants.AccEnum) > 0 ){
+				return fieldBinding;
+            }
+        }
 
         else if( expression instanceof ArrayInitializer )
         {
@@ -61,8 +78,7 @@
             final ClassLiteralAccess classLiteral = (ClassLiteralAccess)expression;
 			return classLiteral.targetType;            
         }        
-        // something that isn't a compile time constant.
-        else
-            return null;
+        // something that isn't a compile time constant.        
+        return null;
 	}
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
index 018dc2b..0992443 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java
@@ -634,19 +634,25 @@
 	return this.tagBits;
 }
 
-public IAnnotationInstance[] getAnnotations() {
-	// make sure we first go resolve the annoations and report any problems found.
-	getAnnotationTagBits();
+public IAnnotationInstance[] getAnnotations()
+{
+	if( this.annotations == null )
+		buildAnnotations();
+	return this.annotations;
+}
+
+private void buildAnnotations()
+{
+	if( this.annotations != null ) return;
+	this.annotations = NoAnnotations;
 	final TypeDeclaration typeDecl = this.scope.referenceContext;
 	final int numAnnotations = typeDecl.annotations == null ? 0 : typeDecl.annotations.length;
-	if( numAnnotations == 0 )
-		return NoAnnotations;
-	else{
-		final IAnnotationInstance[] instances = new IAnnotationInstance[numAnnotations];
-		for( int i=0; i<numAnnotations; i++ ){
-			instances[i] = new SourceAnnotation(typeDecl.annotations[i]);
+	if( numAnnotations > 0 ){
+		this.annotations = new IAnnotationInstance[numAnnotations];
+		for( int i=0; i<numAnnotations; i++ ){		
+			typeDecl.annotations[i].resolveType(typeDecl.staticInitializerScope);			
+			this.annotations[i] = typeDecl.annotations[i].getCompilerAnnotation();			
 		}
-		return instances;
 	}
 }
 
@@ -910,12 +916,8 @@
 		this.synthetics[RECEIVER_TYPE_EMUL].put(targetField, fieldMap);
 	}
 	FieldBinding updatedField = (FieldBinding) fieldMap.get(newDeclaringClass);
-	if (updatedField == null){
-		if( targetField instanceof BinaryFieldBinding )
-			updatedField = new BinaryFieldBinding((BinaryFieldBinding)targetField, newDeclaringClass);
-		else
-			updatedField = new FieldBinding(targetField, newDeclaringClass);
-			
+	if (updatedField == null){		
+		updatedField = new FieldBinding( targetField, newDeclaringClass);
 		fieldMap.put(newDeclaringClass, updatedField);
 	}
 	return updatedField;
@@ -933,11 +935,7 @@
 	}
 	MethodBinding updatedMethod = (MethodBinding) methodMap.get(newDeclaringClass);
 	if (updatedMethod == null){
-		if( targetMethod instanceof BinaryMethodBinding )
-			updatedMethod = new BinaryMethodBinding((BinaryMethodBinding)targetMethod, newDeclaringClass);
-		else
-			updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);	
-			
+		updatedMethod = new MethodBinding(targetMethod, newDeclaringClass);	
 		methodMap.put(newDeclaringClass, updatedMethod);
 	}
 	return updatedMethod;
@@ -1385,4 +1383,19 @@
 	for (int i = memberTypes.length; --i >= 0;)
 		 ((SourceTypeBinding) memberTypes[i]).verifyMethods(verifier);
 }
+/*
+ * Called when the ast information is about to be null-ed out.
+ */
+public void finish()
+{
+	buildAnnotations();
+	if(this.methods != null){
+		for( int i=0, len=this.methods.length; i<len; i++ )
+			this.methods[i].buildAnnotations();
+	}
+	if(this.fields != null){
+		for( int i=0, len=this.fields.length; i<len; i++)
+			this.fields[i].buildAnnotations();
+	}
+}
 }
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
index 6ba984f..5f3c9cd 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/TypeConstants.java
@@ -33,6 +33,15 @@
 	char[] CharArray_JAVA_IO_OBJECTINPUTSTREAM = "java.io.ObjectInputStream".toCharArray(); //$NON-NLS-1$
 	char[] CharArray_JAVA_IO_OBJECTOUTPUTSTREAM = "java.io.ObjectOutputStream".toCharArray(); //$NON-NLS-1$
 	char[] CharArray_JAVA_IO_OBJECTSTREAMFIELD = "java.io.ObjectStreamField".toCharArray(); //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_DEPRECATED_SIG = "Ljava/lang/Deprecated;".toCharArray();  //$NON-NLS-1$	
+	char[] CharArray_JAVA_LANG_OVERRIDE_SIG = "Ljava/lang/Override;".toCharArray();  //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_SUPRESSWARNING_SIG = "Ljava/lang/SupressWarning;".toCharArray();  //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_ANNOTATION_DOCUMENTED_SIG = "Ljava/lang/annotation/Documented;".toCharArray();  //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_ANNOTATION_INHERITED_SIG = "Ljava/lang/annotation/Inherited;".toCharArray();  //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_ANNOTATION_RETENTION_SIG = "Ljava/lang/annotation/Retention;".toCharArray();  //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_ANNOTATION_TARGET_SIG = "Ljava/lang/annotation/Target;".toCharArray();  //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_ANNOTATION_RETENTIONPOLICY_SIG = "Ljava/lang/annotation/RetentionPolicy;".toCharArray();  //$NON-NLS-1$
+	char[] CharArray_JAVA_LANG_ANNOTATION_ELEMENTTYPE_SIG = "Ljava/lang/annotation/ElementType;".toCharArray();  //$NON-NLS-1$
 	char[] ANONYM_PREFIX = "new ".toCharArray(); //$NON-NLS-1$
 	char[] ANONYM_SUFFIX = "(){}".toCharArray(); //$NON-NLS-1$
     char[] WILDCARD_NAME = { '?' };
diff --git a/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java b/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
index 6efe750..dbcc32f 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/lookup/VariableBinding.java
@@ -12,7 +12,7 @@
 
 import org.eclipse.jdt.internal.compiler.impl.Constant;
 
-public abstract class VariableBinding extends Binding {
+public abstract class VariableBinding extends Binding implements TypeConstants {
     
 	public int modifiers;
 	public TypeBinding type;
@@ -20,6 +20,7 @@
 	private Constant constant;
 	public int id; // for flow-analysis (position in flowInfo bit vector)
 	public long tagBits;
+	protected IAnnotationInstance[] annotations;
 
 	public VariableBinding(char[] name, TypeBinding type, int modifiers, Constant constant) {
 		this.name = name;
@@ -55,7 +56,10 @@
 	 * @return the annotations iff this is a field, enum constant or parameter.
 	 * Return null otherwise.
 	 */
-	public abstract IAnnotationInstance[] getAnnotations();
+	public IAnnotationInstance[] getAnnotations()
+	{		
+		return this.annotations; 
+	}
 	
 	public String toString() {
 		String s = (type != null) ? type.debugName() : "UNDEFINED TYPE"; //$NON-NLS-1$
diff --git a/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java b/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
index 984bf04..52aba01 100644
--- a/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
+++ b/dom/org/eclipse/jdt/core/dom/DefaultBindingResolver.java
@@ -269,7 +269,7 @@
 		if (binding != null) {
 			return binding;
 		}
-		binding = new PackageBinding(packageBinding);
+		binding = new PackageBinding(packageBinding, this);
 		this.bindingTables.compilerBindingsToASTBindings.put(packageBinding, binding);
 		return binding;
 	}
@@ -362,6 +362,7 @@
 	}
 	
 	synchronized IResolvedAnnotation getAnnotationInstance(org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance internalInstance){
+		if( internalInstance == null ) return null;
 		IResolvedAnnotation domInstance = 
 			(IResolvedAnnotation) this.bindingTables.compilerBindingsToASTBindings.get(internalInstance);
 		if (domInstance != null) {
@@ -1426,7 +1427,7 @@
 			org.eclipse.jdt.internal.compiler.ast.Annotation internalAstNode = 
 				(org.eclipse.jdt.internal.compiler.ast.Annotation) oldNode;
 			
-			IResolvedAnnotation domAnnotation = this.getAnnotationInstance(internalAstNode.compilerAnnotation);
+			IResolvedAnnotation domAnnotation = this.getAnnotationInstance(internalAstNode.getCompilerAnnotation());
 			if (domAnnotation == null) {
 				return null;
 			}
diff --git a/dom/org/eclipse/jdt/core/dom/MethodBinding.java b/dom/org/eclipse/jdt/core/dom/MethodBinding.java
index 2c4009e..dadc4a6 100644
--- a/dom/org/eclipse/jdt/core/dom/MethodBinding.java
+++ b/dom/org/eclipse/jdt/core/dom/MethodBinding.java
@@ -422,7 +422,7 @@
 		if( isAnnotationMember() ){
 			final Object internalObject = 
 				((org.eclipse.jdt.internal.compiler.lookup.AnnotationMethodBinding)this.binding).getDefaultValue();
-			return ResolvedMemberValuePair.buildDOMValue(internalObject, this.binding.returnType, this.resolver);
+			return ResolvedMemberValuePair.buildDOMValue(internalObject, this.resolver);
 		}
 		return null;
 	}
diff --git a/dom/org/eclipse/jdt/core/dom/PackageBinding.java b/dom/org/eclipse/jdt/core/dom/PackageBinding.java
index 0bba13a..eb5bea3 100644
--- a/dom/org/eclipse/jdt/core/dom/PackageBinding.java
+++ b/dom/org/eclipse/jdt/core/dom/PackageBinding.java
@@ -30,7 +30,7 @@
 	private String name;
 	private String[] components;
 		
-	PackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding) {
+	PackageBinding(org.eclipse.jdt.internal.compiler.lookup.PackageBinding binding, BindingResolver resolver) {
 		this.binding = binding;
 	}
 	
@@ -149,8 +149,7 @@
 	}
 	
 	public IResolvedAnnotation[] getAnnotations() {
-		// TODO Auto-generated method stub
-		throw new RuntimeException("Not implemented yet"); //$NON-NLS-1$
+		throw new UnsupportedOperationException("NYI"); //$NON-NLS-1$
 	}
 
 	/* 
diff --git a/dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java b/dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java
index 7b6b991..ced5457 100644
--- a/dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java
+++ b/dom/org/eclipse/jdt/core/dom/ResolvedAnnotation.java
@@ -10,6 +10,13 @@
  *******************************************************************************/
 package org.eclipse.jdt.core.dom;
 
+import java.util.Arrays;
+import java.util.Comparator;
+
+import org.eclipse.jdt.core.compiler.CharOperation;
+import org.eclipse.jdt.internal.compiler.lookup.AnnotationMethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+
 /**
  * Internal class
  */
@@ -19,10 +26,16 @@
 	private final org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance internalAnnotation;
 	private final BindingResolver bindingResolver;
 	
+	/**	 
+	 * @param anno
+	 * @param resolver
+	 */
 	ResolvedAnnotation(org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance anno, 
 	  				   BindingResolver resolver )
 	{
 		internalAnnotation = anno;
+		if( internalAnnotation == null )
+			throw new IllegalStateException();
 		bindingResolver = resolver;
 	}
 	
@@ -35,17 +48,76 @@
 	public IResolvedMemberValuePair[] getDeclaredMemberValuePairs() {
 		final org.eclipse.jdt.internal.compiler.lookup.IElementValuePair[] internalPair =
 			this.internalAnnotation.getElementValuePairs();
-		final int len = internalPair.length;
+		final int len = internalPair.length;		
 		IResolvedMemberValuePair[] pairs = ResolvedMemberValuePair.NoPair;
-		for( int i=0; i<len; i++ ){
-			pairs[i] = new ResolvedMemberValuePair(internalPair[i],this.bindingResolver);
+		if( len > 0 )
+		{
+			pairs = new ResolvedMemberValuePair[len];
+			for( int i=0; i<len; i++ ){
+				pairs[i] = new ResolvedMemberValuePair(internalPair[i],this.bindingResolver);
+			}
 		}
 		return pairs;
 	}
 	
 	public IResolvedMemberValuePair[] getAllMemberValuePairs() {
-		// TODO missing implementation
-		throw new RuntimeException("Not implemented yet"); //$NON-NLS-1$
+		final ReferenceBinding typeBinding = this.internalAnnotation.getAnnotationType();
+		IResolvedMemberValuePair[] pairs = ResolvedMemberValuePair.NoPair;
+		final org.eclipse.jdt.internal.compiler.lookup.MethodBinding[] methods = typeBinding.methods();
+		final int len = methods == null ? 0 : methods.length;
+		if(typeBinding != null && len > 0 ){
+			final org.eclipse.jdt.internal.compiler.lookup.IElementValuePair[] internalPair = 
+				this.internalAnnotation.getElementValuePairs();
+			final int declaredLen = internalPair == null ? 0 : internalPair.length;
+			final Object[] names = declaredLen < len ? new Object[declaredLen] : null;
+			for( int i=0; i<declaredLen; i++ ){
+				pairs[i] = new ResolvedMemberValuePair(internalPair[i], this.bindingResolver);
+				names[i] = internalPair[i].getMemberName();
+			}
+			if( declaredLen < len ){
+				final MemberComparator comparator = new MemberComparator();
+				Arrays.sort(names, comparator);
+				int pIndex = declaredLen;
+				for( int i=0; i<len; i++, pIndex++ ){
+					final char[] selector = methods[i].selector;
+					final int index = Arrays.binarySearch(names, selector, comparator);
+					if( index < 0 )
+						pairs[pIndex] = new ResolvedDefaultValuePair((AnnotationMethodBinding)methods[i], this.bindingResolver);
+				}				
+			}			
+		}
+		return pairs;
 	}
 	
+	public String toString()
+	{
+		final ITypeBinding annoType = getAnnotationType();	
+	    
+		final StringBuffer buffer = new StringBuffer();		
+		buffer.append('@');
+		if(annoType != null)
+			buffer.append(annoType.getName());
+		buffer.append('(');
+		final IResolvedMemberValuePair[] pairs = getDeclaredMemberValuePairs();		
+		for( int i = 0, len = pairs.length; i<len; i++ ){
+			if( i != 0 )
+				buffer.append(", "); //$NON-NLS-1$
+			buffer.append(pairs[i].toString());
+		}
+		buffer.append(')');
+		return buffer.toString();
+		
+	}
+	
+	private static class MemberComparator implements Comparator
+	{
+		public int compare(Object arg0, Object arg1) 
+		{
+			// throws ClassCastException if either one of the arguments is not 
+			// a char[]
+			final char[] c0 = (char[])arg0;
+			final char[] c1 = (char[])arg1;
+			return CharOperation.compareWith(c0, c1);
+		}
+	}
 }
diff --git a/dom/org/eclipse/jdt/core/dom/ResolvedDefaultValuePair.java b/dom/org/eclipse/jdt/core/dom/ResolvedDefaultValuePair.java
new file mode 100644
index 0000000..b7da76e
--- /dev/null
+++ b/dom/org/eclipse/jdt/core/dom/ResolvedDefaultValuePair.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2005 BEA Systems, Inc.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    tyeung@bea.com - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.jdt.core.dom;
+
+import org.eclipse.jdt.core.dom.BindingResolver;
+import org.eclipse.jdt.core.dom.IMethodBinding;
+import org.eclipse.jdt.core.dom.IResolvedMemberValuePair;
+
+/**
+ * Member value pair which compose of default values.
+ */
+class ResolvedDefaultValuePair implements IResolvedMemberValuePair
+{	
+	private final org.eclipse.jdt.internal.compiler.lookup.MethodBinding method;
+	private final Object domValue;
+	private final BindingResolver bindingResolver;
+	
+	ResolvedDefaultValuePair(org.eclipse.jdt.internal.compiler.lookup.AnnotationMethodBinding binding, final BindingResolver resolver )
+	{	
+		this.method = binding;
+		this.domValue = ResolvedMemberValuePair.buildDOMValue(binding.getDefaultValue(), resolver);
+		this.bindingResolver = resolver;
+	}
+	public String getName() {
+		return new String( this.method.selector ); 
+	}
+	
+	public IMethodBinding getMemberBinding() {
+		return this.bindingResolver.getMethodBinding(this.method);
+	}
+	
+	public Object getValue() {
+		return this.domValue;
+	}	
+	
+	public void toString(StringBuffer buffer) {
+		buffer.append(getName());
+		buffer.append(" = "); //$NON-NLS-1$		
+		appendValue(getValue(), buffer);		
+	}
+	
+	static void appendValue(Object value, StringBuffer buffer) {
+		if( value instanceof Object[] ){
+			appendValue((Object[])value, buffer);
+		}
+		else{
+			if(value instanceof ITypeBinding ){
+				buffer.append( ((ITypeBinding)value).getName() );
+				buffer.append( ".class" ); //$NON-NLS-1$
+			}
+			else
+				buffer.append(value);
+		}
+	}
+	
+	private static void appendValue(Object[] values, StringBuffer buffer) {		
+		buffer.append('{');
+		for( int i=0, len=values.length; i<len; i++ ){
+			if( i != 0 )
+				buffer.append(", "); //$NON-NLS-1$
+			appendValue(values[i], buffer);
+			
+		}				
+		buffer.append('}');
+	}
+	
+	public String toString() {
+		final StringBuffer buffer = new StringBuffer();
+		toString(buffer);
+		return buffer.toString();
+	}
+}
diff --git a/dom/org/eclipse/jdt/core/dom/ResolvedMemberValuePair.java b/dom/org/eclipse/jdt/core/dom/ResolvedMemberValuePair.java
index 5959802..2c4b8b7 100644
--- a/dom/org/eclipse/jdt/core/dom/ResolvedMemberValuePair.java
+++ b/dom/org/eclipse/jdt/core/dom/ResolvedMemberValuePair.java
@@ -18,78 +18,79 @@
  */
 class ResolvedMemberValuePair implements IResolvedMemberValuePair
 {	
-	static final ResolvedMemberValuePair[] NoPair = new ResolvedMemberValuePair[0]; 
+	static final ResolvedMemberValuePair[] NoPair = new ResolvedMemberValuePair[0]; 	
 	private static final Object NoValue = new Object();
+	private static final Object[] EmptyArray = new Object[0];
+	
 	private final org.eclipse.jdt.internal.compiler.lookup.IElementValuePair internalPair;
 	private Object value = null; 
 	private final BindingResolver bindingResolver;
 	
 	ResolvedMemberValuePair(final org.eclipse.jdt.internal.compiler.lookup.IElementValuePair pair, 
-					 BindingResolver resolver)
-	{	
+					 		BindingResolver resolver) {	
 		this.internalPair = pair;
 		this.bindingResolver = resolver;		
 	}
 	
-	private void init()
-	{
-		final org.eclipse.jdt.internal.compiler.lookup.TypeBinding type = this.internalPair.getType();
-		this.value =  buildDOMValue(this.internalPair.getValue(), type, this.bindingResolver);
+	private void init() {		
+		this.value =  buildDOMValue(this.internalPair.getValue(), this.bindingResolver);
 		if( this.value == null )
 			this.value = NoValue;
 	}
 	
 	static Object buildDOMValue(final Object internalObject, 
-			  				    org.eclipse.jdt.internal.compiler.lookup.TypeBinding type,
-			  				    BindingResolver resolver)
-	{
-		if( internalObject == null || type == null ) return null;
-		switch(type.id)
-		{
-		case TypeIds.T_boolean:
-			return new Boolean( ((Constant)internalObject).booleanValue() );			
-		case TypeIds.T_byte:
-			return new Byte( ((Constant)internalObject).byteValue() );			
-		case TypeIds.T_char:
-			return new Character( ((Constant)internalObject).charValue() );
-		case TypeIds.T_double:
-			return new Double( ((Constant)internalObject).doubleValue() );			
-		case TypeIds.T_float:
-			return new Float( ((Constant)internalObject).floatValue() );
-		case TypeIds.T_int:
-			return new Integer( ((Constant)internalObject).intValue() );			
-		case TypeIds.T_long:
-			return new Long( ((Constant)internalObject).longValue() );			
-		case TypeIds.T_short:
-			return new Short( ((Constant)internalObject).shortValue() );
-		case TypeIds.T_JavaLangString:
-			return internalObject;
-		case TypeIds.T_JavaLangClass:
-			return resolver.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)internalObject);
-		}	
+			  				    BindingResolver resolver) {
+		if( internalObject == null ) return null;
 		
-		if( type.isAnnotationType() ){
+		if( internalObject instanceof Constant )
+		{
+			final Constant constant = (Constant)internalObject;
+			switch( constant.typeID() )
+			{
+			case TypeIds.T_boolean:
+				return new Boolean( constant.booleanValue() );			
+			case TypeIds.T_byte:
+				return new Byte( constant.byteValue() );			
+			case TypeIds.T_char:
+				return new Character( constant.charValue() );
+			case TypeIds.T_double:
+				return new Double( constant.doubleValue() );			
+			case TypeIds.T_float:
+				return new Float( constant.floatValue() );
+			case TypeIds.T_int:
+				return new Integer( constant.intValue() );			
+			case TypeIds.T_long:
+				return new Long( constant.longValue() );			
+			case TypeIds.T_short:
+				return new Short( constant.shortValue() );
+			case TypeIds.T_JavaLangString:
+				return constant.stringValue();
+			}
+		}
+		else if( internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.TypeBinding){
+			return resolver.getTypeBinding((org.eclipse.jdt.internal.compiler.lookup.TypeBinding)internalObject);
+		}
+		if( internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance ) {
 			return new ResolvedAnnotation(
 					(org.eclipse.jdt.internal.compiler.lookup.IAnnotationInstance)internalObject, 
 					resolver);
 		}
-		else if( type.isEnum() ){
+		else if( internalObject instanceof org.eclipse.jdt.internal.compiler.lookup.FieldBinding ) {
 			return resolver.getVariableBinding((org.eclipse.jdt.internal.compiler.lookup.FieldBinding)internalObject);
 		}
-		else if( type.isArrayType() ){
+		else if( internalObject instanceof Object[] ) {
 			final Object[] iElements = (Object[])internalObject;
 			final int len = iElements.length;
-			Object[] values = null;
-			if( len > 0){
-				final org.eclipse.jdt.internal.compiler.lookup.TypeBinding elementType =
-					((org.eclipse.jdt.internal.compiler.lookup.ArrayBinding)type).leafComponentType;
+			Object[] values = EmptyArray;
+			if( len > 0){			
 				values = new Object[len];
 				for( int i=0; i<len; i++ ){
-					values[i] = buildDOMValue(iElements[i], elementType, resolver);
+					values[i] = buildDOMValue(iElements[i], resolver);
 				}
 			}
-		}
-		throw new IllegalStateException(); // should never get here.		
+			return values;
+		}		
+		throw new IllegalStateException(internalObject.toString()); // should never get here.		
 	}
 	
 	public String getName() {
@@ -106,4 +107,17 @@
 			init();
 		return value == NoValue ? null : this.value;
 	}	
+	
+	public void toString(StringBuffer buffer) {
+		buffer.append(getName());
+		buffer.append(" = "); //$NON-NLS-1$		
+		ResolvedDefaultValuePair.appendValue(getValue(), buffer);		
+	}
+	
+	public String toString() {
+		final StringBuffer buffer = new StringBuffer();
+		toString(buffer);
+		return buffer.toString();
+	}
 }
+
diff --git a/model/org/eclipse/jdt/core/JavaCore.java b/model/org/eclipse/jdt/core/JavaCore.java
index 4f32ee9..0dd1e6c 100644
--- a/model/org/eclipse/jdt/core/JavaCore.java
+++ b/model/org/eclipse/jdt/core/JavaCore.java
@@ -1019,6 +1019,7 @@
 	 * Add a compilation participant listener dynamically.  It is not necessary
 	 * to call this for listeners registered with the compilationParticipants
 	 * extension point.
+	 * 
 	 * @param icp the listener
 	 * @param eventMask the set of events for which the listener will be notified,
 	 * built by ORing together values from CompilationParticipantEvent.
@@ -1534,15 +1535,20 @@
 	 * listeners that have requested notification of at least one of
 	 * the events in the flags mask.
 	 * The first time this is called, it loads listeners from plugins,
-	 * which may cause plugins to be loaded.  If this is called on
-	 * multiple threads simultaneously, or if loading a plugin causes
-	 * this to be reentered, it may return an incomplete list of listeners,
-	 * but it is guaranteed not to crash or deadlock.
+	 * which may cause plugins to be loaded.  
+	 * 
+	 * <p>
+	 * Note that a deadlock situation can occur if a plugin's <code>start()</code> 
+	 * method blocks on a thread that calls <code>getCompilationParticipants()</code>.  
+	 * See <code>JavaModelManager.CompilationParticipants.getCompilationParticipants()</code>
+	 * for a complete description of the circumstances under which this deadlock can occur.
+	 * 
 	 * @param eventMask an ORed combination of values from ICompilationParticipant.
 	 * @return an immutable list of ICompilationParticipant.
+	 * @see JavaModelManager.CompilationParticipants#getCompilationParticipants
 	 */
 	public static List getCompilationParticipants(int eventMask) {
-		return JavaModelManager.getJavaModelManager().getCompilationParticipants().get(eventMask);
+		return JavaModelManager.getJavaModelManager().getCompilationParticipants().getCompilationParticipants(eventMask);
 	}
 	
 	/**
diff --git a/model/org/eclipse/jdt/internal/core/CompilationUnit.java b/model/org/eclipse/jdt/internal/core/CompilationUnit.java
index d0a6af5..b7136bb 100644
--- a/model/org/eclipse/jdt/internal/core/CompilationUnit.java
+++ b/model/org/eclipse/jdt/internal/core/CompilationUnit.java
@@ -16,9 +16,7 @@
 import org.eclipse.core.runtime.*;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.core.compiler.ICompilationParticipant;
 import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.compiler.PostReconcileCompilationEvent;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.IProblemFactory;
@@ -27,10 +25,8 @@
 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
 import org.eclipse.jdt.internal.compiler.problem.DefaultProblemFactory;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
-import org.eclipse.jdt.internal.core.JavaModelManager.PerWorkingCopyInfo;
 import org.eclipse.jdt.internal.core.util.MementoTokenizer;
 import org.eclipse.jdt.internal.core.util.Util;
-
 /**
  * @see ICompilationUnit
  */
@@ -44,19 +40,7 @@
 	
 	protected String name;
 	public WorkingCopyOwner owner;
-	
-	/** 
-	 * indicates if a NoOpProblemRequestor should be used when 
-	 *  calling getPerWorkingCopyInfo
-	 */
-	private boolean useNoOpProblemRequestor = false;
 
-	/**
-	 * indicates if we should treat this working copy as inconsistent
-	 * even if there wasn't a change in the underlying buffer.
-	 */
-	private boolean forceInconsistent = false;
-	
 	
 /**
  * Constructs a handle to a compilation unit with the given name in the
@@ -773,12 +757,8 @@
  * Returns the per working copy info for the receiver, or null if none exist.
  * Note: the use count of the per working copy info is NOT incremented.
  */
-public JavaModelManager.PerWorkingCopyInfo getPerWorkingCopyInfo() {
-	
-	if ( useNoOpProblemRequestor )
-		return new PerWorkingCopyInfo( this, NO_OP_PROBLEM_REQUESTOR );
-	else
-		return JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(this, false/*don't create*/, false/*don't record usage*/, null/*no problem requestor needed*/);
+public JavaModelManager.PerWorkingCopyInfo getPerWorkingCopyInfo() {	
+	return JavaModelManager.getJavaModelManager().getPerWorkingCopyInfo(this, false/*don't create*/, false/*don't record usage*/, null/*no problem requestor needed*/);
 }
 
 /*
@@ -921,10 +901,7 @@
  * @see IOpenable#isConsistent()
  */
 public boolean isConsistent() {
-	if ( forceInconsistent )
-		return false;
-	else	
-		return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null;
+	return JavaModelManager.getJavaModelManager().getElementsOutOfSynchWithBuffers().get(this) == null;
 }
 /**
  * 
@@ -1111,54 +1088,8 @@
 	
 	
 	ReconcileWorkingCopyOperation op = null;
-	List l = JavaCore.getCompilationParticipants(ICompilationParticipant.POST_RECONCILE_EVENT);	
-	if ( l != null && l.size() > 0 ) {	
-		// we always need an AST to pass into compilation participants
-		op = new ReconcileWorkingCopyOperation(this, true /*createAST*/, AST.JLS3, forceProblemDetection, workingCopyOwner);	
-
-		// TODO:  try not to use these two try-catch blocks here...
-		try {
-		    try {
-				useNoOpProblemRequestor = true;
-				forceInconsistent = ! this.isConsistent();
-				op.runOperation(monitor);
-			}
-			finally {
-				useNoOpProblemRequestor = false;
-			}
-						
-			Iterator it = l.iterator();
-			while ( it.hasNext() ) {
-				ICompilationParticipant p = (ICompilationParticipant)it.next();
-				PostReconcileCompilationEvent prce = new PostReconcileCompilationEvent( this, op.ast, getJavaProject() ); 
-				p.notify( prce );
-				// TODO: do something with the result of notify...
-			}
-
-			// save off the original AST
-			org.eclipse.jdt.core.dom.CompilationUnit originalAst = op.ast;
-
-			// if there were ICompilationParticipants, we will reconcile again and return the ast from the second reconcile
-			// this causes the client to receive an AST that is correct with respect to any changes that occurred in the 
-			// ast as a result of files being added by compilation participants.  This second reconcile also causes any 
-			// problems to be reported to the correct problemRequestor, instead of the no-op problemRequestor. 
-			op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner);
-			op.runOperation(monitor);
-			
-			// if the original AST was null, assume that the working copy was consistent.
-			// and return null. 
-			if ( originalAst == null )
-				return null;	
-		}
-		finally {
-			forceInconsistent = false;
-		}
-	}
-	else 
-	{
-		op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner);
-		op.runOperation(monitor);
-	}
+	op = new ReconcileWorkingCopyOperation(this, createAST, astLevel, forceProblemDetection, workingCopyOwner);
+	op.runOperation(monitor);
 
 	return op.ast;
 }
@@ -1236,14 +1167,4 @@
 	((CompilationUnitElementInfo) getElementInfo()).timestamp = timeStamp;
 }
 
-
-
-private final static NoOpProblemRequestor  NO_OP_PROBLEM_REQUESTOR = new NoOpProblemRequestor();
-private final static class NoOpProblemRequestor implements IProblemRequestor {
-	public void    acceptProblem(IProblem problem) { /* no-op */ }
-	public void    beginReporting()                { /* no-op */ }
-	public void    endReporting()                  { /* no-op */ }
-	public boolean isActive()                      { return true; } 
-}
-
 }
diff --git a/model/org/eclipse/jdt/internal/core/JavaModelManager.java b/model/org/eclipse/jdt/internal/core/JavaModelManager.java
index e76004e..26fd646 100644
--- a/model/org/eclipse/jdt/internal/core/JavaModelManager.java
+++ b/model/org/eclipse/jdt/internal/core/JavaModelManager.java
@@ -174,14 +174,24 @@
 		 * listeners that have requested notification of at least one of
 		 * the events in the flags mask.
 		 * The first time this is called, it loads listeners from plugins,
-		 * which may cause plugins to be loaded.  If this is called on
-		 * multiple threads simultaneously, or if loading a plugin causes
-		 * this to be reentered, it may return an incomplete list of listeners,
-		 * but it is guaranteed not to crash or deadlock.
+		 * which may cause plugins to be loaded.  
+		 * 
+		 * <p>
+		 * The initialization of ICompilationParticipants  is synchronized.  A deadlock may 
+		 * occur if all of the following conditions are true:  
+		 *  
+		 *  <li>A plugin defines <code>ICompilationParticipants</code></li>
+		 *  <li>That plugin's <code>start()</code> method spawns a thread which causes 
+		 *  <code>getCompilationParticipants()</code> to be invoked</li>
+		 *  <li>The <code>start()</code> method blocks waiting for the spawned thread to complete.</li> 
+		 *  
+		 *  Note that a build and reconcile operations will cause <code>getCompilationParticipants()</code> to 
+		 *  be called.
+		 *  
 		 * @param eventMask an ORed combination of values from ICompilationParticipant.
 		 * @return an immutable list of ICompilationParticipant.
 		 */
-		public List get(int eventMask) {
+		public List getCompilationParticipants(int eventMask) {
 			initPlugins();
 			List filteredICPs = new ArrayList();
 			Iterator it;
@@ -204,16 +214,15 @@
 			return Collections.unmodifiableList(filteredICPs);
 		}
 		
-		private void initPlugins() {
-			synchronized (this) {
-				if (null != pluginCPs) {
-					return;
-				}
-				pluginCPs = new HashMap();
+		private synchronized void initPlugins() {
+			if (null != pluginCPs) {
+				return;
 			}
+			pluginCPs = new HashMap();
+
 			IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(
 					JavaCore.PLUGIN_ID, COMPILATION_PARTICIPANT_EXTPOINT_ID);
-			if (extension == null)
+			if (extension == null) 
 				return;
 			IExtension[] extensions = extension.getExtensions();
 			for(int iExtension = 0; iExtension < extensions.length; iExtension++){
diff --git a/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java b/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
index 3cec2ff..75a069d 100644
--- a/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
+++ b/model/org/eclipse/jdt/internal/core/ReconcileWorkingCopyOperation.java
@@ -10,22 +10,25 @@
  *******************************************************************************/
 package org.eclipse.jdt.internal.core;
 
+import java.util.Iterator;
+import java.util.List;
 import java.util.Map;
 
 import org.eclipse.core.runtime.OperationCanceledException;
 import org.eclipse.jdt.core.*;
 import org.eclipse.jdt.core.IJavaElement;
 import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.ICompilationParticipant;
+import org.eclipse.jdt.core.compiler.PostReconcileCompilationEvent;
 import org.eclipse.jdt.core.dom.AST;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
-import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.jdt.internal.core.util.Util;
 
 /**
  * Reconcile a working copy and signal the changes through a delta.
  */
 public class ReconcileWorkingCopyOperation extends JavaModelOperation {
-	public static boolean PERF = false;
-	
+		
 	boolean createAST;
 	int astLevel;
 	boolean forceProblemDetection;
@@ -47,9 +50,11 @@
 		if (this.progressMonitor != null){
 			if (this.progressMonitor.isCanceled()) 
 				throw new OperationCanceledException();
-			this.progressMonitor.beginTask(Messages.element_reconciling, 2); 
+			this.progressMonitor.beginTask(Util.bind("element.reconciling"), 2); //$NON-NLS-1$
 		}
 	
+		notifyCompilationParticipants();
+		
 		CompilationUnit workingCopy = getWorkingCopy();
 		boolean wasConsistent = workingCopy.isConsistent();
 		try {
@@ -120,5 +125,22 @@
 		return status;
 	}
 
+	private void notifyCompilationParticipants() {
+		
+		List l = JavaCore.getCompilationParticipants(ICompilationParticipant.POST_RECONCILE_EVENT);	
 
+		CompilationUnit workingCopy = getWorkingCopy();
+		
+		// we want to go through ICompilationParticipant only if there are participants
+		// and the compilation unit is not consistent or we are forcing problem detection
+		if ( ( l != null && l.size() > 0 ) && ( !workingCopy.isConsistent() || forceProblemDetection )) {	
+			PostReconcileCompilationEvent prce = new PostReconcileCompilationEvent( workingCopy, workingCopy.getJavaProject() );
+			Iterator it = l.iterator();
+			while ( it.hasNext() ) {
+				ICompilationParticipant p = (ICompilationParticipant)it.next(); 
+				p.notify( prce );
+				// TODO: do something with the result of notify...
+			}
+		}
+	}
 }
diff --git a/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
index d2ff2cb..d941f25 100644
--- a/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/AbstractImageBuilder.java
@@ -226,15 +226,13 @@
 /**
  *  notify the ICompilationParticipants of the pre-build event 
  */
-private Set notifyCompilationParticipants(ICompilationUnit[] sourceUnits) {
+private  void notifyCompilationParticipants(ICompilationUnit[] sourceUnits, Set newFiles, Set deletedFiles, Map extraDependencies ) {
 	List cps = JavaCore
 			.getCompilationParticipants( ICompilationParticipant.PRE_BUILD_EVENT );
 	if ( cps.isEmpty() ) {
-		return Collections.EMPTY_SET;
+		return;
 	}
 
-	extraDependencyMap = new HashMap();
-	
 	IFile[] files = new IFile[sourceUnits.length];
 	for ( int i = 0; i < files.length; i++ ) {
 		if ( sourceUnits[i] instanceof SourceFile ) {
@@ -247,7 +245,6 @@
 	PreBuildCompilationEvent pbce = new PreBuildCompilationEvent( files,
 			javaBuilder.javaProject );
 
-	Set newFiles = new HashSet();
 	java.util.Iterator it = cps.iterator();
 	while ( it.hasNext() ) {
 		ICompilationParticipant p = ( ICompilationParticipant ) it.next();
@@ -262,10 +259,25 @@
 					newFiles.add( f[i] );
 			}
 			
-			mergeMaps( pbcr.getNewDependencies(), extraDependencyMap );
+			f = pbcr.getDeletedFiles();
+			if ( f != null ) { 
+				for ( int i = 0; i < f.length; i++ ) 
+					deletedFiles.add( f[i] );
+			}
+			
+			mergeMaps( pbcr.getNewDependencies(), extraDependencies );
 		}
 	}
-	return newFiles;
+	
+	if ( newFiles.size() > 0 ) {
+		Set newFiles_2 = new HashSet();
+		Set deletedFiles_2 = new HashSet();
+		ICompilationUnit[] newFileArray = ifileSet2SourceFileArray( newFiles );
+		notifyCompilationParticipants( newFileArray, newFiles_2, deletedFiles_2, extraDependencies );
+		newFiles.addAll( newFiles_2 );
+		deletedFiles.addAll( deletedFiles_2 );
+	}
+	
 }	
 
 /** 
@@ -299,27 +311,80 @@
  */
 protected ClasspathMultiDirectory getSourceLocationForFile(IFile file) {
 	ClasspathMultiDirectory md = null;
-	if ( file.exists() ) {
-		md = sourceLocations[0];
-		if ( sourceLocations.length > 1 ) {
-			IPath sourceFileFullPath = file.getFullPath();
-			for ( int j = 0, m = sourceLocations.length; j < m; j++ ) {
-				if ( sourceLocations[j].sourceFolder.getFullPath()
-						.isPrefixOf( sourceFileFullPath ) ) {
-					md = sourceLocations[j];
-					if ( md.exclusionPatterns == null
-							&& md.inclusionPatterns == null )
-						break;
-					if ( !Util.isExcluded( file, md.inclusionPatterns,
-							md.exclusionPatterns ) )
-						break;
-				}
+	md = sourceLocations[0];
+	if ( sourceLocations.length > 1 ) {
+		IPath sourceFileFullPath = file.getFullPath();
+		for ( int j = 0, m = sourceLocations.length; j < m; j++ ) {
+			if ( sourceLocations[j].sourceFolder.getFullPath()
+					.isPrefixOf( sourceFileFullPath ) ) {
+				md = sourceLocations[j];
+				if ( md.exclusionPatterns == null
+						&& md.inclusionPatterns == null )
+					break;
+				if ( !Util.isExcluded( file, md.inclusionPatterns,
+						md.exclusionPatterns ) )
+					break;
 			}
 		}
 	}
 	return md;
 }
 
+/**
+ * copies IFile entries in a Set<IFile> into SourceFile entries into a SourceFile[]. 
+ * Copying starts at the specified start position.
+ */
+private void ifileSet2SourceFileArray( Set ifiles, SourceFile[] sourceFiles, int start ) {
+	Iterator it = ifiles.iterator();
+	while ( it.hasNext() ) {
+		IFile f = ( IFile ) it.next();
+		sourceFiles[start++] = new SourceFile( f, getSourceLocationForFile( f ) );
+	}	
+}
+
+/**
+ *  Given a Set<IFile>, this method returns a SourceFile[] where each entry 
+ *  in the array corresponds to an entry in the set.
+ */
+private SourceFile[] ifileSet2SourceFileArray( Set ifiles ) {
+	SourceFile[] sf = new SourceFile[ ifiles.size() ];
+	ifileSet2SourceFileArray( ifiles, sf, 0 );
+	return sf;
+}
+
+private SourceFile[] updateSourceUnits( SourceFile[] units, Set newFiles, Set deletedFiles ) {
+	if ( newFiles.size() == 0 && deletedFiles.size() == 0 )
+		return units;
+	else if ( deletedFiles.size() == 0 ) {
+		// files have only been added
+		SourceFile[] newUnits = new SourceFile[ units.length + newFiles.size() ];
+		System.arraycopy( units, 0, newUnits, 0, units.length );
+		ifileSet2SourceFileArray( newFiles, newUnits, units.length );
+		return newUnits;
+	}
+	else {
+		// files have been added & deleted.  Deal with deleted files first.  If 
+		// someone reports that a file has been added and deleted, then it will be 
+		// added.
+		HashSet unitSet = new HashSet();
+		for ( int i=0; i<units.length; i++ )
+			unitSet.add( units[i].getFile() );
+		Iterator it = deletedFiles.iterator();
+		while ( it.hasNext() )	{
+			IFile f = (IFile) it.next();
+			if ( unitSet.contains( f ) )
+				unitSet.remove( f );
+			handleFileDeletedByCompilationParticipant( f );
+		}
+		unitSet.addAll( newFiles );
+		return ifileSet2SourceFileArray( unitSet );
+	}
+}
+
+protected void handleFileDeletedByCompilationParticipant( IFile f )
+{
+	// noop
+}
 
 void compile(SourceFile[] units, SourceFile[] additionalUnits) {
 	if (units.length == 0) return;
@@ -344,20 +409,14 @@
 	try {
 		inCompiler = true;
 		
-		// notify compilation participants, and add any new files created
-		// by the participants into the set of files being compiled. 
-		Set newFiles = notifyCompilationParticipants( units );
-		if ( newFiles != null && newFiles.size() > 0 ) {
-				SourceFile[] newUnits = new SourceFile[units.length + newFiles.size()];
-				System.arraycopy( units, 0, newUnits, 0, units.length );
-				Iterator it = newFiles.iterator();
-				int idx = units.length;
-				while ( it.hasNext() ) {
-					IFile f = ( IFile ) it.next();
-					newUnits[idx++] = new SourceFile( f, getSourceLocationForFile( f ) );
-				}
-				units = newUnits;
-		}
+		// notify compilation participants, 
+		Set newFiles = new HashSet();
+		Set deletedFiles = new HashSet();
+		extraDependencyMap = new HashMap();
+		notifyCompilationParticipants( units, newFiles, deletedFiles, extraDependencyMap );
+
+		// update units array with the new & deleted files
+		units = updateSourceUnits( units, newFiles, deletedFiles );
 		
 		compiler.compile(units);
 		
@@ -397,33 +456,21 @@
 	char[][] simpleRefs = result.simpleNameReferences;
 	
 	if ( extraDependencyMap != null && extraDependencyMap.size() > 0 ) {
-		//IFile f = javaBuilder.currentProject.getFile( new String( result.fileName ));
 		IFile f = ResourcesPlugin.getWorkspace().getRoot().getFile( new Path( new String( result.fileName ) ));
 		Set s  = (Set)extraDependencyMap.get( f );
 		if ( s != null && s.size() > 0 ) {
-			// Set<String>
-			Set simpleNameSet = new HashSet();
-			Set qualifiedNameSet = new HashSet();
+			NameSet simpleNameSet = new NameSet( simpleRefs.length + s.size() );
+			QualifiedNameSet qualifiedNameSet = new QualifiedNameSet( qualifiedRefs.length + s.size() );
 
 			//
 			// add in all of the existing refs to the sets to filter out duplicates
 			//
-			for ( int i = 0; i< simpleRefs.length; i++ ) {
-				simpleNameSet.add( new String( simpleRefs[i] ) );
-			}
-			
-			for ( int i = 0; i< qualifiedRefs.length; i++ ) {
-				
-				StringBuffer sb = new StringBuffer();
-				int len = qualifiedRefs[i].length - 1;
-				for ( int j = 0; j < len; j++ ) {
-					sb.append( qualifiedRefs[i][j] );
-					sb.append( "." );  //$NON-NLS-1$
-				}
-				sb.append( qualifiedRefs[i][len] );
-				qualifiedNameSet.add( sb.toString() );
-			}
-			
+			for ( int i = 0; i< simpleRefs.length; i++ ) 
+				simpleNameSet.add( simpleRefs[i] );
+
+			for ( int i = 0; i< qualifiedRefs.length; i++ ) 
+				qualifiedNameSet.add( qualifiedRefs[i] );
+
 			//
 			// get all of the the parts of the new dependencies into sets
 			// for  a dependency "a.b.c.d", we want the qualifiedNameSet to include
@@ -432,47 +479,34 @@
 			//
 			Iterator it = s.iterator();
 			while ( it.hasNext() ) {
-				String rpart = (String) it.next();
-				int idx = rpart.indexOf( '.', 0 );
-				while ( idx > -1 ) {
-					qualifiedNameSet.add( rpart );
-					String lpart = rpart.substring( 0, idx );
-					rpart = rpart.substring( idx + 1, rpart.length() );
-					simpleNameSet.add( lpart );
-					idx = rpart.indexOf( '.', idx + 1 );
+				char[] array = ((String) it.next() ).toCharArray();
+				char[][] parts = CharOperation.splitOn('.', array );
+				for ( int i = 0; i<parts.length; i++ )
+					simpleNameSet.add( parts[i] );
+				
+				for( int i = parts.length - 1; i > 0; --i ) {
+					qualifiedNameSet.add( parts );
+					parts = CharOperation.subarray( parts, 0, i );
 				}
-				simpleNameSet.add( rpart );
 			}
-
+	
 			//
-			// now turn the set of simple names into a char[][]
+			// strip out any null entries in the arrays retrieved from the sets.
 			//
-			char[][] newSimpleNameArray = new char[ simpleNameSet.size() ][];
-			it = simpleNameSet.iterator(); 
-			int i = 0;
-			while ( it.hasNext() ) {
-				String str = (String) it.next();
-				newSimpleNameArray[i] = str.toCharArray();
-				i++;
-			}
+			simpleRefs = new char[ simpleNameSet.elementSize][];
+			char[][] names = simpleNameSet.names;
+			int j = 0;
+			for ( int i = 0; i<names.length; i++ )
+				if ( names[i] != null)
+					simpleRefs[j++] = names[i];
 			
-			//
-			//  turn the set of qnames into a char[][][]
-			//
-			char[][][] newQualifiedNameArray = new char[ qualifiedNameSet.size() ][][];
-			it = qualifiedNameSet.iterator();
-			i = 0;
-			while ( it.hasNext() ) {
-				String str = (String) it.next();
-				String[] parts = str.split( "\\." ); //$NON-NLS-1$
-				newQualifiedNameArray[i] = new char[ parts.length ][];
-				for ( int j = 0; j < parts.length; j++ ) {
-					newQualifiedNameArray[i][j] = parts[j].toCharArray();	
-				}
-				i++;
-			}
-			qualifiedRefs = newQualifiedNameArray;
-			simpleRefs = newSimpleNameArray;
+			qualifiedRefs = new char[ qualifiedNameSet.elementSize ][][];
+			j = 0;
+			char[][][] qnames = qualifiedNameSet.qualifiedNames;
+			for ( int i = 0; i< qnames.length; i++ )
+				if ( qnames[i] != null )
+					qualifiedRefs[j++] = qnames[i];
+			
 		}
 	}
 		
diff --git a/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
index b623720..e026e78 100644
--- a/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/BatchImageBuilder.java
@@ -14,7 +14,8 @@
 import org.eclipse.core.runtime.*;
 
 import org.eclipse.jdt.core.JavaCore;
-import org.eclipse.jdt.internal.core.util.Messages;
+import org.eclipse.jdt.core.compiler.ICompilationParticipant;
+import org.eclipse.jdt.core.compiler.CleanCompilationEvent;
 import org.eclipse.jdt.internal.core.util.Util;
 
 import java.util.*;
@@ -31,12 +32,12 @@
 		System.out.println("FULL build"); //$NON-NLS-1$
 
 	try {
-		notifier.subTask(Messages.build_cleaningOutput); 
+		notifier.subTask(Util.bind("build.cleaningOutput")); //$NON-NLS-1$
 		JavaBuilder.removeProblemsAndTasksFor(javaBuilder.currentProject);
 		cleanOutputFolders(true);
 		notifier.updateProgressDelta(0.1f);
 
-		notifier.subTask(Messages.build_analyzingSources); 
+		notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$
 		ArrayList sourceFiles = new ArrayList(33);
 		addAllSourceFiles(sourceFiles);
 		notifier.updateProgressDelta(0.15f);
@@ -98,13 +99,33 @@
 	}
 }
 
+private void notifyCompilationParticipantsOfClean()
+{
+	List cps = JavaCore.getCompilationParticipants( 
+			ICompilationParticipant.CLEAN_EVENT );
+		
+	if ( cps.isEmpty() ) 
+		return;
+
+	CleanCompilationEvent pbce = new CleanCompilationEvent(	javaBuilder.javaProject );
+
+	java.util.Iterator it = cps.iterator();
+	while ( it.hasNext() ) {
+		ICompilationParticipant p = ( ICompilationParticipant ) it.next();
+		p.notify( pbce );
+	}
+}
+	
 protected void cleanOutputFolders(boolean copyBack) throws CoreException {
 	boolean deleteAll = JavaCore.CLEAN.equals(
 		javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_CLEAN_OUTPUT_FOLDER, true));
 	if (deleteAll) {
+		
+		notifyCompilationParticipantsOfClean();
+		
 		ArrayList visited = new ArrayList(sourceLocations.length);
 		for (int i = 0, l = sourceLocations.length; i < l; i++) {
-			notifier.subTask(Messages.build_cleaningOutput); 
+			notifier.subTask(Util.bind("build.cleaningOutput")); //$NON-NLS-1$
 			ClasspathMultiDirectory sourceLocation = sourceLocations[i];
 			if (sourceLocation.hasIndependentOutputFolder) {
 				IContainer outputFolder = sourceLocation.binaryFolder;
@@ -189,7 +210,7 @@
 	// When, if ever, does a builder need to copy resources files (not .java or .class) into the output folder?
 	// If we wipe the output folder at the beginning of the build then all 'extra' resources must be copied to the output folder.
 
-	notifier.subTask(Messages.build_copyingResources); 
+	notifier.subTask(Util.bind("build.copyingResources")); //$NON-NLS-1$
 	final int segmentCount = sourceLocation.sourceFolder.getFullPath().segmentCount();
 	final char[][] exclusionPatterns = sourceLocation.exclusionPatterns;
 	final char[][] inclusionPatterns = sourceLocation.inclusionPatterns;
@@ -219,7 +240,7 @@
 								createProblemFor(
 									resource,
 									null,
-									Messages.bind(Messages.build_duplicateResource, (new String[] {id})), 
+									Util.bind("build.duplicateResource", id), //$NON-NLS-1$
 									javaBuilder.javaProject.getOption(JavaCore.CORE_JAVA_BUILD_DUPLICATE_RESOURCE, true));
 								return false;
 							}
diff --git a/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java b/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
index 653bb23..60e0538 100644
--- a/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
+++ b/model/org/eclipse/jdt/internal/core/builder/IncrementalImageBuilder.java
@@ -20,7 +20,6 @@
 import org.eclipse.jdt.internal.compiler.problem.*;
 import org.eclipse.jdt.internal.compiler.util.SimpleLookupTable;
 import org.eclipse.jdt.internal.compiler.util.SuffixConstants;
-import org.eclipse.jdt.internal.core.util.Messages;
 import org.eclipse.jdt.internal.core.util.Util;
 
 import java.io.*;
@@ -71,7 +70,7 @@
 	try {
 		resetCollections();
 
-		notifier.subTask(Messages.build_analyzingDeltas); 
+		notifier.subTask(Util.bind("build.analyzingDeltas")); //$NON-NLS-1$
 		IResourceDelta sourceDelta = (IResourceDelta) deltas.get(javaBuilder.currentProject);
 		if (sourceDelta != null)
 			if (!findSourceFiles(sourceDelta)) return false;
@@ -90,7 +89,7 @@
 		}
 		notifier.updateProgressDelta(0.10f);
 
-		notifier.subTask(Messages.build_analyzingSources); 
+		notifier.subTask(Util.bind("build.analyzingSources")); //$NON-NLS-1$
 		addAffectedSourceFiles();
 		notifier.updateProgressDelta(0.05f);
 
@@ -242,6 +241,51 @@
 	return true;
 }
 
+protected void handleFileDeletedByCompilationParticipant( IFile f )
+{
+	try
+	{
+	ClasspathMultiDirectory md = getSourceLocationForFile( f );
+	int segmentCount = md.sourceFolder.getFullPath().segmentCount();
+	IPath typePath = f.getFullPath().removeFirstSegments(segmentCount).removeFileExtension();
+	String typeLocator = f.getProjectRelativePath().toString();
+	char[][] definedTypeNames = newState.getDefinedTypeNamesFor(typeLocator);
+	if (definedTypeNames == null) { // defined a single type matching typePath
+		removeClassFile(typePath, md.binaryFolder);
+		/*
+		if ((sourceDelta.getFlags() & IResourceDelta.MOVED_TO) != 0) {
+			// remove problems and tasks for a compilation unit that is being moved (to another package or renamed)
+			// if the target file is a compilation unit, the new cu will be recompiled
+			// if the target file is a non-java resource, then markers are removed
+			// see bug 2857
+			IResource movedFile = javaBuilder.workspaceRoot.getFile(sourceDelta.getMovedToPath());
+			JavaBuilder.removeProblemsAndTasksFor(movedFile); 
+		}
+		*/
+	} else {
+		if (JavaBuilder.DEBUG)
+			System.out.println("Found removed source file " + typePath.toString()); //$NON-NLS-1$
+		addDependentsOf(typePath, true); // add dependents of the source file since it may be involved in a name collision
+		if (definedTypeNames.length > 0) { // skip it if it failed to successfully define a type
+			IPath packagePath = typePath.removeLastSegments(1);
+			for (int i = 0, l = definedTypeNames.length; i < l; i++)
+				removeClassFile(packagePath.append(new String(definedTypeNames[i])), md.binaryFolder);
+		}
+	}
+	newState.removeLocator(typeLocator);
+	}
+	catch ( CoreException ce )
+	{
+		// TODO:  handle this exception
+		ce.printStackTrace();
+	}
+	catch( Exception e )
+	{
+		e.printStackTrace();
+	}
+}
+
+
 protected void findAffectedSourceFiles(IResourceDelta binaryDelta, int segmentCount, StringSet structurallyChangedTypes) {
 	// When a package becomes a type or vice versa, expect 2 deltas,
 	// one on the folder & one on the class file
diff --git a/search/org/eclipse/jdt/core/search/SearchPattern.java b/search/org/eclipse/jdt/core/search/SearchPattern.java
index 84f57f6..cd5666e 100644
--- a/search/org/eclipse/jdt/core/search/SearchPattern.java
+++ b/search/org/eclipse/jdt/core/search/SearchPattern.java
@@ -802,7 +802,9 @@
 	 * @return a search pattern on the given string pattern, or <code>null</code> if the string pattern is ill-formed
 	 */
 	public static SearchPattern createPattern(String stringPattern, int searchFor, int limitTo, int matchRule) {
-		if (stringPattern == null || stringPattern.length() == 0) return null;
+		// Null string not allowed, empty string only allowed for Package seach (default package)
+		if (stringPattern == null || stringPattern.length() == 0 && searchFor != IJavaSearchConstants.PACKAGE) 
+			return null;
 
 		// Ignore additional nature flags
 		limitTo &= ~(IJavaSearchConstants.IGNORE_DECLARING_TYPE+IJavaSearchConstants.IGNORE_RETURN_TYPE);
@@ -1087,10 +1089,8 @@
 				} catch (JavaModelException e) {
 					return null;
 				}
-				IType declaringClass = method.getDeclaringType();
-				if (ignoreDeclaringType) {
-					if (isConstructor) declaringSimpleName = declaringClass.getElementName().toCharArray();
-				} else {
+				if (!ignoreDeclaringType) {
+					IType declaringClass = method.getDeclaringType();
 					declaringSimpleName = declaringClass.getElementName().toCharArray();
 					declaringQualification = declaringClass.getPackageFragment().getElementName().toCharArray();
 					char[][] enclosingNames = enclosingTypeNames(declaringClass);