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