/*******************************************************************************
 * Copyright (c) 2001, 2008 IBM Corporation and others.
 * 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:
 * IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.validation.internal.operations;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.QualifiedName;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.IJobChangeEvent;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.JobChangeAdapter;
import org.eclipse.wst.common.frameworks.internal.operations.IHeadlessRunnableWithProgress;
import org.eclipse.wst.validation.ValidationFramework;
import org.eclipse.wst.validation.internal.FilterUtil;
import org.eclipse.wst.validation.internal.IProjectValidationHelper;
import org.eclipse.wst.validation.internal.InternalValidatorManager;
import org.eclipse.wst.validation.internal.ReferencialFileValidatorRegistryReader;
import org.eclipse.wst.validation.internal.RegistryConstants;
import org.eclipse.wst.validation.internal.ResourceConstants;
import org.eclipse.wst.validation.internal.ResourceHandler;
import org.eclipse.wst.validation.internal.TaskListUtility;
import org.eclipse.wst.validation.internal.Tracing;
import org.eclipse.wst.validation.internal.ValManager;
import org.eclipse.wst.validation.internal.ValidationRegistryReader;
import org.eclipse.wst.validation.internal.ValidatorMetaData;
import org.eclipse.wst.validation.internal.core.IFileDelta;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.core.ValidatorLauncher;
import org.eclipse.wst.validation.internal.plugin.ValidationHelperRegistryReader;
import org.eclipse.wst.validation.internal.plugin.ValidationPlugin;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
import org.eclipse.wst.validation.internal.provisional.core.IValidator;
import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob;

/**
 * Implemented Validators methods must not be called directly by anyone other than this class, since
 * some initialization of the validator is done here (via the getProject() method). The
 * initialization is separated because the IProject isn't known until runtime.
 * <p>
 * This operation is not intended to be subclassed outside of the validation framework.
 */
public abstract class ValidationOperation implements IWorkspaceRunnable, IHeadlessRunnableWithProgress {
	// Since IResourceConstants don't have a "no delta" flag, let this constant be the flag.
	public static final int NO_DELTA_CHANGE = -1; 
	private static final String DELTA_AS_STRING = "IFileDelta[{0}] '{'{1}'}'"; //$NON-NLS-1$
	private static final String COMMA = ", "; //$NON-NLS-1$
	
	// For the depreciated constructors, by default the operation will not fork. 
	protected static final boolean DEFAULT_ASYNC = true;
	
	protected static final boolean DEFAULT_FORCE = true;
	
	class ValidationLauncherJob extends Job {
	    private Job validationJob;
	    public ValidationLauncherJob(Job validationJob) {
            super(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_VALIDATION_JOB_MSG));
            
            setSystem(true);
            setRule(ResourcesPlugin.getWorkspace().getRoot());
            this.validationJob= validationJob;
	    }
	    
	    protected IStatus run(IProgressMonitor monitor) {
    		validationJob.schedule();
            return Status.OK_STATUS;
	    }
	    
	    @Override
	    public boolean belongsTo(Object family) {
			if (family == ResourcesPlugin.FAMILY_MANUAL_BUILD)return true;
			if (family == ValidationBuilder.FAMILY_VALIDATION_JOB){
				return true;
			}
			return super.belongsTo(family);
	    }
	}
	
	/**
	 * @deprecated Will be removed in Milestone 3. Use DEFAULT_ASYNC
	 */
	protected static final boolean DEFAULT_FORK = false; // @deprecated
	private IProject 		_project; // project to be validated
	private int 			_ruleGroup = RegistryConstants.ATT_RULE_GROUP_DEFAULT;
	private boolean _fork = DEFAULT_ASYNC; // do not fork the validation into a
	// different thread by default
	private Map<ValidatorMetaData, Set<IFileDelta>> _fileDeltas; // To reduce object creation,
	private IResourceDelta _delta;
	
	// the resource delta tree to be processed, or null if a full build/menu
	// option was triggered. This value is cached so that validation can be run
	// either from a builder, or from a menu item. (The Operation interface
	// doesn't allow any parameter on execute except the IProgressMonitor.)
	private Set<ValidatorMetaData> _enabledValidators;
	
	private boolean _force = DEFAULT_FORCE; // force this operation to run even if it doesn't need to?
	private boolean _isFullValidate; 	// Run a full validation or an incremental? (true = full)
	private Boolean _isAutoBuild; 		// Is the global auto-build preference enabled?
	private Set<ValidatorMetaData> _launchedValidators;
	
	protected IWorkbenchContext context;

	// are enabled and were launched (i.e., that have input to validate). For internal
	// validation framework use only;
	// it's needed for the automatic tests.
	/**
	 * This method is used for FINEST logging, to report exactly what deltas were about to be
	 * validated.
	 */
	private static final String getDeltaAsString(IFileDelta[] delta) {
		String args = ""; //$NON-NLS-1$
		int numArgs = 0;
		if (delta != null) {
			numArgs = delta.length;
			StringBuffer buffer = new StringBuffer();
			for (int i = 0; i < delta.length; i++) {
				buffer.append(COMMA);
				buffer.append(delta[i].toString());
			}
			buffer.replace(0, 1, ""); //$NON-NLS-1$ // magic numbers 0 and 1 => Remove first COMMA from the list (hence index 0); length of COMMA is 2, hence index 0, 1.
			args = buffer.toString();
		}
		return MessageFormat.format(DELTA_AS_STRING, new Object[]{String.valueOf(numArgs), args});
	}

	protected static void checkCanceled(WorkbenchReporter reporter) throws OperationCanceledException {
		if (reporter == null)return;
		else if (reporter.getProgressMonitor().isCanceled()) {
			throw new OperationCanceledException(""); //$NON-NLS-1$
		}
	}

	protected static boolean shouldForce(IResourceDelta delta) {
		return ((delta == null) ? DEFAULT_FORCE : false);
	}

	protected static boolean shouldForce(Object[] changedResources) {
		return (((changedResources == null) || (changedResources.length == 0)) ? DEFAULT_FORCE : false);
	}

	/**
	 * @deprecated. Will be removed in Milestone 3. Use ValidationOperation(project, boolean)
	 */
	public ValidationOperation(IProject project) {
		this(project, DEFAULT_ASYNC, DEFAULT_FORCE);
	}

	/**
	 * Internal.
	 */
	public ValidationOperation(IProject project, boolean force, boolean async) {
		this(project, null, null, RegistryConstants.ATT_RULE_GROUP_DEFAULT, force, async);
	}

	/**
	 * @deprecated. Will be removed in Milestone 3. Use ValidationOperation(project, int, boolean)
	 */
	public ValidationOperation(IProject project, int ruleGroup) {
		this(project, null, null, ruleGroup, DEFAULT_FORCE, DEFAULT_ASYNC);
	}

	/**
	 * @deprecated. Will be removed in Milestone 3. Use ValidationOperation(IProject,
	 *              IResourceDelta, Boolean, int, boolean, boolean)
	 */
	public ValidationOperation(IProject project, IResourceDelta delta, boolean isAutoBuild, int ruleGroup, boolean force, boolean fork) {
		this(project, delta, ((isAutoBuild) ? Boolean.TRUE : Boolean.FALSE), ruleGroup, fork, force);
	}

	/**
	 * Internal.
	 */
	protected ValidationOperation(IProject project, IResourceDelta delta, Boolean isAutoBuild, int ruleGroup, boolean force, boolean fork) {
		super();
		_project = project;
		_delta = delta;
		_isAutoBuild = isAutoBuild;
		_ruleGroup = ruleGroup;
		_fork = fork;
		_force = force;
		_enabledValidators = new HashSet<ValidatorMetaData>();
	}
	
	/**
	 * Internal.
	 */
	protected ValidationOperation(IProject project, IWorkbenchContext aContext, IResourceDelta delta, Boolean isAutoBuild, int ruleGroup, boolean force, boolean fork) {
		super();
		_project = project;
		_delta = delta;
		_isAutoBuild = isAutoBuild;
		_ruleGroup = ruleGroup;
		_fork = fork;
		_force = force;
		_enabledValidators = new HashSet<ValidatorMetaData>();
		context = aContext;
	}

	/**
	 * @deprecated Will be removed in Milestone 3.
	 */
	protected void terminateCleanup(WorkbenchReporter reporter) {
		Set enabledValidators = getEnabledValidators();
		Iterator iterator = enabledValidators.iterator();
		ValidatorMetaData vmd = null;

		while (iterator.hasNext()) {
			vmd = (ValidatorMetaData) iterator.next();
			reporter.displaySubtask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_VALIDATOR_CLEANUP, new String[]{vmd.getValidatorDisplayName()}));
			try {
				reporter.removeAllMessages(vmd.getValidator());
			} catch (InstantiationException e) {
				// Remove the vmd from the reader's list
				ValidationRegistryReader.getReader().disableValidator(vmd);
				ValidationPlugin.getPlugin().handleException(e);
				continue;
			}
			addCancelTask(vmd);
			reporter.displaySubtask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_VALIDATOR_TERMINATED, new String[]{getProject().getName(), vmd.getValidatorDisplayName()}));
		}
	} 
	

	/**
	 * @param vmd
	 * @param delta
	 * @param logger
	 * @param start
	 */
//	private void logValidationInfo(ValidatorMetaData vmd, IFileDelta[] delta, Logger logger, long start) {
//		long finish = System.currentTimeMillis();
//		TimeEntry entry = ValidationPlugin.getTimeEntry();
//		entry.setSourceID("ValidationOperation.launchValidator"); //$NON-NLS-1$
//		entry.setProjectName(getProject().getName());
//		entry.setToolName(vmd.getValidatorUniqueName());
//		entry.setElapsedTime(finish - start);
//		if (logger.isLoggingLevel(Level.FINE)) {
//			StringBuffer buffer = new StringBuffer();
//			if (isFullValidate()) {
//				buffer.append("EVERYTHING"); //$NON-NLS-1$
//			} else {
//				if (delta.length == 0) {
//					buffer.append("NOTHING"); //$NON-NLS-1$
//				} else {
//					buffer.append(getDeltaAsString(delta));
//				}
//			}
//			entry.setDetails(buffer.toString());
//		}
//		logger.write(Level.INFO, entry);
//	}

	/**
	 * @param reporter
	 * @param vmd
	 * @param logger
	 * @param exc
	 */
//	private void handleThrowables(WorkbenchReporter reporter, ValidatorMetaData vmd, Logger logger, Throwable exc) {
//		// If a runtime exception has occured, e.g. NullPointer or ClassCast,
//		// display it with the "A runtime exception has occurred " messsage.
//		// This will provide more information to the user when he/she calls IBM
//		// Service.
//		if (logger.isLoggingLevel(Level.SEVERE)) {
//			LogEntry entry = ValidationPlugin.getLogEntry();
//			entry.setSourceID("ValidationOperation::launchValidator"); //$NON-NLS-1$
//			entry.setTargetException(exc);
//			logger.write(Level.SEVERE, entry);
//		}
//		String[] msgParm = {exc.getClass().getName(), vmd.getValidatorDisplayName(), (exc.getMessage() == null ? "" : exc.getMessage())}; //$NON-NLS-1$
//		Message message = ValidationPlugin.getMessage();
//		message.setSeverity(IMessage.NORMAL_SEVERITY);
//		message.setId(ResourceConstants.VBF_EXC_RUNTIME);
//		message.setParams(msgParm);
//		try {
//			reporter.addMessage(vmd.getValidator(), message);
//		} catch (InstantiationException exc2) {
//			handleInstantiationException(vmd, logger, exc2);
//		} catch (MessageLimitException e) {
//			throw e;
//		}
//		return;
//	}

	/**
	 * @param vmd
	 * @param logger
	 * @param exc2
	 */
//	private void handleInstantiationException(ValidatorMetaData vmd, Logger logger, InstantiationException exc2) {
//		// Remove the vmd from the reader's list
//		ValidationRegistryReader.getReader().disableValidator(vmd);
//		// Log the reason for the disabled validator
//		if (logger.isLoggingLevel(Level.SEVERE)) {
//			LogEntry entry = ValidationPlugin.getLogEntry();
//			entry.setSourceID("ValidationOperation::launchValidator (deprecated)"); //$NON-NLS-1$
//			entry.setTargetException(exc2);
//			logger.write(Level.SEVERE, entry);
//		}
//	}

	/**
	 * @param reporter
	 * @param vmd
	 * @param logger
	 * @param exc
	 */
//	private void handleValidationExceptions(WorkbenchReporter reporter, ValidatorMetaData vmd, Logger logger, ValidationException exc) {
//		// First, see if a validator just caught all Throwables and
//		// accidentally wrapped a MessageLimitException instead of propagating
//		// it.
//		if (exc.getAssociatedException() != null) {
//			if (exc.getAssociatedException() instanceof MessageLimitException) {
//				MessageLimitException mssgExc = (MessageLimitException) exc.getAssociatedException();
//				throw mssgExc;
//			} else if (exc.getAssociatedException() instanceof ValidationException) {
//				try {
//					ValidationException vexc = (ValidationException) exc.getAssociatedException();
//					vexc.setClassLoader(vmd.getValidator().getClass().getClassLoader()); // first,
//					// set the class loader,so that the exception's getMessage() method can retrieve
//					// the resource bundle
//				} catch (InstantiationException exc2) {
//					handleInstantiationException(vmd, logger, exc2);
//				}
//			}
//		}
//		// If there is a problem with this particular validator, log the error
//		// and continue
//		// with the next validator.
//		try {
//			exc.setClassLoader(vmd.getValidator().getClass().getClassLoader()); // first,
//			// set the class loader,so that the exception's getMessage() method can retrieve the
//			// resource bundle
//		} catch (InstantiationException exc2) {
//			handleInstantiationException(vmd, logger, exc2);
//		}
//		if (logger.isLoggingLevel(Level.SEVERE)) {
//			LogEntry entry = ValidationPlugin.getLogEntry();
//			entry.setSourceID("ValidationOperation.validate(WorkbenchMonitor)"); //$NON-NLS-1$
//			entry.setTargetException(exc);
//			logger.write(Level.SEVERE, entry);
//			if (exc.getAssociatedException() != null) {
//				entry.setTargetException(exc.getAssociatedException());
//				logger.write(Level.SEVERE, entry);
//			}
//		}
//		String message = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
//		reporter.displaySubtask(message);
//		if (exc.getAssociatedMessage() != null) {
//			try {
//				reporter.addMessage(vmd.getValidator(), exc.getAssociatedMessage());
//			} catch (InstantiationException exc2) {
//				handleInstantiationException(vmd, logger, exc2);
//			}
//		}
//	}

	/**
	 * @param reporter
	 * @param vmd
	 * @param logger
	 * @param exc
	 */
//	private void handleHelperCleanupExceptions(WorkbenchReporter reporter, ValidatorMetaData vmd, Logger logger, Throwable exc) {
//		// If a runtime exception has occured, e.g. NullPointer or ClassCast,
//		// display it with the "A runtime exception has occurred " messsage.
//		// This will provide more information to the user when he/she calls IBM
//		// Service.
//		if (logger.isLoggingLevel(Level.SEVERE)) {
//			LogEntry entry = ValidationPlugin.getLogEntry();
//			entry.setSourceID("ValidationOperation::launchValidator"); //$NON-NLS-1$
//			entry.setTargetException(exc);
//			logger.write(Level.SEVERE, entry);
//		}
//		String[] msgParm = {exc.getClass().getName(), vmd.getValidatorDisplayName(), (exc.getMessage() == null ? "" : exc.getMessage())}; //$NON-NLS-1$
//		Message message = ValidationPlugin.getMessage();
//		message.setSeverity(IMessage.NORMAL_SEVERITY);
//		message.setId(ResourceConstants.VBF_EXC_RUNTIME);
//		message.setParams(msgParm);
//		try {
//			reporter.addMessage(vmd.getValidator(), message);
//		} catch (InstantiationException exc2) {
//			handleInstantiationException(vmd, logger, exc2);
//		} catch (MessageLimitException e) {
//			throw e;
//		}
//		return;
//	}

	public boolean isFork() {
		return _fork;
	}

	public boolean isForce() {
		return _force;
	}

	public void setForce(boolean force) {
		_force = force;
	}

	/**
	 * If the code that invoked this operation suspended auto-build before invoking this operation,
	 * the user's auto-build setting is stored in the following methods.
	 */
	public boolean isAutoBuild() {
		if (_isAutoBuild == null) {
			return ValidatorManager.getManager().isGlobalAutoBuildEnabled();
		}
		return _isAutoBuild.booleanValue();
	}

	protected void setAutoBuild(boolean autoOn) {
		_isAutoBuild = ((autoOn) ? Boolean.TRUE : Boolean.FALSE);
	}

	protected boolean isFullValidate() {
		return _isFullValidate;
	}

	private void setFullValidate(boolean b) {
		_isFullValidate = b;
	}

	protected int getRuleGroup() {
		return _ruleGroup;
	}

	/**
	 * Return true if the given validator must run (i.e., it has changes to validate, and it was not
	 * run automatically.)
	 */
	private boolean isValidationNecessary(ValidatorMetaData vmd, IFileDelta[] delta) {
		// Validation is not necessary if there are no files for the validator to validate.
		return isFullValidate() || (delta.length > 0);
	}

	/**
	 * Return true if, given the enabled validators and file deltas, there is work for this
	 * operation to do.
	 */
	public boolean isNecessary(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
		Set enabledValidators = getEnabledValidators();
		if ((enabledValidators == null) || (enabledValidators.size() == 0)) {
			return false;
		}
		if (isFullValidate()) {
			return true;
		}
		Iterator iterator = enabledValidators.iterator();
		while (iterator.hasNext()) {
			ValidatorMetaData vmd = (ValidatorMetaData) iterator.next();
			if (isValidationNecessary(vmd, getFileDeltas(monitor, vmd))) {
				return true;
			}
		}
		return false;
	}

	private Map<ValidatorMetaData, Set<IFileDelta>> getFileDeltas(IProgressMonitor monitor) throws CoreException {
		if (_fileDeltas == null)loadFileDeltas(monitor);
		return _fileDeltas;
	}

	private IFileDelta[] getFileDeltas(IProgressMonitor monitor, ValidatorMetaData vmd) throws CoreException {
		Set<IFileDelta> result = getFileDeltas(monitor).get(vmd);
		if (result == null)return new IFileDelta[0];
		
		IFileDelta[] temp = new IFileDelta[result.size()];
		result.toArray(temp);
		return temp;
	}

	/**
	 * Store the file deltas (VMD <=>Set[IFileDelta]) if the file deltas haven't been loaded. If the
	 * deltas have already been loaded, return without doing anything.
	 */
	private void loadFileDeltas(IProgressMonitor monitor) throws CoreException {
		// Although, for a full build, we don't build up a list of changed
		// files, we do need to notify each IWorkbenchContext that an
		// IResource has been filtered in.
		// It's a full validation if the IResourceDelta is null and the
		// Object[] (or IResource[]) is also null.
		// i.e., it's a full validation if no incremental input has been set.
		setFullValidate((getDelta() == null) && (_fileDeltas == null));
		if (isFullValidate()) {
			_fileDeltas = FilterUtil.loadDeltas(monitor, getEnabledValidators(), getProject());
		} else {
			_fileDeltas = FilterUtil.loadDeltas(monitor, getEnabledValidators(), getDelta()); // traverse,
			// and process, each resource in the delta tree
		}
	}

	protected void setFileDeltas(Map<ValidatorMetaData, Set<IFileDelta>> deltas) {
		_fileDeltas = deltas;
	}

	protected IResourceDelta getDelta() {
		return _delta;
	}

	protected void setDelta(IResourceDelta delta) {
		_delta = delta;
	}

	protected boolean areValidatorsEnabled() {
		return (getEnabledValidators().size() != 0);
	}

	/**
	 * Return the validators which are both configured on this type of project, (as stored in
	 * getProject()), and enabled by the user on this project.
	 */
	public Set<ValidatorMetaData> getEnabledValidators() {
		return _enabledValidators;
	}

	/**
	 * This is an internal method, subject to change without notice. It is provided only for the
	 * automated validation framework tests.
	 */
	public Set<ValidatorMetaData> getLaunchedValidators() {
		if (_launchedValidators == null) {
			_launchedValidators = new HashSet<ValidatorMetaData>();
		}
		return _launchedValidators;
	}

	protected void setEnabledValidators(Set evmds) {
		// Check that every VMD in the set is configured on this project.
		// Necessary because the user can manually choose which validators
		// to launch, and the validator may not be installed.
		_enabledValidators.clear();
		Iterator iterator = evmds.iterator();
		while (iterator.hasNext()) {
			ValidatorMetaData vmd = (ValidatorMetaData) iterator.next();
			if (ValidationRegistryReader.getReader().isConfiguredOnProject(vmd, getProject())) {
				_enabledValidators.add(vmd);
			}
		}
	}

	/**
	 * This method returns the IProject that this ValidationOperation was created with.
	 */
	public IProject getProject() {
		return _project;
	}

	protected int getUnitsOfWork() {
		/*
		 * // Let one unit of work equal one resource. number of enabled validators // i.e., each
		 * enabled validator must process (at most) each resource in the project; count each process
		 * as one unit of work // Note that this is a ceiling number, because if we're doing an
		 * incremental validation, not all resources will // be validated.
		 * setNumResources(countResources(getProject())); getEnabledValidators().size();
		 */
		// Until the validators can report units-of-work complete,
		// initialize the monitor with an unknown amount of work.
		// (So the user will see movement in the progress bar, even
		// if the movement doesn't indicate the amount of work done.)
		return IProgressMonitor.UNKNOWN;
	}

	/**
	 * If the user is cancelling validation on the current project/resource, Add an information task
	 * to the task list informing the user that validation has not been run on the current project.
	 */
	protected void addCancelTask(ValidatorMetaData vmd) {
		InternalValidatorManager.getManager().addOperationTask(getProject(), vmd, ResourceConstants.VBF_STATUS_VALIDATOR_TERMINATED, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
	}

	/**
	 * This method starts the validation of each configured enabled validator on the current
	 * project.
	 * 
	 * The IProgressMonitor passed in must not be null.
	 */
	public void run(IProgressMonitor progressMonitor) throws OperationCanceledException {
		try {
			// In order to check whether or not the monitor has been canceled, the monitor must not be null.
			if (progressMonitor == null)return;
			IProject project = getProject();
			if (ValidationFramework.getDefault().isSuspended(project))return;
			if (ValManager.getDefault().isDisabled(project))return;
			
			if (!areValidatorsEnabled()) {
				// save some processing time...
				return;
			}
			
			final WorkbenchReporter reporter = new WorkbenchReporter(getProject(), progressMonitor);

			try {
				// Periodically check if the user has canceled the operation
				checkCanceled(reporter);
				preValidate(reporter);
				validate(reporter);
				validateReferencialFiles(reporter);
			} catch (CoreException e) {
				ValidationPlugin.getPlugin().handleException(e);
			}
		} finally {
			//TODO GRK determine if timing info should be added here
//			if (logger.isLoggingLevel(Level.FINE)) {
//				long finish = System.currentTimeMillis();
//				TimeEntry entry = ValidationPlugin.getTimeEntry();
//				entry.setSourceID("ValidationOperation.run(WorkbenchMonitor)"); //$NON-NLS-1$
//				entry.setProjectName(getProject().getName());
//				entry.setToolName("ValidationOperation"); //$NON-NLS-1$
//				entry.setElapsedTime(finish - start);
//				logger.write(Level.FINE, entry);
//			}
		}
	}

	private void validateReferencialFiles(WorkbenchReporter reporter) {
		ReferencialFileValidatorRegistryReader reader = ReferencialFileValidatorRegistryReader.getInstance();
		if (reader != null) {
			reader.readRegistry();
			ReferencialFileValidator refFileValidator = reader.getReferencialFileValidator();
			if (refFileValidator != null) {
				if (_delta != null) {
					refFileValidateFileDelta(reporter, refFileValidator);
				} else if (_project != null) {
					postValidateProject(reporter, refFileValidator);
				}
			}
		}
	}

	/**
	 * @param reporter
	 * @param referencialFileValidator
	 */
	private void refFileValidateFileDelta(WorkbenchReporter reporter, ReferencialFileValidator refFileValidator) {
		IResourceDelta[] resourceDelta = _delta.getAffectedChildren(IResourceDelta.ADDED | IResourceDelta.CHANGED | IResourceDelta.REMOVED);
		List<IResource> inputFiles = new ArrayList<IResource>();
		
		List<IFile> referencingFiles = new ArrayList<IFile>();
		if (resourceDelta != null && resourceDelta.length > 0) {
			for (int i = 0; i < resourceDelta.length; i++) {
				IResource resource = resourceDelta[i].getResource();
				if (resource instanceof IFolder) {
					getFileResourceDeltaInFolder(resourceDelta[i], inputFiles);
				} else if (resource instanceof IFile)
					inputFiles.add(resource);
			}
			List<IFile> rFilesToValidate = refFileValidator.getReferencedFile(inputFiles);
			if (rFilesToValidate != null && !rFilesToValidate.isEmpty())
				referencingFiles.addAll(rFilesToValidate);
			try {
				if (!referencingFiles.isEmpty())
					validateReferencingFiles(reporter, referencingFiles);
			} catch (Exception e) {
				ValidationPlugin.getPlugin().handleException(e);
			}
		}
	}

	/**
	 * @param delta
	 * @return
	 */
	private void getFileResourceDeltaInFolder(IResourceDelta delta, List<IResource> inputFiles) {
		IResourceDelta[] resourceDelta = delta.getAffectedChildren();
		for (int i = 0; i < resourceDelta.length; i++) {
			IResource resource = resourceDelta[i].getResource();
			if (resource instanceof IFile)inputFiles.add(resource);
			else if (resource instanceof IFolder)getFileResourceDeltaInFolder(resourceDelta[i], inputFiles);
		}
	}

	/**
	 * @param reporter
	 * @param referencialFileValidator
	 */
	private void postValidateProject(WorkbenchReporter reporter, ReferencialFileValidator refFileValidator) {
		Set set = ValidationRegistryReader.getReader().getValidatorMetaData(_project);
		Iterator it = set.iterator();
		while (it.hasNext()) {
			ValidatorMetaData data = (ValidatorMetaData) it.next();
			List filters = data.getNameFilters();
			List files = getAllFilesForFilter(filters);
			if (!files.isEmpty()) {
				List<IFile> fileForValidation = refFileValidator.getReferencedFile(files);
				try {
					validateReferencingFiles(reporter, fileForValidation);
				} catch (Exception e) {
					ValidationPlugin.getPlugin().handleException(e);
				}
			}
		}
	}

	/**
	 * @param filters
	 * @return
	 */
	private List<IFile> getAllFilesForFilter(List filters) {
		if (!filters.isEmpty()) {
			List allProjectFiles = ReferencialFileValidatorHelper.getAllProjectFiles(_project);
			List<IFile> filterFiles = new ArrayList<IFile>();
			for (int i = 0; i < filters.size(); i++) {
				String fileName = (String) filters.get(i);
				if (fileName == null)
					continue;
				for (int j = 0; j < allProjectFiles.size(); j++) {
					IFile projectFile = (IFile) allProjectFiles.get(j);
					if (fileName.charAt(0) == '*') {
						String extName = fileName.substring(2, fileName.length());
						String ext = projectFile.getFileExtension();
						if (ext != null && ext.equals(extName))
							filterFiles.add(projectFile);
					} else if (fileName.equals(projectFile.getName()))
						filterFiles.add(projectFile);
				}

			}
			return filterFiles;
		}
		return new LinkedList<IFile>();
	}

	private void validateReferencingFiles(IReporter reporter, List<IFile> referencingFiles) throws Exception {
		Set<IFile> validatedFiles = new HashSet<IFile>();
		for (IFile refFile : referencingFiles) {
			if (!validatedFiles.contains(refFile)) {
				IResource resource = refFile.getParent();
				IProject project = null;
				if (resource != null && !(resource instanceof IProject))
					project = getProjectContainer(resource);
				else
					project = (IProject) resource;
				if (project != null) {
					Set<ValidatorMetaData> set = ValidationRegistryReader.getReader().getValidatorMetaData(project);
					for (ValidatorMetaData data : set) {
						if (data.isApplicableTo(refFile)) {
							IValidator validator = data.getValidator();
							validator.validate(data.getHelper(project),reporter);
							validatedFiles.add(refFile);
						}
					}
				}
			}
		}
	}

	private IProject getProjectContainer(IResource resource) {
		IResource pResource = resource.getParent();
		if (!(pResource instanceof IProject))
			return getProjectContainer(pResource);
		return (IProject) pResource;
	}

	protected void preValidate(WorkbenchReporter reporter) throws CoreException, OperationCanceledException {
		// Load the input.
		getFileDeltas(reporter.getProgressMonitor());
	}

	/**
	 * Iterate over all of the enabled validators and run the thread-safe validators in a background
	 * thread, and the not-thread-safe validators in this thread.
	 */
	protected void validate(WorkbenchReporter reporter) throws OperationCanceledException {
		if (reporter == null)return;
		checkCanceled(reporter);
		reporter.getProgressMonitor().beginTask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_PROGRESSMONITOR_TITLE), getUnitsOfWork());
		IValidator validator = null;
		Iterator iterator = null;
		IFileDelta[] delta = null;
		
		Set<ValidatorMetaData> jobValidators = new HashSet<ValidatorMetaData>();
		Set<ValidatorMetaData> validators = new HashSet<ValidatorMetaData>();
				
		for(ValidatorMetaData vmd : getEnabledValidators()){
			IValidator valInstance = null;
			try {
				valInstance = vmd.getValidator();
			} 
			catch (InstantiationException e1) {
				if(!ValidatorManager.getManager().getProblemValidators().contains(vmd)) {
					ValidatorManager.getManager().getProblemValidators().add(vmd);
					System.out.println(e1.getMessage());
				}
			}
			
			if( isFork() && (valInstance != null) && valInstance instanceof IValidatorJob ){
				try {
					delta = getFileDeltas(reporter.getProgressMonitor(), vmd);
				} catch (CoreException e) {
					e.printStackTrace();
				}
				boolean willRun = (isForce() || isValidationNecessary(vmd, delta));
				if( willRun )jobValidators.add( vmd );
			}
			else if (valInstance != null){
				validators.add( vmd );
			}
		}
		if( jobValidators.size() > 0 ){
			launchJobs( jobValidators, reporter );
		}
				
		ValidatorMetaData currentVmd = null;
		try {
			for (ValidatorMetaData vmd : validators) {
				currentVmd = vmd;
				// Is validation about to be run on this validator?
				// Validation will run either if this operation forces regardless
				// of need, or if the validator was not run automatically.
				// If validation is not about to be run, then don't activate
				// the plug-in
				try {
					delta = getFileDeltas(reporter.getProgressMonitor(), vmd);
					boolean willRun = (isForce() || isValidationNecessary(vmd, delta));
					if (Tracing.isTraceV1()) {
						StringBuffer buffer = new StringBuffer();
						buffer.append("ValidationOperation: will run? "); //$NON-NLS-1$
						buffer.append(willRun);
						buffer.append("  "); //$NON-NLS-1$
						buffer.append("is force? "); //$NON-NLS-1$
						buffer.append(isForce());
						buffer.append("  "); //$NON-NLS-1$
						buffer.append("isAutoBuild? "); //$NON-NLS-1$
						buffer.append(_isAutoBuild);
						buffer.append("  "); //$NON-NLS-1$
						buffer.append("isAutoValidate? "); //$NON-NLS-1$
						buffer.append("  "); //$NON-NLS-1$
						buffer.append("isIncremental? "); //$NON-NLS-1$
						buffer.append(vmd.isIncremental());
						buffer.append("  "); //$NON-NLS-1$
						if (isFullValidate()) {
							buffer.append("EVERYTHING"); //$NON-NLS-1$
						} else {
							if (delta.length == 0) {
								buffer.append("NOTHING"); //$NON-NLS-1$
							} else {
								buffer.append(getDeltaAsString(delta));
							}
						}
						Tracing.log(buffer);
					}
					if (!willRun) {
						continue;
					}
				} catch (CoreException e) {
					ValidationPlugin.getPlugin().handleException(e);
					String mssg = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
					reporter.displaySubtask(mssg);
					continue;
				}
				try {
					context = vmd.getHelper(getProject());
					initValidateContext(delta);
					validator = vmd.getValidator();
					
					checkCanceled(reporter);
					
				} catch (InstantiationException e) {
					// Remove the vmd from the reader's list
					ValidationRegistryReader.getReader().disableValidator(vmd);
					ValidationPlugin.getPlugin().handleException(e);
					continue;
				}
				
//				if (isFork() && vmd.isAsync()) {
//					// Don't appear to run in the foreground by sending
//					// progress to the IProgressMonitor in the
//					// WorkbenchMonitor. Suppress the status messages by
//					// changing the IProgressMonitor to a
//					// NullProgressMonitor.
//					VThreadManager.getManager().queue(wrapInRunnable(nullReporter, validator, vmd,(WorkbenchContext)getContext(),delta, iterator));
//				} else {
//					internalValidate(reporter, validator, vmd, context, delta);
//				}
				internalValidate(reporter, validator, vmd, context, delta);
			}
		} 
		catch (OperationCanceledException exc) {
			handleOperationCancelledValidateException(reporter, validator, currentVmd, iterator, exc);
		} 
		finally {
			releaseCachedMaps();
		}
	}

	private void releaseCachedMaps() {
		if (ValidationRegistryReader.getReader().projectValidationMetaData != null) {
			ValidationRegistryReader.getReader().projectValidationMetaData.clear();
			ValidationRegistryReader.getReader().projectValidationMetaData = null;
		}
		IProjectValidationHelper helper = ValidationHelperRegistryReader.getInstance().getValidationHelper();
		if (helper != null)
			helper.disposeInstance();
	}

	private void initValidateContext(IFileDelta[] delta) {
		 if (context instanceof WorkbenchContext) {
			 ((WorkbenchContext)context).setValidationFileURIs(new ArrayList<String>());
			 for(IFileDelta file : delta) {
				 if(file.getDeltaType() != IFileDelta.DELETED ) {
					 ((WorkbenchContext)context).getValidationFileURIs().add(file.getFileName());
				 }
			 } 
		}
	}

	/**
	 * @param reporter
	 * @param validator
	 * @param vmd
	 * @param iterator
	 * @param logger
	 * @param exc
	 */
	private void handleOperationCancelledValidateException(WorkbenchReporter reporter, IValidator validator, ValidatorMetaData vmd, Iterator iterator, OperationCanceledException exc) {
		/*
		 * If the user terminates validation (i.e., presses "cancel" on the progress monitor) before
		 * the validation completes, perform clean up on each configured enabled validator.
		 * 
		 * To clean up, several steps are performed: 1. call <code></code> on each configured
		 * enabled validator, so that each validator can perform cleanup that it knows is necessary.
		 * 2. remove all tasks that this validator has added to the task list 3. add another task to
		 * the task list to say that validation, using this validator on this project, was
		 * terminated.
		 * 
		 * Steps 2 and 3 are done so that it's clear what has, and has not, been validated. If these
		 * steps weren't performed, validation could be done on some items in the project, but not
		 * others; and the user could mistakenly believe that those are the only problems with the
		 * project. Unless the user knows that a full verification needs to be done, he/she could
		 * continue to rely on automatic verification, and never know that there are problems with a
		 * resource which hasn't been validated.
		 */
		reporter.displaySubtask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_VALIDATOR_CLEANUP, new String[]{vmd.getValidatorDisplayName()}));
		reporter.removeAllMessages(validator);
		addCancelTask(vmd);
		reporter.displaySubtask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_VALIDATOR_TERMINATED, new String[]{getProject().getName(), vmd.getValidatorDisplayName()}));
		while (iterator.hasNext()) {
			vmd = (ValidatorMetaData) iterator.next();
			try {
				validator = vmd.getValidator();
			} catch (InstantiationException exc2) {
				// Remove the vmd from the reader's list
				ValidationRegistryReader.getReader().disableValidator(vmd);
				ValidationPlugin.getPlugin().handleException(exc2);
				continue;
			}
			reporter.displaySubtask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_VALIDATOR_CLEANUP, new String[]{vmd.getValidatorDisplayName()}));
			reporter.removeAllMessages(validator);
			addCancelTask(vmd);
			reporter.displaySubtask(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_VALIDATOR_TERMINATED, new String[]{getProject().getName(), vmd.getValidatorDisplayName()}));
		}
		throw exc; // propagate the exception up to the framework so that
		// the framework can display the correct "canceled"
		// message in the dialog

	}

	/* package */
	void internalValidate(final WorkbenchReporter reporter, final IValidator validator, final ValidatorMetaData vmd,final IWorkbenchContext aContext, final IFileDelta[] delta) throws OperationCanceledException {
		try {
			checkCanceled(reporter);
			removeOldMessages(reporter, validator, vmd, delta);
			// Do NOT check if the message limit is exceeded before launching
			// the validator.
			// Even if the limit is exceeded when the messages are removed from
			// the delta
			// files, it could be that the validator itself will remove
			// messages before
			// proceeding. Let the validator run so that it can remove messages
			// if it
			// needs to, and if it tries to add a message when the limit is
			// exceeded, let
			// the WorkbenchReporter take care of it.
			launchValidator(reporter, validator, vmd, aContext, delta);
		} catch (OperationCanceledException exc) {
			// This is handled in the validate(WorkbenchReporter) method.
			throw exc;
		}catch (Exception e) {
			// If there is a problem with this particular validator, log the
			// error and continue with the next validator.
			// If a runtime exception has occurred, e.g. NullPointer or
			// ClassCast, display it with the "A runtime exception has occurred" message.
			// This will provide more information to the user when he/she calls Service.
			ValidationPlugin.getPlugin().handleException(e);
			String mssg = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
			reporter.displaySubtask(mssg);
			
			/*
			 The code  below  causes bundle not found exception since, the  bundle here is
			 validate_base and we  are  trying to load that bundle from the classloader of 
			 the Validator. 
			  
			String[] msgParm = {exc.getClass().getName(), vmd.getValidatorDisplayName(), (exc.getMessage() == null ? "" : exc.getMessage())}; //$NON-NLS-1$
			Message message = ValidationPlugin.getMessage();
			message.setSeverity(IMessage.NORMAL_SEVERITY);
			message.setId(ResourceConstants.VBF_EXC_RUNTIME);
			message.setParams(msgParm);
			reporter.addMessage(validator, message);
			*/
		} finally {
			// If user fixes problem, and limit exceeded, add "exceeded"
			// message, or
			// if limit not exceeded any more, remove "exceeded" message.
			//Message Limit is removed from the framework
			//ValidatorManager.getManager().checkMessageLimit(getProject(), true);
			reporter.getProgressMonitor().done();
		}
	}

	/**
	 * In order to allow validators to run, must first check if there's space for new markers. But
	 * the old markers must not prevent validation from running again (limit exceeded), so delete
	 * all of the old markers first, and then run validation.
	 */
	private final void removeOldMessages(WorkbenchReporter reporter, IValidator validator, ValidatorMetaData vmd, IFileDelta[] delta) {
		if (reporter == null) {
			return;
		}
		// If the validator has been enabled, remove the "cancel" task.
		// If the validator, on the last run, threw a Throwable, remove the
		// "internal error" task. (For the same reasons we remove the "cancel"
		// task.
		InternalValidatorManager.getManager().removeOperationTasks(getProject(), vmd);
		checkCanceled(reporter);
		try {
			// Check to see if a full build must be performed, or if a delta
			// build is to be performed, if there are files to verify for that
			// validator. (If it's delta, but there are no files, calling
			// validate on that validator starts a full build, instead of just
			// returning.)
			if (isFullValidate()) {
				String message = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_START_REMOVING_OLD_MESSAGES, new String[]{vmd.getValidatorDisplayName(), getProject().getName()});
				reporter.displaySubtask(message);
				reporter.removeAllMessages(validator);
				message = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_FINISH_REMOVING_OLD_MESSAGES, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
				reporter.displaySubtask(message);
			} else {
				// Don't need to check that there are deltas to validate
				// because that's already checked in isValidationNecessary
				String message = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_START_REMOVING_OLD_MESSAGES, new String[]{vmd.getValidatorDisplayName(), getProject().getName()});
				reporter.displaySubtask(message);
				for (int i = 0; i < delta.length; i++) {
					WorkbenchFileDelta fd = (WorkbenchFileDelta) delta[i];
					if (fd.getDeltaType() != IFileDelta.DELETED) {
						// If the file has been deleted, eclipse erases all
						// markers on the file.
						// Also, when a resource doesn't exist,
						// WorkbenchReporter's getMessageResource()
						// returns the IProject, which means that removing the
						// messages from this
						// file removes all of this validator's messages on
						// this IProject (aix defect 206157)
						IResource resource = reporter.getMessageResource(validator, fd);
						if (fd.getObject().equals(fd.getResource())) {
							WorkbenchReporter.removeAllMessages(resource, validator); // remove
						} else {
							reporter.removeAllMessages(validator, fd.getObject());
						}
					}
				}
				message = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_FINISH_REMOVING_OLD_MESSAGES, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
				reporter.displaySubtask(message);
			}
		} catch (OperationCanceledException exc) {
			throw exc;
		} catch (Exception e) {
			ValidationPlugin.getPlugin().handleException(e);
			String mssg = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
			reporter.displaySubtask(mssg);
			return;
		}
	}

	/**
	 * 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.)
	 */
	private final void launchValidator(WorkbenchReporter reporter, IValidator validator, ValidatorMetaData vmd, IWorkbenchContext helper, IFileDelta[] delta) {
		if (reporter == null)return;
		checkCanceled(reporter);
		// Check to see if a full build must be performed, or if a delta
		// build is to be performed, if there are files to verify for that
		// validator. (If it's delta, but there are no files, calling
		// validate on that validator starts a full build, instead of just
		// returning.)
		try {
			// Validate the resource; this step will add errors/warnings to the
			// task list, and remove errors/warnings from the task list.
			if (helper instanceof WorkbenchContext) {
				// Initialize the "loadRuleGroup" method with the group of rules
				// which the validator should validate.
				((WorkbenchContext) helper).setRuleGroup(getRuleGroup());
			}
			String message = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_STARTING_VALIDATION, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
			reporter.displaySubtask(message);
			if (Tracing.isLogging()) {
				// This internal "launched validators" value is used only in tests.
				getLaunchedValidators().add(vmd);
			}
			//initValidateContext(delta);
			ValidatorLauncher.getLauncher().start(helper, validator, reporter);
			//TODO GRK determine if timing info should be added here
//			if (logger.isLoggingLevel(Level.INFO)) {
//				TimeEntry entry = ValidationPlugin.getTimeEntry();
//				entry.setSourceID("ValidationOperation.launchValidator"); //$NON-NLS-1$
//				entry.setProjectName(getProject().getName());
//				entry.setToolName(vmd.getValidatorUniqueName());
//				entry.setElapsedTime(finish - start);
//				if (logger.isLoggingLevel(Level.FINE)) {
//					StringBuffer buffer = new StringBuffer();
//					if (isFullValidate()) {
//						buffer.append("EVERYTHING"); //$NON-NLS-1$
//					} else {
//						if (delta.length == 0) {
//							buffer.append("NOTHING"); //$NON-NLS-1$
//						} else {
//							buffer.append(getDeltaAsString(delta));
//						}
//					}
//					entry.setDetails(buffer.toString());
//				}
//				logger.write(Level.INFO, entry);
//			}
			message = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
			reporter.displaySubtask(message);
		} catch (OperationCanceledException exc) {
			throw exc;
		} catch (ValidationException exc) {
			// First, see if a validator just caught all Throwables and
			// accidentally wrapped a MessageLimitException instead of
			// propagating it.
			if (exc.getAssociatedException() != null) {
				if (exc.getAssociatedException() instanceof ValidationException) {
					ValidationException vexc = (ValidationException) exc.getAssociatedException();
					vexc.setClassLoader(validator.getClass().getClassLoader()); // first,
					// set the class loader, so that the exception's getMessage() method
					// can retrieve the resource bundle
				}
			}
			// If there is a problem with this particular validator, log the
			// error and continue with the next validator.
			exc.setClassLoader(validator.getClass().getClassLoader()); // first,
			ValidationPlugin.getPlugin().handleException(exc);
			ValidationPlugin.getPlugin().handleException(exc.getAssociatedException());
			String message = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
			reporter.displaySubtask(message);
			if (exc.getAssociatedMessage() != null) {
				reporter.addMessage(validator, exc.getAssociatedMessage());
			}
		} catch (Exception e) {
			ValidationPlugin.getPlugin().handleException(e);
			String mssg = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
			reporter.displaySubtask(mssg);
			
			/*
			 The code  below  causes bundle not found exception since, the  bundle here is
			 validate_base and we  are  trying to load that bundle from the classloader of 
			 the Validator. 
			 
			String[] msgParm = {exc.getClass().getName(), vmd.getValidatorDisplayName(), (exc.getMessage() == null ? "" : exc.getMessage())}; //$NON-NLS-1$
			Message message = ValidationPlugin.getMessage();
			message.setSeverity(IMessage.NORMAL_SEVERITY);
			message.setId(ResourceConstants.VBF_EXC_RUNTIME);
			message.setParams(msgParm);
			reporter.addMessage(validator, message);
			*/
			
		} finally {
			try {
				validator.cleanup(reporter);
			} catch (OperationCanceledException e) {
				throw e;
			} catch (Exception e) {
				ValidationPlugin.getPlugin().handleException(e);
				return;
			}
			try {
				helper.cleanup(reporter);
			} catch (OperationCanceledException e) {
				throw e;
			} catch (Exception e) {
				ValidationPlugin.getPlugin().handleException(e);
				return;
			} finally {
				// Now that cleanup has been called, set the project to null.
				// This project's
				// resources have been freed so this project should also be
				// cleared on the helper.
				// If it isn't set to null, then the next time that the helper
				// is retrieved from
				// the ValidatorMetaData, the resources allocated for this
				// project, in the
				// helper's initialize method, will not be reallocated if the
				// project is the same.
				helper.setProject(null);
			}
			// Tell the progress monitor that we've completed n units of work
			// (i.e., n resources validated by one validator).
			reporter.getProgressMonitor().worked(((delta == null) ? 1 : delta.length));
		}
	}

//	private Runnable wrapInRunnable(final WorkbenchReporter reporter, final IValidator validator, final ValidatorMetaData vmd, final IWorkbenchContext helper, final IFileDelta[] delta, final Iterator iterator) {
//		// Need to create a new Runnable each time because several Runnable
//		// instances may exist at the same time.
//		Runnable runnable = new ProjectRunnable(reporter, validator, vmd, helper, delta, iterator);
//		return runnable;
//	}

	/*
	 * // For convenience, keep this method in the class but commented out. // When async needs to
	 * be tested, this method may be needed again. private static void debug(String prefix,
	 * IWorkbenchContext helper) { IProject hProject = helper.getProject(); System.err.println(prefix +
	 * "Start ValidationOperation "+Thread.currentThread().getName() + "::" + hProject.getName());
	 * if( Thread.currentThread().getName().equals("ValidationThread") &&
	 * (hProject.getName().indexOf("noFork") > -1)) { Thread.dumpStack(); } else
	 * if((!Thread.currentThread().getName().equals("ValidationThread")) &&
	 * (hProject.getName().indexOf("fork") > -1)) { Thread.dumpStack(); } System.err.println(prefix +
	 * "End ValidationOperation"); }
	 */
	public class ProjectRunnable implements Runnable {
		private WorkbenchReporter _reporter = null;
		private IValidator _validator = null;
		private ValidatorMetaData _vmd = null;
//		private IValidationContext _helper = null;
		private IFileDelta[] __delta = null;

		public ProjectRunnable(WorkbenchReporter reporter, IValidator validator, ValidatorMetaData vmd, IWorkbenchContext helper, IFileDelta[] delta, Iterator iterator) {
			_reporter = reporter;
			_validator = validator;
			_vmd = vmd;
//			_helper = helper;
			__delta = delta;
		}

		public void run() {
			try {
				internalValidate(_reporter, _validator, _vmd, context,__delta);
			} catch (OperationCanceledException exc) {
				// User can't cancel a job in a background thread, so ignore this exception.
			}
		}

		public IProject getProject() {
			return _reporter.getProject();
		}
	}

	/**
	 * @return Returns the context.
	 */
	public IValidationContext getContext() {
		return context;
	}

	/**
	 * @param context The context to set.
	 */
	public void setContext(IWorkbenchContext context) {
		this.context = context;
	}
	
	void launchJobs(Set<ValidatorMetaData> validators, final WorkbenchReporter reporter) throws OperationCanceledException{
		
		IValidator validator = null;
		IFileDelta[] delta = null;
		IWorkbenchContext workbenchcontext = null;
		
		for (ValidatorMetaData vmd : validators) {
			checkCanceled(reporter);
			
			try {
				delta = getFileDeltas(reporter.getProgressMonitor(), vmd);
				boolean willRun = (isForce() || isValidationNecessary(vmd, delta));
				if (!willRun)continue;

			} catch (CoreException e) {
				ValidationPlugin.getPlugin().handleException(e);
				String mssg = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
				reporter.displaySubtask(mssg);
				continue;
			}
			
			try {
				validator = vmd.createValidator();
				workbenchcontext = vmd.createHelper( getProject() );
				initValidateContext( delta, workbenchcontext );
				vmd.addHelper((IValidatorJob)validator, workbenchcontext);				
				checkCanceled(reporter);
				
			} catch (InstantiationException e) {
				// Remove the vmd from the reader's list
				ValidationRegistryReader.getReader().disableValidator(vmd);
				ValidationPlugin.getPlugin().handleException(e);
				continue;
			}
			
			try {
				checkCanceled(reporter);
				removeOldMessages(reporter, validator, vmd, delta);
				
				if( validator instanceof IValidatorJob ){
					launchValidatorJob( reporter, (IValidatorJob)validator, vmd, workbenchcontext, delta);
				}

				
			} catch (OperationCanceledException exc) {
				throw exc;

			} catch (Exception e) {
				ValidationPlugin.getPlugin().handleException(e);
				String mssg = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
				reporter.displaySubtask(mssg);
			} catch (Error e) {
				ValidationPlugin.getPlugin().handleException(e);
				String mssg = ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_STATUS_ENDING_VALIDATION_ABNORMALLY, new String[]{getProject().getName(), vmd.getValidatorDisplayName()});
				reporter.displaySubtask(mssg);
				throw e;
			} finally {
				// If user fixes problem, and limit exceeded, add "exceeded"
				// message, or if limit not exceeded any more, remove "exceeded" message.
				reporter.getProgressMonitor().done();
			}
		}
	}
		
	private void initValidateContext(IFileDelta[] delta, IWorkbenchContext context ) {
		 if (context instanceof WorkbenchContext) {
			 ((WorkbenchContext)context).setValidationFileURIs(new ArrayList<String>());
			 for(IFileDelta file : delta) {
				 if(file.getDeltaType() != IFileDelta.DELETED ) {
					 ((WorkbenchContext)context).getValidationFileURIs().add(file.getFileName());
				 }
			 } 
		}
	}
						
	private final void launchValidatorJob(WorkbenchReporter reporter,
		IValidatorJob validator, ValidatorMetaData vmd, IWorkbenchContext helper, IFileDelta[] delta) {
		
		if (reporter == null)return;
		checkCanceled(reporter);

		if (helper instanceof WorkbenchContext) {
			((WorkbenchContext) helper).setRuleGroup(getRuleGroup());
		}
		if (Tracing.isLogging()) {
			// This internal "launched validators" value is used only in tests.
			getLaunchedValidators().add(vmd);
		}
		
		ValidatorJob validatorjob = new ValidatorJob( validator, vmd.getValidatorDisplayName(), 
			vmd.getValidatorUniqueName(), helper.getProject(), helper );

		ISchedulingRule schedulingRule = validator.getSchedulingRule(helper);
		validatorjob.setRule( schedulingRule );		
		QualifiedName validatorKey = new QualifiedName(null, "Validator"); //$NON-NLS-1$
		validatorjob.setProperty( validatorKey, validator );
		validatorjob.addJobChangeListener(
			new JobChangeAdapter(){
				
				public void done(IJobChangeEvent event){
					Job job = event.getJob();
					QualifiedName validatorKey = new QualifiedName(null, "Validator"); //$NON-NLS-1$
					IValidatorJob validator = (IValidatorJob)job.getProperty( validatorKey );
					ValidatorManager mgr = ValidatorManager.getManager();
					final List<MessageInfo> list = mgr.getMessages(validator);							
					
					IWorkspaceRunnable runnable = new IWorkspaceRunnable() {
					    public void run(IProgressMonitor monitor) throws CoreException {

							for(MessageInfo info : list){
								try {								
									TaskListUtility.addTask( info.getMessageOwnerId(), info.getResource(),
										info.getLocation(), info.getMsg().getId(), info.getText(),
										info.getMsg().getSeverity(),
										info.getMarkerId(),
										info.getTargetObjectName(),
										info.getMsg().getGroupName(),
										info.getMsg().getOffset(),
										info.getMsg().getLength());								
								} catch (CoreException e) {
									ValidationPlugin.getPlugin().handleException(e);
								}										
							}
					    }
					};
					try {
						
						ResourcesPlugin.getWorkspace().run(runnable, null, IWorkspace.AVOID_UPDATE, null);
					} catch (CoreException e) {
					   e.printStackTrace();
					}
					mgr.clearMessages( validator );
					validator = null;
				}
			}
		);
		validatorjob.setPriority(Job.DECORATE);

		ValidationLauncherJob validationLauncherJob = new ValidationLauncherJob(validatorjob);
		validationLauncherJob.schedule();
	}
		
}
