[258000] Multi threading fixes
diff --git a/plugins/org.eclipse.wst.validation.ui/vf2/org/eclipse/wst/validation/ui/internal/ManualValidationRunner.java b/plugins/org.eclipse.wst.validation.ui/vf2/org/eclipse/wst/validation/ui/internal/ManualValidationRunner.java
index 52b47ea..f70bcce 100644
--- a/plugins/org.eclipse.wst.validation.ui/vf2/org/eclipse/wst/validation/ui/internal/ManualValidationRunner.java
+++ b/plugins/org.eclipse.wst.validation.ui/vf2/org/eclipse/wst/validation/ui/internal/ManualValidationRunner.java
@@ -22,9 +22,9 @@
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.MultiRule;
 import org.eclipse.swt.widgets.Display;
-import org.eclipse.wst.validation.ValidationResult;
 import org.eclipse.wst.validation.internal.ValOperation;
 import org.eclipse.wst.validation.internal.ValType;
+import org.eclipse.wst.validation.internal.ValidationResultSummary;
 import org.eclipse.wst.validation.internal.ValidationRunner;
 import org.eclipse.wst.validation.ui.internal.dialog.ResultsDialog;
 
@@ -85,14 +85,14 @@
 		int resourceCount = 0;
 		for (Set s : _projects.values())resourceCount += s.size();
 		final int finalResourceCount = resourceCount;
-		if (vo.getResult().isCanceled())return Status.CANCEL_STATUS;
+		if (vo.isCanceled())return Status.CANCEL_STATUS;
 		
 		if (_showResults){
 			Display display = Display.getDefault();
 			Runnable run = new Runnable(){
 
 				public void run() {
-					ValidationResult vr = vo.getResult();
+					ValidationResultSummary vr = vo.getResult();
 					ResultsDialog rd = new ResultsDialog(null, vr, time, finalResourceCount);
 					rd.open();
 				}
diff --git a/plugins/org.eclipse.wst.validation.ui/vf2/org/eclipse/wst/validation/ui/internal/dialog/ResultsDialog.java b/plugins/org.eclipse.wst.validation.ui/vf2/org/eclipse/wst/validation/ui/internal/dialog/ResultsDialog.java
index 4522eea..c50e50e 100644
--- a/plugins/org.eclipse.wst.validation.ui/vf2/org/eclipse/wst/validation/ui/internal/dialog/ResultsDialog.java
+++ b/plugins/org.eclipse.wst.validation.ui/vf2/org/eclipse/wst/validation/ui/internal/dialog/ResultsDialog.java
@@ -24,10 +24,10 @@
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.swt.widgets.Label;
 import org.eclipse.swt.widgets.Shell;
-import org.eclipse.wst.validation.ValidationResult;
 import org.eclipse.wst.validation.internal.Misc;
 import org.eclipse.wst.validation.internal.ValManager;
 import org.eclipse.wst.validation.internal.ValPrefManagerGlobal;
+import org.eclipse.wst.validation.internal.ValidationResultSummary;
 import org.eclipse.wst.validation.internal.model.GlobalPreferences;
 import org.eclipse.wst.validation.internal.ui.ValidationUIMessages;
 import org.eclipse.wst.validation.ui.internal.ValUIMessages;
@@ -39,7 +39,7 @@
  */
 public class ResultsDialog extends IconAndMessageDialog {
 	
-	private ValidationResult 	_result;
+	private ValidationResultSummary 	_result;
 	private long				_time;
 	private int					_resourceCount;
 	private Button _hideButton;
@@ -52,7 +52,7 @@
 	 * @param time the time that the validation took in milliseconds
 	 * @param resourceCount the number of resources that were validated
 	 */
-	public ResultsDialog(Shell parentShell, ValidationResult results, long time, int resourceCount) {
+	public ResultsDialog(Shell parentShell, ValidationResultSummary results, long time, int resourceCount) {
 		super(parentShell);
 		_result = results;
 		_time = time;
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResults.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResults.java
index f614121..c32d273 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResults.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationResults.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.wst.validation;
 
+
 /**
  * The combined results of validating multiple resources.
  * <p>
@@ -22,10 +23,24 @@
  *
  */
 public class ValidationResults {
-	private ValidationResult _result;
+	
+	private ValidatorMessage[] _messages;
+	private int _error;
+	private int	_warn;
+	private int _info;
 	
 	public ValidationResults(ValidationResult result){
-		_result = result;
+		if (result == null){
+			_messages = new ValidatorMessage[0];			
+		}
+		else {
+			ValidatorMessage[] messages = result.getMessages();
+			_messages = new ValidatorMessage[messages.length];
+			System.arraycopy(messages, 0, _messages, 0, messages.length);
+			_error = result.getSeverityError();
+			_warn = result.getSeverityWarning();
+			_info = result.getSeverityInfo();
+		}
 	}
 	
 	/**
@@ -33,32 +48,28 @@
 	 * @return an array is returned even if there are no messages.
 	 */
 	public ValidatorMessage[] getMessages(){
-		if (_result == null)return new ValidatorMessage[0];
-		return _result.getMessages();
+		return _messages;
 	}
 
 	/**
 	 * Answer the number of error messages that were generated as part of this validation operation.
 	 */
 	public int getSeverityError() {
-		if (_result == null)return 0;
-		return _result.getSeverityError();
+		return _error;
 	}
 
 	/**
 	 * Answer the number of informational messages that were generated as part of this validation operation.
 	 */
 	public int getSeverityInfo() {
-		if (_result == null)return 0;
-		return _result.getSeverityInfo();
+		return _info;
 	}
 	
 	/**
 	 * Answer the number of warning messages that were generated as part of this validation operation.
 	 */
 	public int getSeverityWarning() {
-		if (_result == null)return 0;
-		return _result.getSeverityWarning();
+		return _warn;
 	}
 
 }
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationState.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationState.java
index 3c194ac..bee84c4 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationState.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/ValidationState.java
@@ -10,8 +10,8 @@
  *******************************************************************************/
 package org.eclipse.wst.validation;
 
-import java.util.HashMap;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;
 
@@ -48,7 +48,10 @@
 	 */
 	public static final String TriggerResource = ValidationPlugin.PLUGIN_ID + ".Trigger"; //$NON-NLS-1$
 
-	private Map<String, Object> _map = new HashMap<String, Object>(50);
+	private Map<String, Object> _map = new ConcurrentHashMap<String, Object>(50);
+	
+	public ValidationState(){
+	}
 	
 	/**
 	 * Save some state information.
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 1865096..8ecd1ac 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
@@ -662,7 +662,7 @@
 			Tracing.log("ValManager-01: " + msg); //$NON-NLS-1$
 		}
 		if (vr != null){
-			operation.getResult().mergeResults(vr);
+			operation.mergeResults(vr);
 			if (vr.getSuspendValidation() != null)operation.suspendValidation(vr.getSuspendValidation(), validator);
 		}
 	}
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperation.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperation.java
index 7f35a71..a5de936 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperation.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperation.java
@@ -10,7 +10,6 @@
  *******************************************************************************/
 package org.eclipse.wst.validation.internal;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -36,50 +35,61 @@
  * @author karasiuk
  *
  */
-public class ValOperation {
+public final class ValOperation {
 	
-	private ValidationState 	_state = new ValidationState();
-	private ValidationResult	_result = new ValidationResult();
+	private final ValidationState 	_state = new ValidationState();
+	private final ValidationResult	_result = new ValidationResult();
 	
 	/**
 	 * Each project can have a set of validators that are suspended for the duration of the validation operation.
 	 * The set contains the validator's id.
 	 */
-	private Map<IProject, Set<String>> _suspended = 
-		Collections.synchronizedMap(new HashMap<IProject, Set<String>>(40));
+	private final Map<IProject, Set<String>> _suspended = new HashMap<IProject, Set<String>>(40);
 	
 	/** The time that the operation started. */
-	private long	_started = System.currentTimeMillis();
+	private final long	_started = System.currentTimeMillis();
 	
 	/** 
-	 * Are we in a multi project validation? This can be triggered by either clean all or 
+	 * Are we in a multi project validation? That is, could we be validating several
+	 * projects at the same time? This can be triggered by either clean all or 
 	 * if auto build is turned off, a build all. 
 	 */
-	private boolean	_multiProject;
+	private final boolean	_multiProject;
 	
 	/** 
 	 * Holds all the resources that have been validated as a side-effect of running other validations.
 	 * The key is the validator id and the value is a Set of IResources.
 	 */
-	private Map<String, Set<IResource>> 	_validated = new HashMap<String, Set<IResource>>(20);
+	private final Map<String, Set<IResource>> 	_validated = new HashMap<String, Set<IResource>>(20);
 	
 	public ValOperation(){
+		_multiProject = false;
+	}
+	
+	/**
+	 * 
+	 * @param multiProject Set to true if we could be validating several projects at the same time.
+	 */
+	public ValOperation(boolean multiProject){
+		_multiProject = multiProject;
 	}
 	
 	public ValidationState getState() {
 		return _state;
 	}
-	public void setState(ValidationState state) {
-		_state = state;
-	}
-	public ValidationResult getResult() {
-		return _result;
-	}
 	
-	public void setResult(ValidationResult result) {
-		_result = result;
+	/**
+	 * Answer a summary of the validation results.
+	 * @return
+	 */
+	public ValidationResultSummary getResult() {
+		synchronized(_result){
+			ValidationResultSummary vrs = new ValidationResultSummary(_result.getSeverityError(), 
+				_result.getSeverityWarning(), _result.getSeverityInfo());
+			return vrs;
+		}
 	}
-	
+		
 	public ValidationResults getResults(){
 		return new ValidationResults(_result);
 	}
@@ -91,12 +101,14 @@
 	 * @param resource resource that has been validated.
 	 */
 	public void addValidated(String id, IResource resource){
-		Set<IResource> set = _validated.get(id);
-		if (set == null){
-			set = new HashSet<IResource>(20);
-			_validated.put(id, set);
+		synchronized(_validated){
+			Set<IResource> set = _validated.get(id);
+			if (set == null){
+				set = new HashSet<IResource>(20);
+				_validated.put(id, set);
+			}
+			set.add(resource);
 		}
-		set.add(resource);
 	}
 	
 	/**
@@ -107,10 +119,12 @@
 	 * @param resource
 	 */
 	public boolean isValidated(String id, IResource resource){
-		Set<IResource> set = _validated.get(id);
-		if (set == null)return false;
-		
-		return set.contains(resource);
+		synchronized(_validated){
+			Set<IResource> set = _validated.get(id);
+			if (set == null)return false;
+			
+			return set.contains(resource);
+		}
 	}
 
 	/**
@@ -125,8 +139,10 @@
 	 */
 	public boolean isSuspended(Validator val, IProject project) {
 		if (project == null)return false;
-		Set<String> set = getSuspended(project);		
-		return set.contains(val.getId());
+		synchronized(_suspended){
+			Set<String> set = getSuspended(project);		
+			return set.contains(val.getId());
+		}
 	}
 	
 	private Set<String> getSuspended(IProject project){
@@ -152,12 +168,34 @@
 		return _multiProject;
 	}
 
-	/** 
-	 * Are we in a multi project validation? That is, could we be validating several
-	 * projects at the same time? This can be triggered by either clean all or 
-	 * if auto build is turned off, a build all. 
+	/**
+	 * Indicate if the operation was canceled.
+	 * 
+	 * @param canceled
+	 * 		Set to true if it was canceled and false if it was not canceled.
 	 */
-	public void setMultiProject(boolean multiProject) {
-		_multiProject = multiProject;
-	}	
+	public void setCanceled(boolean canceled) {
+		synchronized (_result) {
+			_result.setCanceled(canceled);
+		}
+		
+	}
+
+	/**
+	 * Was the operation canceled before it completed? For example if the validation is being run through the
+	 * user interface, the end user can cancel the operation through the progress monitor.
+	 * 
+	 * @return true if the operation was canceled
+	 */
+	public boolean isCanceled() {
+		synchronized (_result) {
+			return _result.isCanceled();
+		}
+	}
+
+	public void mergeResults(ValidationResult vr) {
+		synchronized (_result) {
+			_result.mergeResults(vr);
+		}
+	}
 }
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationManager.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationManager.java
index e78b6e1..63d78ea 100644
--- a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationManager.java
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValOperationManager.java
@@ -10,6 +10,8 @@
  *******************************************************************************/
 package org.eclipse.wst.validation.internal;
 
+import java.util.concurrent.atomic.AtomicInteger;
+
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.IResourceChangeEvent;
@@ -112,7 +114,7 @@
 	 * If we are doing a clean all, with auto build turned on, we increment this by one, 
 	 * so that we know to throw away the first workspace, auto build, post event.
 	 */
-	private int _discardAutoPost;
+	private AtomicInteger _discardAutoPost = new AtomicInteger();
 
 	public static ValOperationManager getDefault(){
 		return Singleton.valOperationManager;
@@ -129,8 +131,9 @@
 		}
 		
 		if (isBuildStarting(event)){
-			_operation = new ValOperation();
-			_operation.setMultiProject(true);
+			synchronized(this){
+				_operation = new ValOperation(true);
+			}
 			IValidatorVisitor visitor = new IValidatorVisitor(){
 
 				public void visit(Validator validator, IProject project, ValType valType, 
@@ -146,7 +149,9 @@
 		if (isBuildFinished(event)){
 			ValOperationJob finished = new ValOperationJob(getOperation());
 			finished.schedule();
-			_operation = null;
+			synchronized(this){
+				_operation = null;
+			}
 		}
 		
 		
@@ -195,7 +200,7 @@
 		
 		if (ResourcesPlugin.getWorkspace().isAutoBuilding()){
 			if (isWorkspace && preBuild && kind == IncrementalProjectBuilder.CLEAN_BUILD){
-				_discardAutoPost = 1;
+				_discardAutoPost.set(1);
 				return true;
 			}
 			
@@ -215,8 +220,9 @@
 	 * @return return true if we are just finishing a build.
 	 */
 	private boolean isBuildFinished(IResourceChangeEvent event) {
-		
-		if (_operation == null)return false;
+		synchronized(this){
+			if (_operation == null)return false;
+		}
 		
 		int type = event.getType();
 		int kind = event.getBuildKind();
@@ -226,8 +232,7 @@
 		
 		if (ResourcesPlugin.getWorkspace().isAutoBuilding()){
 			if (isWorkspace && postBuild && kind == IncrementalProjectBuilder.AUTO_BUILD){
-				if (_discardAutoPost == 1)_discardAutoPost = 0;
-				else return true;
+				if (!_discardAutoPost.compareAndSet(1, 0))return true;
 			}
 		}
 		else {
@@ -252,7 +257,7 @@
 	 * Answer the current validation operation. If we are not in a multiple project validation
 	 * we will return a new one. 
 	 */
-	public ValOperation getOperation() {
+	public synchronized ValOperation getOperation() {
 		/*
 		 * If we don't have a current operation, we create a new one. The only time we save
 		 * the operation is when we are sure that we are in a multi project validation.
diff --git a/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationResultSummary.java b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationResultSummary.java
new file mode 100644
index 0000000..2c124bd
--- /dev/null
+++ b/plugins/org.eclipse.wst.validation/vf2/org/eclipse/wst/validation/internal/ValidationResultSummary.java
@@ -0,0 +1,27 @@
+package org.eclipse.wst.validation.internal;
+
+public class ValidationResultSummary {
+	
+	private int _error;
+	private int _warning;
+	private int	_info;
+	
+	public ValidationResultSummary(int error, int warning, int info){
+		_error = error;
+		_warning = warning;
+		_info = info;
+	}
+
+	public int getSeverityError() {
+		return _error;
+	}
+
+	public int getSeverityWarning() {
+		return _warning;
+	}
+
+	public int getSeverityInfo() {
+		return _info;
+	}
+
+}
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 c60af24..4cdb2dc 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
@@ -27,10 +27,15 @@
 
 /**
  * Run the validators on a selected set of resources.
+ * <p>
+ * This is used to run manual validations (i.e. the user selects the Validate menu item), 
+ * or it is invoked programmatically by a third party through the ValidationFramework API.
+ * It is not used for the build based invocation.
+ * </p> 
  * @author karasiuk
  *
  */
-public class ValidationRunner implements IWorkspaceRunnable {
+public final class ValidationRunner implements IWorkspaceRunnable {
 	
 	private Map<IProject, Set<IResource>>		_projects;
 	private	ValType			_valType;
@@ -91,7 +96,7 @@
 				
 		for (Map.Entry<IProject, Set<IResource>> me : _projects.entrySet()){
 			if (monitor.isCanceled()){
-				_valOperation.getResult().setCanceled(true);
+				_valOperation.setCanceled(true);
 				return _valOperation;
 			}
 			IProject project = me.getKey();