[224489][258841][258968] apply patches for these bugs
diff --git a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationOperation.java b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationOperation.java
index d56d6cb..75b76eb 100644
--- a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationOperation.java
+++ b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/operations/ValidationOperation.java
@@ -17,6 +17,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Queue;
 import java.util.Set;
 
 import org.eclipse.core.resources.IFile;
@@ -79,21 +80,48 @@
 	
 	protected static final boolean DEFAULT_FORCE = true;
 	
-	class ValidationLauncherJob extends Job {
-	    private Job validationJob;
-	    public ValidationLauncherJob(Job validationJob) {
+	private static ValidationLauncherJob launcherJob = new ValidationLauncherJob();
+	
+	private static final int jobsPerProcessor = 3;
+	
+	private static class ValidationLauncherJob extends Job {
+	    private Queue<Job> validationJobs = new LinkedList<Job>();
+	    public ValidationLauncherJob() {
             super(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_VALIDATION_JOB_MSG));
-            
             setSystem(true);
             setRule(ResourcesPlugin.getWorkspace().getRoot());
-            this.validationJob= validationJob;
 	    }
 	    
 	    protected IStatus run(IProgressMonitor monitor) {
-    		validationJob.schedule();
+			int processors = Runtime.getRuntime().availableProcessors();
+			int totalInitialJobs = processors * jobsPerProcessor;
+    		synchronized (validationJobs) {
+    			// never schedule more than 3 validation jobs per processor at a time
+    			for (int i=0; i< totalInitialJobs; i++) {
+    				Job validationJob = validationJobs.poll();
+    				if (validationJob == null) break;
+    				addJobChangeAdapter(validationJob);
+    				validationJob.schedule();
+    			}
+    		}
             return Status.OK_STATUS;
 	    }
 	    
+	    private void addJobChangeAdapter(Job job) {
+	    	job.addJobChangeListener(new JobChangeAdapter(){
+	    		// when done, see if there is another validation job to schedule
+				public void done(IJobChangeEvent event) {
+					synchronized (validationJobs) {
+						Job validationJob = validationJobs.poll();
+						if (validationJob != null) {
+							addJobChangeAdapter(validationJob);
+							validationJob.schedule();
+						}
+					}
+				}
+			});
+	    }
+	    
 	    @Override
 	    public boolean belongsTo(Object family) {
 			if (family == ResourcesPlugin.FAMILY_MANUAL_BUILD)return true;
@@ -102,6 +130,16 @@
 			}
 			return super.belongsTo(family);
 	    }
+	    
+	    public void addValidationJob(Job validationJob) {
+	    	synchronized (validationJobs) {
+	    		validationJobs.add(validationJob);
+	    		// schedule the job if we were empty
+	    		if (validationJobs.size() == 1) {
+	    			this.schedule();
+	    		}
+	    	}
+	    }
 	}
 	
 	/**
@@ -1402,9 +1440,7 @@
 			}
 		);
 		validatorjob.setPriority(Job.DECORATE);
-
-		ValidationLauncherJob validationLauncherJob = new ValidationLauncherJob(validatorjob);
-		validationLauncherJob.schedule();
+		launcherJob.addValidationJob(validatorjob);
 	}
 		
 }
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/AbstractValidator.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/AbstractValidator.java
index bda42a5..83c1d55 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/AbstractValidator.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/AbstractValidator.java
@@ -160,6 +160,23 @@
 	 */
 	public void validationFinishing(IProject project, ValidationState state, IProgressMonitor monitor){		
 	}
+	
+	/**
+	 * Should the validation framework first clear the markers that this
+	 * validator has placed on this resource? This method can be overridden by
+	 * validator implementors to provide a validator specific behavior.
+	 * 
+	 * @param event
+	 *            The validation event that triggered the validation.
+	 * @return true if the validation framework should first clear all the
+	 *         markers that this validator produced. This is the default
+	 *         behavior. Return false to leave the markers unchanged. It then
+	 *         becomes the responsibility of the validator to manage it's own
+	 *         markers for this resource, for this validation event.
+	 */
+	public boolean shouldClearMarkers(ValidationEvent event){
+		return true;
+	}
 		
 	/**
 	 * Answer the validator that you belong to. The validator controls the
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/Validator.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/Validator.java
index f79cc6d..e8948fb 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/Validator.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/Validator.java
@@ -17,6 +17,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.eclipse.core.resources.IMarker;
 import org.eclipse.core.resources.IProject;
@@ -208,6 +209,23 @@
 	}
 	
 	/**
+	 * Should the validation framework first clear the markers that this
+	 * validator has placed on this resource? This method can be overridden by
+	 * validator implementors to provide a validator specific behavior.
+	 * 
+	 * @param event
+	 *            The validation event that triggered the validation.
+	 * @return true if the validation framework should first clear all the
+	 *         markers that this validator produced. This is the default
+	 *         behavior. Return false to leave the markers unchanged. It then
+	 *         becomes the responsibility of the validator to manage it's own
+	 *         markers for this resource, for this validation event.
+	 */
+	public boolean shouldClearMarkers(ValidationEvent event){
+		return true;
+	}
+	
+	/**
 	 * Answer true if this validator, based on it's filters, should validate
 	 * this resource. This method does not check to see if global validation or
 	 * project validation has been suspended or not.
@@ -816,6 +834,17 @@
 		
 	private Level _level;
 	
+	/**
+	 * Do we still need to invoke the validateStarting method for this validator, for the null project?
+	 * 
+	 * Because we do not want to activate a validator's plug-in too soon, we do not activate the validator
+	 * as a reaction to the global validation starting event. Instead we mark it pending, and wait until
+	 * we are sure that we have something to validate.
+	 * 
+	 * If this flag is true, it means that the validateStarting method still needs to be called for this validator.
+	 */
+	private AtomicBoolean _pendingValidationStarted = new AtomicBoolean();
+	
 	V2(IConfigurationElement configElement, IProject project){
 		assert configElement != null;
 		_validatorConfigElement = configElement;
@@ -900,6 +929,7 @@
 		v._id = _id;
 		v._name = _name;
 		v._validatorGroupIds = _validatorGroupIds;
+		v._pendingValidationStarted = _pendingValidationStarted;
 				
 		return v;
 	}
@@ -1014,6 +1044,11 @@
 	boolean isLoaded() {
 		return _validator != null;
 	}
+	
+	@Override
+	public boolean shouldClearMarkers(ValidationEvent event) {
+		return getValidator().shouldClearMarkers(event);
+	}
 		
 	/**
 	 * Answer true if this validator, based on it's filters, should validate this resource.
@@ -1194,12 +1229,22 @@
 	
 	@Override
 	public void validationStarting(IProject project, ValidationState state, IProgressMonitor monitor) {
-		getDelegatedValidator().validationStarting(project, state, monitor);
+		if (project == null)_pendingValidationStarted.set(true);
+		else {
+			AbstractValidator val = getDelegatedValidator();
+			if (_pendingValidationStarted.getAndSet(false)){
+				val.validationStarting(null, state, monitor);
+			}
+			val.validationStarting(project, state, monitor);
+		}
 	}
 	
 	@Override
 	public void validationFinishing(IProject project, ValidationState state, IProgressMonitor monitor) {
-		getDelegatedValidator().validationFinishing(project, state, monitor);
+		if (project == null){
+			if (!_pendingValidationStarted.getAndSet(false))getDelegatedValidator().validationFinishing(null, state, monitor);
+		}
+		else getDelegatedValidator().validationFinishing(project, state, monitor);
 	}
 
 	@SuppressWarnings("unchecked")
@@ -1240,6 +1285,7 @@
 		_groupsArray = v2._groupsArray;
 		_id = v2._id;
 		_name = v2._name;
+		_pendingValidationStarted = v2._pendingValidationStarted;
 		_validator = v2._validator;
 		_validatorConfigElement = v2._validatorConfigElement;
 		_validatorClassName = v2._validatorClassName;
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValBuilderJob.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValBuilderJob.java
index 5d3ab2b..5ab8edb 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValBuilderJob.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValBuilderJob.java
@@ -189,6 +189,7 @@
 		
 	}
 
+	@SuppressWarnings("deprecation")
 	public boolean visit(IResourceDelta delta) throws CoreException {
 		IResource resource = delta.getResource();
 		if (DisabledResourceManager.getDefault().isDisabled(resource)){
@@ -208,11 +209,12 @@
 		if (index.isDependedOn(resource)){
 			MarkerManager mm = MarkerManager.getDefault();
 			for (DependentResource dr : index.get(resource)){
-				if (Friend.shouldValidate(dr.getValidator(), dr.getResource(), ValType.Build, new ContentTypeWrapper())){
-					mm.clearMarker(dr.getResource(), dr.getValidator()); 
+				Validator val = dr.getValidator();
+				if (Friend.shouldValidate(val, dr.getResource(), ValType.Build, new ContentTypeWrapper())){
 					_request.getOperation().getState().put(ValidationState.TriggerResource, resource);
 					ValidationEvent event = new ValidationEvent(dr.getResource(), IResourceDelta.NO_CHANGE, delta);
-					ValManager.getDefault().validate(dr.getValidator(), _request.getOperation(), dr.getResource(), 
+					if (val.shouldClearMarkers(event))mm.clearMarker(dr.getResource(), val); 
+					ValManager.getDefault().validate(val, _request.getOperation(), dr.getResource(), 
 						IResourceDelta.NO_CHANGE, _monitor, event);
 				}
 			}