| package org.eclipse.wst.validation.internal; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.IResourceChangeEvent; |
| import org.eclipse.core.resources.IResourceChangeListener; |
| import org.eclipse.core.resources.IResourceDelta; |
| import org.eclipse.core.resources.IWorkspace; |
| import org.eclipse.core.resources.IncrementalProjectBuilder; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.NullProgressMonitor; |
| import org.eclipse.wst.validation.Validator; |
| import org.eclipse.wst.validation.internal.model.IValidatorVisitor; |
| |
| /** |
| * Keep track of a validation operation when it is triggered as part of a build. |
| * @author karasiuk |
| * |
| */ |
| public class ValOperationManager implements IResourceChangeListener { |
| |
| private static ValOperationManager _me; |
| |
| /** |
| * This operation is in affect for a build cycle. At the end of the build it is |
| * reinitialized. |
| */ |
| private ValOperation _operation; |
| |
| public static synchronized ValOperationManager getDefault(){ |
| if (_me == null)_me = new ValOperationManager(); |
| return _me; |
| } |
| |
| private ValOperationManager(){ |
| init(); |
| } |
| |
| /** |
| * Initialize yourself for a new validation operation. |
| */ |
| private void init(){ |
| _operation = new ValOperation(); |
| } |
| |
| public void resourceChanged(IResourceChangeEvent event) { |
| int type = event.getType(); |
| int kind = event.getBuildKind(); |
| |
| IProject project = null; |
| if (event.getSource() instanceof IProject) { |
| project = (IProject) event.getSource(); |
| } |
| |
| if (kind == IncrementalProjectBuilder.CLEAN_BUILD && ((type & IResourceChangeEvent.PRE_BUILD) != 0)){ |
| processClean(event); |
| } |
| |
| if (isBuildStarting(event)){ |
| IValidatorVisitor visitor = new IValidatorVisitor(){ |
| |
| public void visit(Validator validator, IProject project, boolean isManual, |
| boolean isBuild, ValOperation operation, IProgressMonitor monitor) { |
| |
| validator.validationStarting(project, operation.getState(), monitor); |
| } |
| }; |
| ValManager.getDefault().accept(visitor, project, false, true, _operation, new NullProgressMonitor()); |
| |
| } |
| |
| if (isBuildFinished(event)){ |
| IValidatorVisitor visitor = new IValidatorVisitor(){ |
| |
| public void visit(Validator validator, IProject project, boolean isManual, |
| boolean isBuild, ValOperation operation, IProgressMonitor monitor) { |
| |
| validator.validationFinishing(project, operation.getState(), monitor); |
| } |
| |
| }; |
| ValManager.getDefault().accept(visitor, project, false, true, _operation, new NullProgressMonitor()); |
| //TODO this may prove to be a mistake, I may be clearing the validation result too soon. |
| init(); |
| } |
| |
| |
| //TODO remove this |
| if (Tracing.isLogging()){ |
| String kindName = null; |
| if (kind == IncrementalProjectBuilder.AUTO_BUILD)kindName = "Auto"; //$NON-NLS-1$ |
| else if (kind == IncrementalProjectBuilder.CLEAN_BUILD)kindName = "Clean"; //$NON-NLS-1$ |
| else if (kind == IncrementalProjectBuilder.FULL_BUILD)kindName = "Full"; //$NON-NLS-1$ |
| else if (kind == IncrementalProjectBuilder.INCREMENTAL_BUILD)kindName = "Incremental"; //$NON-NLS-1$ |
| else kindName = String.valueOf(kind); |
| |
| StringBuffer b = new StringBuffer(100); |
| |
| String sourceName = "unknown"; //$NON-NLS-1$ |
| if (event.getSource() instanceof IResource) { |
| IResource res = (IResource) event.getSource(); |
| sourceName = res.getName(); |
| } |
| else if (event.getSource() instanceof IWorkspace) { |
| sourceName = "Workspace"; //$NON-NLS-1$ |
| } |
| b.append("Source="+sourceName+", kind="+kindName+", type="+type); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
| if ((type & IResourceChangeEvent.POST_BUILD) != 0)b.append(", post build"); //$NON-NLS-1$ |
| if ((type & IResourceChangeEvent.PRE_BUILD) != 0){ |
| b.append(", pre build"); //$NON-NLS-1$ |
| } |
| IResourceDelta rd = event.getDelta(); |
| if (rd == null)b.append(", there was no resource delta"); //$NON-NLS-1$ |
| |
| Tracing.log(b); |
| } |
| |
| } |
| |
| /** |
| * Determine if we are starting a new build cycle. |
| * @param event |
| * @return |
| */ |
| private boolean isBuildStarting(IResourceChangeEvent event) { |
| int type = event.getType(); |
| int kind = event.getBuildKind(); |
| |
| if (ResourcesPlugin.getWorkspace().isAutoBuilding()){ |
| if (((type & IResourceChangeEvent.PRE_BUILD) != 0) && |
| (kind == IncrementalProjectBuilder.AUTO_BUILD || |
| kind == IncrementalProjectBuilder.INCREMENTAL_BUILD || |
| kind == IncrementalProjectBuilder.FULL_BUILD))return true; |
| |
| if (((type & IResourceChangeEvent.POST_BUILD) != 0) && |
| (kind == IncrementalProjectBuilder.CLEAN_BUILD))return true; |
| |
| return false; |
| } |
| else { |
| if (kind == IncrementalProjectBuilder.AUTO_BUILD )return false; |
| if (((type & IResourceChangeEvent.PRE_BUILD) != 0) && |
| (kind == IncrementalProjectBuilder.INCREMENTAL_BUILD || |
| kind == IncrementalProjectBuilder.FULL_BUILD))return true; |
| return false; |
| } |
| } |
| |
| /** |
| * Determine if we are at the end of a build cycle. This will give callers the ability to |
| * clear caches etc. |
| * |
| * @param event |
| * @return return true if we are just finishing a build. |
| */ |
| private boolean isBuildFinished(IResourceChangeEvent event) { |
| /* |
| * I discovered these conditions empirically, by running running different types of builds |
| * and noticing which events were signaled. |
| * |
| * When auto build is enabled, it seemed like all the cases ended with an AutoBuild build type, a |
| * POST_BUILD and a target of WorkSpace. |
| * |
| * When auto build is not enabled, the AUTO BUILD events are signaled, so they should be ignored. |
| * Anything other than a clean POST_BUILD seemed to indicate the end of a build cycle. (In some cases |
| * this might be a little too aggressive, but since the end result is just the deleting of some |
| * caches, it is better to be aggressive than to leave the caches around too long). |
| */ |
| int type = event.getType(); |
| int kind = event.getBuildKind(); |
| |
| if (ResourcesPlugin.getWorkspace().isAutoBuilding()){ |
| if (((type & IResourceChangeEvent.POST_BUILD) != 0) && kind == IncrementalProjectBuilder.AUTO_BUILD |
| && event.getSource() instanceof IWorkspace){ |
| return true; |
| } |
| } |
| else { |
| if (kind != IncrementalProjectBuilder.AUTO_BUILD && ((type & IResourceChangeEvent.POST_BUILD) != 0)){ |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| private void processClean(IResourceChangeEvent event){ |
| // Originally I was using this to monitor IProject build requests as well, but that is not not needed |
| // since these will be handled by the IncrementalProjectBuilder.clean() method. |
| IProgressMonitor monitor = new NullProgressMonitor(); |
| Object source = event.getSource(); |
| if (source instanceof IWorkspace) { |
| ValManager.getDefault().clean(null, _operation, monitor); |
| } |
| |
| } |
| |
| /** |
| * Answer the current validation operation. |
| */ |
| public ValOperation getOperation() { |
| return _operation; |
| } |
| |
| } |