[220809] need a way to selectively disable validation
diff --git a/plugins/org.eclipse.wst.validation.ui/validateui/org/eclipse/wst/validation/internal/ui/ValidationMenuAction.java b/plugins/org.eclipse.wst.validation.ui/validateui/org/eclipse/wst/validation/internal/ui/ValidationMenuAction.java
index 9a7a33d..af083e7 100644
--- a/plugins/org.eclipse.wst.validation.ui/validateui/org/eclipse/wst/validation/internal/ui/ValidationMenuAction.java
+++ b/plugins/org.eclipse.wst.validation.ui/validateui/org/eclipse/wst/validation/internal/ui/ValidationMenuAction.java
@@ -41,6 +41,7 @@
 import org.eclipse.ui.IViewPart;
 import org.eclipse.wst.validation.ValidationFramework;
 import org.eclipse.wst.validation.internal.ConfigurationManager;
+import org.eclipse.wst.validation.internal.DisabledResourceManager;
 import org.eclipse.wst.validation.internal.ValType;
 import org.eclipse.wst.validation.internal.ValidationRegistryReader;
 import org.eclipse.wst.validation.internal.ValidationSelectionHandlerRegistryReader;
@@ -133,8 +134,8 @@
 				}
 			}
 			if (!valid) {
-				// Stop processing. (This allows the "Run Validation" menu item
-				// to gray out once at least one non-validatable element is selected.)
+				// Stop processing. This allows the "Run Validation" menu item
+				// to gray out once an element that can not be validated is selected.
 				_selectedResources.clear();
 			}
 		}
@@ -208,10 +209,11 @@
 		if (_projectVisitor == null) {
 			_projectVisitor = new IResourceVisitor() {
 				public boolean visit(IResource res) {
+					if (DisabledResourceManager.getDefault().isDisabled(res))return false;
 					if (res instanceof IFile)addSelected(res);
 					else if (res instanceof IFolder)addSelected(res);
 					
-					return true; // visit the resource's children
+					return true;
 				}
 			};
 		}
diff --git a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/FilterUtil.java b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/FilterUtil.java
index c7da535..435a41b 100644
--- a/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/FilterUtil.java
+++ b/plugins/org.eclipse.wst.validation/validate/org/eclipse/wst/validation/internal/FilterUtil.java
@@ -340,34 +340,39 @@
 	}
 
 	/**
-	 * Whether a full verification or a delta verification is in progress, both will call this
-	 * method to process the resource. This method calls the current Validator to filter the
-	 * resource (i.e., this method returns if the resource fails the filter test).
-	 * <code>process</code> also sends output to the <code>IProgressMonitor</code>, and calls
-	 * the current Validator to validate the resource.
-	 * 
-	 * To process a resource, there are several steps: 1. check if the resource is registered for
-	 * this validator (i.e., the validator has either specified it in a filter, or has not filtered
-	 * it out explicitly) 2. call <code>isValidationSource</code> on the current validator with
-	 * the current resource. This method performs further filtering by the Validator itself, in
-	 * addition to the static filtering done by the framework, based on the information in
-	 * plugin.xml. 3. If the resource passes both filters, call <code>validate</code> on the
-	 * validator, with the resource. 4. When complete (either by failing to pass a filter, or by the
-	 * completion of the <code>validate</code>), increment the IProgressMonitor's status by one
-	 * (i.e., one resource has been processed.)
+	 * Whether a full verification or a delta verification is in progress, both
+	 * will call this method to process the resource. This method calls the
+	 * current Validator to filter the resource (i.e., this method returns if
+	 * the resource fails the filter test). It also sends output to the
+	 * <code>IProgressMonitor</code>, and calls the current Validator to
+	 * validate the resource.
+	 * <p>
+	 * To process a resource, there are several steps:
+	 * <ol>
+	 * <li>Check if the resource is registered for this validator (i.e., the
+	 * validator has either specified it in a filter, or has not filtered it out
+	 * explicitly)
+	 * <li>Call <code>isValidationSource</code> on the current validator with
+	 * the current resource. This method performs further filtering by the
+	 * Validator itself, in addition to the static filtering done by the
+	 * framework, based on the information in the extension point.
+	 * <li>If the resource passes both filters, call <code>validate</code> on
+	 * the validator, with the resource.
+	 * <li>When complete (either by failing to pass a filter, or by the
+	 * completion of the <code>validate</code>), increment the
+	 * IProgressMonitor's status by one (i.e., one resource has been processed.)
+	 * </ol>
 	 */
-	static void filterOut(IProgressMonitor monitor, Map<ValidatorMetaData, Set<IFileDelta>> enabledValidators, IResource resource, int resourceDelta, boolean isFullBuild) {
+	static void filterOut(IProgressMonitor monitor, Map<ValidatorMetaData, Set<IFileDelta>> enabledValidators, 
+		IResource resource, int resourceDelta, boolean isFullBuild) {
 		if (monitor == null)return;
 
 		checkCanceled(monitor);
 
-		Iterator iterator = enabledValidators.keySet().iterator();
 		boolean cannotLoad = false;
-		while (iterator.hasNext()) {
+		for (ValidatorMetaData vmd : enabledValidators.keySet()) {
 			checkCanceled(monitor);
 
-			ValidatorMetaData vmd = (ValidatorMetaData) iterator.next();
-
 			if (!filterOut(monitor, vmd, resource, resourceDelta)) {
 				try {
 					// Notify the helper that a resource is about to be filtered in
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationFramework.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationFramework.java
index d9c8e8b..37cb53d 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationFramework.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationFramework.java
@@ -31,6 +31,7 @@
 import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.wst.validation.internal.DebugConstants;
 import org.eclipse.wst.validation.internal.DependencyIndex;
+import org.eclipse.wst.validation.internal.DisabledResourceManager;
 import org.eclipse.wst.validation.internal.MarkerManager;
 import org.eclipse.wst.validation.internal.Misc;
 import org.eclipse.wst.validation.internal.PerformanceMonitor;
@@ -83,28 +84,34 @@
 	}
 	
 	/**
-	 * Disable all validation for the given resource. This method instructions the framework
-	 * to not run any validators on the given resource or any of it's children. This setting is
-	 * persistent. 
+	 * Disable all validation for the given resource. This method instructions
+	 * the framework to not run any validators on the given resource or any of
+	 * it's children. This setting is persistent. Currently this only works with version 2
+	 * validators.
 	 * 
 	 * Use the enableValidation method to restore validation.
 	 * 
-	 * @param resource the resource that is having validation disabled.
+	 * @param resource
+	 *            The resource that is having validation disabled. It must be an IFolder or an IFile.
 	 * 
 	 * @see #enableValidation(IResource)
 	 */
 	public void disableValidation(IResource resource){
+		assert resource != null;
+		DisabledResourceManager.getDefault().disableValidation(resource);
 	}
 	
 	/**
 	 * Enable validation for the given resource. If the resource was not previously
-	 * disabled this method call has no effect.
+	 * disabled this method call has no effect. Currently this only works with version 2 
+	 * validators.
 	 * 
-	 * @param resource the resource that is having validation re-enabled.
+	 * @param resource The resource that is having validation re-enabled.
 	 * 
 	 * @see #disableValidation(IResource)
 	 */
 	public void enableValidation(IResource resource){
+		DisabledResourceManager.getDefault().enableValidation(resource);
 	}
 	
 	/**
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/DisabledResourceManager.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/DisabledResourceManager.java
index 3f9312c..1b522fa 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/DisabledResourceManager.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/DisabledResourceManager.java
@@ -15,6 +15,13 @@
 
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.ProjectScope;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;
+import org.osgi.service.prefs.BackingStoreException;
 
 /**
  * Validators can assert that certain resources (usually folders) are not validated. This class keeps track of those
@@ -32,23 +39,95 @@
 	}
 	
 	private Set<IResource> _disabled = new HashSet<IResource>(100);
+	private Set<IProject>	_loadedProjects = new HashSet<IProject>(40);
 	
 	private DisabledResourceManager(){
 		EventManager.getManager().addProjectChangeListener(this);
 	}
 	
+	public void disableValidation(IResource resource){
+		// We check for two reasons, 1) we may save some work, 2) we force the project to be loaded 
+		if (isDisabled(resource))return;
+		
+		Set<IResource> copy = new HashSet<IResource>(_disabled.size()+2);
+		copy.addAll(_disabled);
+		copy.add(resource);
+		save(copy, resource.getProject());
+		_disabled = copy;
+	}
+	
+	public void enableValidation(IResource resource){
+		// We check for two reasons, 1) we may save some work, 2) we force the project to be loaded 
+		if (!isDisabled(resource))return;
+		
+		Set<IResource> copy = new HashSet<IResource>(_disabled.size()+2);
+		copy.addAll(_disabled);
+		copy.remove(resource);
+		save(copy, resource.getProject());
+		_disabled = copy;		
+	}
+	
+	private IEclipsePreferences getPreferences(IProject project){
+		IScopeContext projectContext = new ProjectScope(project);
+		return projectContext.getNode(ValidationPlugin.PLUGIN_ID);
+	}
+	
+	private void save(Set<IResource> disabled, IProject project) {
+		Serializer ser = new Serializer(200);
+		for (IResource resource : disabled){
+			if (project == resource.getProject()){
+				ser.put(resource.getProjectRelativePath().toPortableString());
+			}
+		}
+		IEclipsePreferences prefs = getPreferences(project);
+		prefs.put(PrefConstants.disabled, ser.toString());
+		try {
+			prefs.flush();
+		}
+		catch (BackingStoreException e){
+			ValidationPlugin.getPlugin().handleException(e);
+		}
+	}
+	
+	private void load(IProject project){
+		Set<IResource> copy = new HashSet<IResource>(_disabled.size()+10);
+		copy.addAll(_disabled);
+		IEclipsePreferences prefs = getPreferences(project);
+		String disabled = prefs.get(PrefConstants.disabled, ""); //$NON-NLS-1$
+		if (disabled.length() > 0){
+			Deserializer des = new Deserializer(disabled);
+			while(des.hasNext()){
+				String pathString = des.getString();
+				IPath path = Path.fromPortableString(pathString);
+				IResource resource = project.findMember(path);
+				copy.add(resource);
+			}
+		}
+		_disabled = copy;
+	}
+
 	public void dispose(){
 		EventManager.getManager().removeProjectChangeListener(this);
 	}
 	
 	/**
-	 * Answer true if this resource and any of it's children should not be validated.
+	 * Answer true if this resource should not be validated.
 	 * 
 	 * @param resource the resource that is being tested.
 	 * @return true if the resource should not be validated.
 	 */
 	public boolean isDisabled(IResource resource){
-		return !_disabled.contains(resource);
+		IProject project = resource.getProject();
+		if (_loadedProjects.contains(project))return _disabled.contains(resource);
+		return isDisabled(resource, project); 		
+	}
+	
+	private synchronized boolean isDisabled(IResource resource, IProject project){
+		if (!_loadedProjects.contains(project)){
+			load(project);
+			_loadedProjects.add(project);
+		}
+		return _disabled.contains(resource);
 	}
 	
 	public void addDisabled(IResource resource){
@@ -66,7 +145,8 @@
 		
 	}
 	
-	private void projectRemoved(IProject project) {
+	private synchronized void projectRemoved(IProject project) {
+		_loadedProjects.remove(project);
 		Set<IResource> copy = new HashSet<IResource>(100);
 		for (IResource resource : _disabled){
 			if (resource.getProject() != project)copy.add(resource);
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/MarkerManager.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/MarkerManager.java
index 7034764..4307902 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/MarkerManager.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/MarkerManager.java
@@ -47,10 +47,12 @@
 	
 	/**
 	 * Clear any validation markers that may have been set by this validator.
-	 *  
-	 * @param resource the resource that may have it's markers cleared. It can be null, in which case
-	 * the operation is a no-op.
-	 * @param validator the validator that created the marker
+	 * 
+	 * @param resource
+	 *            The resource that may have it's markers cleared. It can be
+	 *            null, in which case the operation is a no-op.
+	 * @param validator
+	 *            The validator that created the marker.
 	 */
 	public void clearMarker(IResource resource, Validator validator) throws CoreException {
 		if (resource == null)return;
@@ -89,14 +91,21 @@
 	}
 	
 	/**
-	 * Delete all the markers on this resource that were created before the operation start time.
+	 * Delete all the markers on this resource that were created before the
+	 * operation start time.
+	 * 
 	 * @param resource
+	 *            The resource that is having it's markers deleted.
 	 * @param operationStartTime
+	 *            The time as returned by System.currentTimeMillis().
+	 * @param depth
+	 *            The depth of the markers to clear. It is one of the
+	 *            IResource.DEPTH_XXX constants.
 	 */
-	public void deleteMarkers(IResource resource, long operationStartTime){
+	public void deleteMarkers(IResource resource, long operationStartTime, int depth){
 		try {
-			hook(resource);
-			IMarker[] markers = resource.findMarkers(null, true, IResource.DEPTH_ZERO);
+			hook(resource); 
+			IMarker[] markers = resource.findMarkers(null, true, depth);
 			for (IMarker marker : markers){
 				if (_markers.contains(marker.getType())){
 					long createTime = marker.getCreationTime();
@@ -112,6 +121,7 @@
 			ValidationPlugin.getPlugin().handleException(e);
 		}		
 	}
+	
 	public void makeMarkers(List<IMessage> list){
 		for (IMessage message : list){
 			IResource res = null;
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/PrefConstants.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/PrefConstants.java
index ec35427..3bac075 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/PrefConstants.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/PrefConstants.java
@@ -49,6 +49,9 @@
 	/** delegate - the delegating implementation to use */
 	String delegate = "delegate"; //$NON-NLS-1$
 	
+	/** disabled - the list of disabled resources in the project. */
+	String disabled = "disabled"; //$NON-NLS-1$
+	
 	/** exactMatch - must the content type match exactly? */
 	String exactMatch = "exactMatch"; //$NON-NLS-1$
 	
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 ebe8090..32884ef 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
@@ -127,10 +127,14 @@
 	}
 
 	public boolean visit(IResourceDelta delta) throws CoreException {
+		IResource resource = delta.getResource();
+		if (DisabledResourceManager.getDefault().isDisabled(resource)){
+			MarkerManager.getDefault().deleteMarkers(resource, _operation.getStarted(), IResource.DEPTH_INFINITE);
+			return false;
+		}
 		int kind = delta.getKind();
 		if ((delta.getFlags() & InterestedFlags) == 0)return true;
 		
-		IResource resource = delta.getResource();
 		if ((kind & (IResourceDelta.ADDED | IResourceDelta.CHANGED)) != 0){
 			ValManager.getDefault().validate(_project, resource, delta.getKind(), ValType.Build, _buildKind, 
 				_operation, _monitor);
@@ -154,6 +158,11 @@
 
 	public boolean visit(IResource resource) throws CoreException {
 		try {
+			if (DisabledResourceManager.getDefault().isDisabled(resource)){
+				MarkerManager.getDefault().deleteMarkers(resource, _operation.getStarted(), IResource.DEPTH_INFINITE);
+				return false;
+			}
+			
 			ValManager.getDefault().validate(_project, resource, IResourceDelta.NO_CHANGE, ValType.Build, 
 				_buildKind, _operation, _monitor);
 		}
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValManager.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValManager.java
index f09c2de..4dce10b 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValManager.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValManager.java
@@ -498,7 +498,7 @@
 	public void validate(IProject project, final IResource resource, final int kind, ValType valType, 
 		int buildKind, ValOperation operation, final IProgressMonitor monitor) {
 		
-		MarkerManager.getDefault().deleteMarkers(resource, operation.getStarted());
+		MarkerManager.getDefault().deleteMarkers(resource, operation.getStarted(), IResource.DEPTH_ZERO);
 		
 		IValidatorVisitor visitor = new IValidatorVisitor(){
 
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationRunner.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationRunner.java
index 94302f0..45bc4c3 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationRunner.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationRunner.java
@@ -47,7 +47,7 @@
 	 *            The type of validation that has been requested.
 	 * 
 	 * @param monitor
-	 *            progress monitor
+	 *            Progress monitor.
 	 */
 	public static ValOperation validate(Map<IProject, Set<IResource>> projects, ValType valType, 
 		IProgressMonitor monitor) throws CoreException{