org.eclipse.wst.validation.internal.operations.ValidationOperation Maven / Gradle / Ivy
/*******************************************************************************
* Copyright (c) 2001, 2009 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.Queue;
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;
/**
* Validators 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.
*
* 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;
private static ValidationLauncherJob launcherJob = new ValidationLauncherJob();
private static final int jobsPerProcessor = 3;
private final static class ValidationLauncherJob extends Job {
private Queue _validationJobs = new LinkedList();
public ValidationLauncherJob() {
super(ResourceHandler.getExternalizedMessage(ResourceConstants.VBF_VALIDATION_JOB_MSG));
setSystem(true);
setRule(ResourcesPlugin.getWorkspace().getRoot());
}
protected IStatus run(IProgressMonitor monitor) {
int processors = Runtime.getRuntime().availableProcessors();
int totalInitialJobs = processors * jobsPerProcessor;
synchronized (_validationJobs) {
// never schedule more than 3 validation jobs per processor at a time
for (int i=0; i< totalInitialJobs; i++) {
Job validationJob = _validationJobs.poll();
if (validationJob == null) break;
addJobChangeAdapter(validationJob);
validationJob.schedule();
}
}
return Status.OK_STATUS;
}
private void addJobChangeAdapter(Job job) {
job.addJobChangeListener(new JobChangeAdapter(){
// when done, see if there is another validation job to schedule
public void done(IJobChangeEvent event) {
synchronized (_validationJobs) {
Job validationJob = _validationJobs.poll();
if (validationJob != null) {
addJobChangeAdapter(validationJob);
validationJob.schedule();
}
}
}
});
}
@Override
public boolean belongsTo(Object family) {
if (family == ResourcesPlugin.FAMILY_MANUAL_BUILD)return true;
if (family == ValidationBuilder.FAMILY_VALIDATION_JOB){
return true;
}
return super.belongsTo(family);
}
public void addValidationJob(Job validationJob) {
synchronized (_validationJobs) {
_validationJobs.add(validationJob);
// schedule the job if we were empty
if (_validationJobs.size() == 1) {
this.schedule();
}
}
}
}
/**
* @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> _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 _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 _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();
}
/**
* 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();
context = aContext;
}
/**
* @deprecated Will be removed in Milestone 3.
*/
protected void terminateCleanup(WorkbenchReporter reporter) {
for (ValidatorMetaData vmd : getEnabledValidators()) {
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;
for (ValidatorMetaData vmd : enabledValidators) {
if (isValidationNecessary(vmd, getFileDeltas(monitor, vmd)))return true;
}
return false;
}
private Map> getFileDeltas(IProgressMonitor monitor) throws CoreException {
if (_fileDeltas == null)loadFileDeltas(monitor);
return _fileDeltas;
}
private IFileDelta[] getFileDeltas(IProgressMonitor monitor, ValidatorMetaData vmd) throws CoreException {
Set 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> 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 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 getLaunchedValidators() {
if (_launchedValidators == null) {
_launchedValidators = new HashSet();
}
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();
for (ValidatorMetaData vmd : evmds) {
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);
}
}
}
}
private void refFileValidateFileDelta(WorkbenchReporter reporter, ReferencialFileValidator refFileValidator) {
IResourceDelta[] resourceDelta = _delta.getAffectedChildren(IResourceDelta.ADDED | IResourceDelta.CHANGED | IResourceDelta.REMOVED);
List inputFiles = new ArrayList();
List referencingFiles = new ArrayList();
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 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);
}
}
}
private void getFileResourceDeltaInFolder(IResourceDelta delta, List 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);
}
}
private void postValidateProject(WorkbenchReporter reporter, ReferencialFileValidator refFileValidator) {
Set set = ValidationRegistryReader.getReader().getValidatorMetaData(_project);
for (ValidatorMetaData data : set) {
List filters = data.getNameFilters();
List files = getAllFilesForFilter(filters);
if (!files.isEmpty()) {
List fileForValidation = refFileValidator.getReferencedFile(files);
try {
validateReferencingFiles(reporter, fileForValidation);
} catch (Exception e) {
ValidationPlugin.getPlugin().handleException(e);
}
}
}
}
private List getAllFilesForFilter(List filters) {
if (!filters.isEmpty()) {
List allProjectFiles = ReferencialFileValidatorHelper.getAllProjectFiles(_project);
List filterFiles = new ArrayList();
for (String fileName : filters) {
if (fileName == null)continue;
for (IFile projectFile : allProjectFiles) {
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();
}
private void validateReferencingFiles(IReporter reporter, List referencingFiles) throws Exception {
Set validatedFiles = new HashSet();
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 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 jobValidators = new HashSet();
Set validators = new HashSet();
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-01: 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() {
ValidationRegistryReader.getReader().clearCachedMaps();
IProjectValidationHelper helper = ValidationHelperRegistryReader.getInstance().getValidationHelper();
if (helper != null)
helper.disposeInstance();
}
private void initValidateContext(IFileDelta[] delta) {
if (context instanceof WorkbenchContext) {
((WorkbenchContext)context).setValidationFileURIs(new ArrayList());
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
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).
* process
also sends output to the IProgressMonitor
, 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 isValidationSource
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 validate
on the
* validator, with the resource.
*
* 4. When complete (either by failing to pass a filter, or by the
* completion of the validate
), 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"); }
*/
/**
* @deprecated This class is no longer used by the framework.
*/
public class ProjectRunnable implements Runnable {
private WorkbenchReporter _reporter;
private IValidator _validator;
private ValidatorMetaData _vmd;
private IFileDelta[] _delta;
@SuppressWarnings("unchecked")
public ProjectRunnable(WorkbenchReporter reporter, IValidator validator,
ValidatorMetaData vmd, IWorkbenchContext helper, IFileDelta[] delta, Iterator iterator) {
_reporter = reporter;
_validator = validator;
_vmd = vmd;
_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 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());
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 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);
launcherJob.addValidationJob(validatorjob);
}
}