Bug 578257 - API job should cancel execution on disposed baseline

Provide monitor & ask for cancellation on the monitor in case API
analysis job runs at same time a baseline is disposed.

Change-Id: I0fc91b0252eaf2a7b0275c84b7245a1804f3bfee
Signed-off-by: Andrey Loskutov <loskutov@gmx.de>
Reviewed-on: https://git.eclipse.org/r/c/pde/eclipse.pde.ui/+/189733
Tested-by: PDE Bot <pde-bot@eclipse.org>
diff --git a/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/BadClassfileTests.java b/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/BadClassfileTests.java
index 943dfa8..ebb33cd 100644
--- a/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/BadClassfileTests.java
+++ b/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/BadClassfileTests.java
@@ -22,6 +22,7 @@
 
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.MultiStatus;
 import org.eclipse.osgi.service.resolver.ResolverError;
@@ -222,7 +223,7 @@
 			}
 
 			@Override
-			public boolean acceptReference(IReference reference) {
+			public boolean acceptReference(IReference reference, IProgressMonitor monitor) {
 				return true;
 			}
 
diff --git a/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/TestSuiteHelper.java b/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/TestSuiteHelper.java
index dd97331..32f6b0f 100644
--- a/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/TestSuiteHelper.java
+++ b/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/model/tests/TestSuiteHelper.java
@@ -298,6 +298,11 @@
 				}
 				return fReferences;
 			}
+
+			@Override
+			public boolean isDisposed() {
+				return false;
+			}
 		};
 	}
 
diff --git a/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/search/tests/TestRequestor.java b/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/search/tests/TestRequestor.java
index 4491c61..1742a91 100644
--- a/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/search/tests/TestRequestor.java
+++ b/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/search/tests/TestRequestor.java
@@ -16,6 +16,7 @@
 import java.util.HashSet;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.pde.api.tools.internal.model.ProjectComponent;
 import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
 import org.eclipse.pde.api.tools.internal.provisional.VisibilityModifiers;
@@ -78,7 +79,7 @@
 	}
 
 	@Override
-	public boolean acceptReference(IReference reference) {
+	public boolean acceptReference(IReference reference, IProgressMonitor monitor) {
 		try {
 			IApiMember member = reference.getResolvedReference();
 			if(member != null) {
diff --git a/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/util/tests/UtilTests.java b/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/util/tests/UtilTests.java
index c3ba11a..4f6e18c 100644
--- a/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/util/tests/UtilTests.java
+++ b/apitools/org.eclipse.pde.api.tools.tests/src/org/eclipse/pde/api/tools/util/tests/UtilTests.java
@@ -452,6 +452,11 @@
 			public IReferenceCollection getExternalDependencies() {
 				return null;
 			}
+
+			@Override
+			public boolean isDisposed() {
+				return false;
+			}
 		}
 		List<IApiComponent> allComponents = new ArrayList<>();
 		String[] componentNames = new String[] {
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java
index cb6d374..73f7205 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/ApiBaselineManager.java
@@ -47,11 +47,13 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
 import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.core.runtime.preferences.IEclipsePreferences;
 import org.eclipse.core.runtime.preferences.IPreferencesService;
 import org.eclipse.core.runtime.preferences.IScopeContext;
 import org.eclipse.core.runtime.preferences.InstanceScope;
 import org.eclipse.osgi.service.resolver.BundleDescription;
+import org.eclipse.pde.api.tools.internal.builder.ApiAnalysisBuilder.ApiAnalysisJob;
 import org.eclipse.pde.api.tools.internal.model.ApiBaseline;
 import org.eclipse.pde.api.tools.internal.model.ApiModelCache;
 import org.eclipse.pde.api.tools.internal.model.ApiModelFactory;
@@ -550,6 +552,7 @@
 	 */
 	public void stop() {
 		try {
+			Job.getJobManager().cancel(ApiAnalysisJob.class);
 			if (baselinecache != null) {
 				// we should first dispose all existing baselines
 				for (IApiBaseline iApiBaseline : baselinecache.values()) {
@@ -627,6 +630,7 @@
 			if (ApiPlugin.DEBUG_BASELINE_MANAGER) {
 				System.out.println("disposing workspace baseline"); //$NON-NLS-1$
 			}
+			Job.getJobManager().cancel(ApiAnalysisJob.class);
 			workspacebaseline.dispose();
 			StubApiComponent.disposeAllCaches();
 			workspacebaseline = null;
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractIllegalMethodReference.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractIllegalMethodReference.java
index fd9b911..555199d 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractIllegalMethodReference.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractIllegalMethodReference.java
@@ -17,6 +17,7 @@
 import java.util.Map;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.pde.api.tools.internal.model.MethodKey;
 import org.eclipse.pde.api.tools.internal.provisional.builder.IReference;
 import org.eclipse.pde.api.tools.internal.provisional.descriptors.IElementDescriptor;
@@ -85,8 +86,8 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
-		if (!super.isProblem(reference)) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
+		if (!super.isProblem(reference, monitor)) {
 			return false;
 		}
 		IApiMember method = reference.getResolvedReference();
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractIllegalTypeReference.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractIllegalTypeReference.java
index c126ea1..511017a 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractIllegalTypeReference.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractIllegalTypeReference.java
@@ -17,6 +17,7 @@
 import java.util.Map;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.ICompilationUnit;
 import org.eclipse.jdt.core.IMethod;
 import org.eclipse.jdt.core.ISourceRange;
@@ -80,8 +81,8 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
-		if (!super.isProblem(reference)) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
+		if (!super.isProblem(reference, monitor)) {
 			return false;
 		}
 		IApiMember type = reference.getResolvedReference();
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractProblemDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractProblemDetector.java
index b470445..077aedb 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractProblemDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractProblemDetector.java
@@ -54,6 +54,7 @@
 import org.eclipse.pde.api.tools.internal.provisional.IApiMarkerConstants;
 import org.eclipse.pde.api.tools.internal.provisional.builder.IApiProblemDetector;
 import org.eclipse.pde.api.tools.internal.provisional.builder.IReference;
+import org.eclipse.pde.api.tools.internal.provisional.model.IApiBaseline;
 import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
 import org.eclipse.pde.api.tools.internal.provisional.model.IApiElement;
 import org.eclipse.pde.api.tools.internal.provisional.model.IApiField;
@@ -506,16 +507,16 @@
 		List<IApiProblem> problems = new LinkedList<>();
 		Iterator<IReference> iterator = references.iterator();
 		SubMonitor loopMonitor = SubMonitor.convert(monitor, references.size());
-		while (iterator.hasNext()) {
+		while (iterator.hasNext() && !monitor.isCanceled()) {
 			loopMonitor.split(1);
 			IReference reference = iterator.next();
 			if (reference.getResolvedReference() == null) {
 				// unresolved reference ignore it
 			} else {
-				if (isProblem(reference)) {
+				if (isProblem(reference, monitor)) {
+					IApiComponent component = reference.getMember().getApiComponent();
 					try {
 						IApiProblem problem = null;
-						IApiComponent component = reference.getMember().getApiComponent();
 						if (component instanceof ProjectComponent) {
 							ProjectComponent ppac = (ProjectComponent) component;
 							IJavaProject project = ppac.getJavaProject();
@@ -528,6 +529,7 @@
 						}
 					} catch (CoreException e) {
 						ApiPlugin.log(e.getStatus());
+						checkIfDisposed(component, monitor);
 					}
 				}
 			}
@@ -536,12 +538,37 @@
 	}
 
 	/**
+	 * Checks if given component is disposed or belongs to already disposed baseline
+	 * - and if yes, cancels given monitor if the API analysis runs in a job
+	 *
+	 * @param component
+	 * @param monitor
+	 */
+	public static void checkIfDisposed(IApiComponent component, IProgressMonitor monitor) {
+		if (component != null && !monitor.isCanceled() && ApiAnalysisBuilder.isRunningAsJob()) {
+			try {
+				if (component.isDisposed()) {
+					monitor.setCanceled(true);
+					return;
+				}
+				IApiBaseline baseline = component.getBaseline();
+				if (baseline != null && baseline.isDisposed()) {
+					monitor.setCanceled(true);
+				}
+			} catch (CoreException e) {
+				monitor.setCanceled(true);
+			}
+		}
+	}
+
+	/**
 	 * Returns whether the resolved reference is a real problem.
 	 *
 	 * @param reference
+	 * @param monitor
 	 * @return whether a problem
 	 */
-	protected boolean isProblem(IReference reference) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
 		// by default fragment -> host references are not problems
 		// https://bugs.eclipse.org/bugs/show_bug.cgi?id=255659
 		IApiMember member = reference.getResolvedReference();
@@ -553,6 +580,7 @@
 					return !lcomp.getHost().equals(member.getApiComponent());
 				}
 			} catch (CoreException ce) {
+				checkIfDisposed(reference.getMember().getApiComponent(), monitor);
 				ApiPlugin.log(ce);
 			}
 		}
@@ -1032,8 +1060,8 @@
 	 * @return the API problem if problem or null
 	 * @throws CoreException
 	 */
-	public IApiProblem checkAndCreateProblem(IReference reference) throws CoreException {
-		if (isProblem(reference) == false) {
+	public IApiProblem checkAndCreateProblem(IReference reference, IProgressMonitor monitor) throws CoreException {
+		if (isProblem(reference, monitor) == false) {
 			return null;
 		}
 		return createProblem(reference);
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractTypeLeakDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractTypeLeakDetector.java
index 3fa2bf0..255433f 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractTypeLeakDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/AbstractTypeLeakDetector.java
@@ -17,6 +17,7 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.ISourceRange;
@@ -74,7 +75,7 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
 		IApiMember member = reference.getResolvedReference();
 		try {
 			IApiAnnotations annotations = member.getApiComponent().getApiDescription().resolveAnnotations(member.getHandle());
@@ -98,6 +99,7 @@
 			}
 		} catch (CoreException e) {
 			ApiPlugin.log(e);
+			checkIfDisposed(member.getApiComponent(), monitor);
 		}
 		return false;
 	}
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java
index 6c9fcef..e52943b 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ApiAnalysisBuilder.java
@@ -396,8 +396,7 @@
 			return projects;
 		}
 		boolean fullBuild = kind == FULL_BUILD;
-		boolean runAsJob = prefs.getBoolean(ICoreConstants.RUN_API_ANALYSIS_AS_JOB);
-		if (runAsJob) {
+		if (isRunningAsJob()) {
 			ApiAnalysisJob job = new ApiAnalysisJob(BuilderMessages.api_analysis_builder, currentproject, fullBuild,
 					wbaseline, projects);
 			job.cancelSimilarJobs(fullBuild);
@@ -555,7 +554,7 @@
 		}
 	}
 
-	class ApiAnalysisJob extends Job {
+	public class ApiAnalysisJob extends Job {
 
 		private boolean fullBuild;
 		private IApiBaseline wbaseline;
@@ -849,7 +848,7 @@
 		return hasFatalProblem;
 	}
 
-	private static boolean isRunningAsJob() {
+	public static boolean isRunningAsJob() {
 		PDEPreferencesManager prefs = PDECore.getDefault().getPreferencesManager();
 		boolean runAsJob = prefs.getBoolean(ICoreConstants.RUN_API_ANALYSIS_AS_JOB);
 		return runAsJob;
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalFieldReferenceDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalFieldReferenceDetector.java
index a8aae4c..8279f46 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalFieldReferenceDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalFieldReferenceDetector.java
@@ -18,6 +18,7 @@
 import java.util.StringTokenizer;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
@@ -133,8 +134,8 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
-		if (!super.isProblem(reference)) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
+		if (!super.isProblem(reference, monitor)) {
 			return false;
 		}
 		String componentId = fFieldComponents.get(reference.getResolvedReference().getHandle());
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalImplementsProblemDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalImplementsProblemDetector.java
index 07ef089..006b04b 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalImplementsProblemDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalImplementsProblemDetector.java
@@ -16,6 +16,7 @@
 import java.util.HashMap;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
 import org.eclipse.pde.api.tools.internal.provisional.Factory;
 import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
@@ -84,10 +85,10 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
 		try {
 			if (isIllegalType(reference)) {
-				return super.isProblem(reference);
+				return super.isProblem(reference, monitor);
 			}
 			if (fRestrictedInterfaces.size() > 0) {
 				IApiMember member = reference.getMember();
@@ -101,8 +102,12 @@
 			if (ApiPlugin.DEBUG_PROBLEM_DETECTOR) {
 				ApiPlugin.log(ce);
 			}
+			IApiMember member = reference.getMember();
+			if (member != null) {
+				checkIfDisposed(member.getApiComponent(), monitor);
+			}
 		}
-		return super.isProblem(reference);
+		return super.isProblem(reference, monitor);
 	}
 
 	@Override
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalMethodReferenceDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalMethodReferenceDetector.java
index 502d7e9..9747421 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalMethodReferenceDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/IllegalMethodReferenceDetector.java
@@ -18,6 +18,7 @@
 import java.util.StringTokenizer;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.IType;
 import org.eclipse.jface.text.BadLocationException;
 import org.eclipse.jface.text.IDocument;
@@ -63,8 +64,8 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
-		if (super.isProblem(reference)) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
+		if (super.isProblem(reference, monitor)) {
 			return true;
 		}
 		// check the restricted types listing
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakExtendsProblemDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakExtendsProblemDetector.java
index 8522131..de1be2a 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakExtendsProblemDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakExtendsProblemDetector.java
@@ -19,6 +19,7 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.pde.api.tools.internal.model.ApiType;
 import org.eclipse.pde.api.tools.internal.model.MethodKey;
@@ -68,8 +69,8 @@
 	}
 
 	@Override
-	public boolean isProblem(IReference reference) {
-		boolean isProb = super.isProblem(reference);
+	public boolean isProblem(IReference reference, IProgressMonitor monitor) {
+		boolean isProb = super.isProblem(reference, monitor);
 		problemFlags = IApiProblem.LEAK_EXTENDS;
 		//check if the no extend type is left to be extended
 		// or if noimplement interface is extended but not marked noimplement
@@ -108,6 +109,7 @@
 			}
 			catch (CoreException e) {
 				ApiPlugin.log(e);
+				checkIfDisposed(member.getApiComponent(), monitor);
 			}
 		}
 		if (isProb) {
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakFieldProblemDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakFieldProblemDetector.java
index bb31d2b..5f0a045 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakFieldProblemDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakFieldProblemDetector.java
@@ -16,6 +16,7 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IField;
 import org.eclipse.jdt.core.ISourceRange;
@@ -74,8 +75,8 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
-		if (super.isProblem(reference)) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
+		if (super.isProblem(reference, monitor)) {
 			IApiField field = (IApiField) reference.getMember();
 			if ((Flags.AccProtected & field.getModifiers()) > 0) {
 				// TODO: could do this check before resolution - it's a check on
@@ -89,6 +90,7 @@
 					}
 				} catch (CoreException e) {
 					ApiPlugin.log(e);
+					checkIfDisposed(field.getApiComponent(), monitor);
 				}
 			}
 			return true;
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakImplementsProblemDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakImplementsProblemDetector.java
index fea946d..b30325c 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakImplementsProblemDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakImplementsProblemDetector.java
@@ -16,6 +16,7 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.pde.api.tools.internal.provisional.ApiPlugin;
 import org.eclipse.pde.api.tools.internal.provisional.IApiAnnotations;
 import org.eclipse.pde.api.tools.internal.provisional.RestrictionModifiers;
@@ -54,8 +55,8 @@
 	}
 
 	@Override
-	public boolean isProblem(IReference reference) {
-		boolean isProb = super.isProblem(reference);
+	public boolean isProblem(IReference reference, IProgressMonitor monitor) {
+		boolean isProb = super.isProblem(reference, monitor);
 		// check if no implement interface is implemented and thereby leaking api
 		// types from noimplement interface
 		if (isProb == false) {
@@ -74,6 +75,7 @@
 			}
 			catch (CoreException e) {
 				ApiPlugin.log(e);
+				checkIfDisposed(member.getApiComponent(), monitor);
 			}
 		}
 		return isProb;
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakReturnTypeDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakReturnTypeDetector.java
index a16b233..edb8f43 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakReturnTypeDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/LeakReturnTypeDetector.java
@@ -17,6 +17,7 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.pde.api.tools.internal.provisional.builder.IReference;
 import org.eclipse.pde.api.tools.internal.provisional.model.IApiType;
@@ -53,8 +54,8 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
-		if (super.isProblem(reference) == true) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
+		if (super.isProblem(reference, monitor) == true) {
 			return true;
 		}
 		IApiType type = (IApiType) reference.getResolvedReference();
@@ -68,7 +69,8 @@
 							return true;
 						}
 					}
-				}catch (CoreException e) {
+				} catch (CoreException e) {
+					checkIfDisposed(reference.getMember().getApiComponent(), monitor);
 					// do nothing, skip it
 				}
 			}
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/MethodLeakDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/MethodLeakDetector.java
index e36fdcd..ae90789 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/MethodLeakDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/MethodLeakDetector.java
@@ -17,6 +17,7 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.jdt.core.Flags;
 import org.eclipse.jdt.core.IType;
@@ -69,7 +70,7 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
 		IApiMethod method = (IApiMethod) reference.getMember();
 		IApiType type = (IApiType) reference.getResolvedReference();
 		try {
@@ -109,6 +110,7 @@
 			}
 		} catch (CoreException e) {
 			ApiPlugin.log(e);
+			checkIfDisposed(method.getApiComponent(), monitor);
 		}
 		return false;
 	}
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ReferenceAnalyzer.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ReferenceAnalyzer.java
index 6890dbc..6053d3f 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ReferenceAnalyzer.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/ReferenceAnalyzer.java
@@ -245,6 +245,9 @@
 			localMonitor.subTask(BuilderMessages.ReferenceAnalyzer_analyzing_api_checking_use);
 			SubMonitor loopMonitor = localMonitor.split(1).setWorkRemaining(detectors.length);
 			for (IApiProblemDetector detector : detectors) {
+				if (monitor.isCanceled()) {
+					break;
+				}
 				allProblems.addAll(detector.createProblems(loopMonitor.split(1)));
 			}
 			IApiProblem[] array = allProblems.toArray(new IApiProblem[allProblems.size()]);
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/SystemApiDetector.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/SystemApiDetector.java
index 4f0b5cd..b305f8e 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/SystemApiDetector.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/builder/SystemApiDetector.java
@@ -314,7 +314,7 @@
 	}
 
 	@Override
-	protected boolean isProblem(IReference reference) {
+	protected boolean isProblem(IReference reference, IProgressMonitor monitor) {
 		// the reference must be in the system library
 		try {
 			IApiMember member = reference.getMember();
@@ -361,6 +361,7 @@
 			}
 		} catch (CoreException e) {
 			ApiPlugin.log(e);
+			checkIfDisposed(reference.getMember().getApiComponent(), monitor);
 		}
 		return false;
 	}
@@ -408,8 +409,11 @@
 		List<IApiProblem> problems = new LinkedList<>();
 		SubMonitor loopMonitor = SubMonitor.convert(monitor, references.size());
 		for (IReference reference : references) {
+			if (monitor.isCanceled()) {
+				break;
+			}
 			loopMonitor.split(1);
-			if (isProblem(reference)) {
+			if (isProblem(reference, monitor)) {
 				try {
 					IApiProblem problem = null;
 					IApiComponent component = reference.getMember().getApiComponent();
@@ -425,6 +429,7 @@
 					}
 				} catch (CoreException e) {
 					ApiPlugin.log(e.getStatus());
+					AbstractProblemDetector.checkIfDisposed(reference.getMember().getApiComponent(), monitor);
 				}
 			}
 		}
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/ApiBaseline.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/ApiBaseline.java
index fd9dfc3..2caca5a 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/ApiBaseline.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/ApiBaseline.java
@@ -820,6 +820,11 @@
 		fState = null;
 	}
 
+	@Override
+	public boolean isDisposed() {
+		return disposed;
+	}
+
 	/**
 	 * performs the actual dispose of mappings and cached elements
 	 */
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java
index 6fa57ba..20078a1 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/BundleComponent.java
@@ -152,8 +152,6 @@
 	 */
 	private long fBundleId;
 
-	private volatile boolean disposed;
-
 	/**
 	 * Constructs a new API component from the specified location in the file
 	 * system in the given baseline.
@@ -189,7 +187,6 @@
 			synchronized (this) {
 				fManifest = null;
 				fBundleDescription = null;
-				disposed = true;
 			}
 		}
 	}
@@ -1275,7 +1272,4 @@
 				NLS.bind(Messages.BundleApiComponent_baseline_disposed, getName(), baseline.getName()), null));
 	}
 
-	protected boolean isDisposed() {
-		return disposed;
-	}
 }
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/Component.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/Component.java
index a9ad50c..0a63a65 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/Component.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/model/Component.java
@@ -49,6 +49,8 @@
 	 */
 	private volatile IReferenceCollection fReferences;
 
+	private volatile boolean disposed;
+
 	/**
 	 * Constructs an API component in the given {@link IApiBaseline}.
 	 *
@@ -85,6 +87,7 @@
 		} finally {
 			synchronized (this) {
 				fApiDescription = null;
+				disposed = true;
 			}
 		}
 	}
@@ -185,4 +188,9 @@
 		}
 		return fReferences;
 	}
+
+	@Override
+	public boolean isDisposed() {
+		return disposed;
+	}
 }
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/model/IApiBaseline.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/model/IApiBaseline.java
index ba5a7b1..59880a1 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/model/IApiBaseline.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/model/IApiBaseline.java
@@ -167,4 +167,9 @@
 	 * @param location the new location of the baseline
 	 */
 	public void setLocation(String location);
+
+	/**
+	 * @return true if the current baseline is disposed
+	 */
+	public boolean isDisposed();
 }
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/model/IApiComponent.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/model/IApiComponent.java
index fb322cd..cfd2d4e 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/model/IApiComponent.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/model/IApiComponent.java
@@ -242,4 +242,9 @@
 	 * @return the collection of reference descriptors
 	 */
 	public IReferenceCollection getExternalDependencies();
+
+	/**
+	 * @return true if the current component is disposed
+	 */
+	public boolean isDisposed();
 }
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/search/ApiSearchEngine.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/search/ApiSearchEngine.java
index 19d990d..0109709 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/search/ApiSearchEngine.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/search/ApiSearchEngine.java
@@ -157,7 +157,7 @@
 		IReference ref = null;
 		SubMonitor localmonitor = SubMonitor.convert(monitor, references.size());
 		IApiMember member = null;
-		for (Iterator<IReference> iter = references.iterator(); iter.hasNext();) {
+		for (Iterator<IReference> iter = references.iterator(); iter.hasNext() && !monitor.isCanceled();) {
 			if (localmonitor.isCanceled()) {
 				return Collections.emptyList();
 			}
@@ -167,7 +167,7 @@
 				continue;
 			}
 			localmonitor.setTaskName(MessageFormat.format(SearchMessages.ApiSearchEngine_searching_for_use_from, fRequestorContext, type.getName()));
-			if (requestor.acceptReference(ref)) {
+			if (requestor.acceptReference(ref, monitor)) {
 				refs.add(ref);
 			}
 			localmonitor.worked(1);
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/search/IApiSearchRequestor.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/search/IApiSearchRequestor.java
index 180eaa5..f6fe357 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/search/IApiSearchRequestor.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/provisional/search/IApiSearchRequestor.java
@@ -13,6 +13,7 @@
  *******************************************************************************/
 package org.eclipse.pde.api.tools.internal.provisional.search;
 
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.pde.api.tools.internal.provisional.builder.IReference;
 import org.eclipse.pde.api.tools.internal.provisional.model.IApiComponent;
 import org.eclipse.pde.api.tools.internal.provisional.model.IApiMember;
@@ -94,7 +95,7 @@
 	 * @param reference
 	 * @return true if the reference should be accepted, false otherwise
 	 */
-	public boolean acceptReference(IReference reference);
+	public boolean acceptReference(IReference reference, IProgressMonitor monitor);
 
 	/**
 	 * Returns the or'd listing of {@link IReference} kinds to look for.
diff --git a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseSearchRequestor.java b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseSearchRequestor.java
index 122a21c..0dc3de7 100644
--- a/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseSearchRequestor.java
+++ b/apitools/org.eclipse.pde.api.tools/src/org/eclipse/pde/api/tools/internal/search/UseSearchRequestor.java
@@ -16,6 +16,7 @@
 import java.util.Set;
 
 import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.pde.api.tools.internal.AntFilterStore;
 import org.eclipse.pde.api.tools.internal.builder.AbstractProblemDetector;
 import org.eclipse.pde.api.tools.internal.builder.ProblemDetectorBuilder;
@@ -203,7 +204,7 @@
 	}
 
 	@Override
-	public boolean acceptReference(IReference reference) {
+	public boolean acceptReference(IReference reference, IProgressMonitor monitor) {
 		try {
 			IApiMember member = reference.getResolvedReference();
 			if (member != null) {
@@ -211,7 +212,7 @@
 				if (!fComponentIds.contains(component.getSymbolicName()) || component.equals(reference.getMember().getApiComponent())) {
 					return false;
 				}
-				if (isIllegalUse(reference) || (includesAPI() && includesInternal())) {
+				if (isIllegalUse(reference, monitor) || (includesAPI() && includesInternal())) {
 					return true;
 				}
 				IApiAnnotations annots = component.getApiDescription().resolveAnnotations(member.getHandle());
@@ -226,6 +227,7 @@
 			}
 		} catch (CoreException ce) {
 			ApiPlugin.log(ce);
+			AbstractProblemDetector.checkIfDisposed(reference.getMember().getApiComponent(), monitor);
 		}
 		return false;
 	}
@@ -238,14 +240,17 @@
 	 * @return true if the reference is illegal use false otherwise
 	 * @since 1.1
 	 */
-	boolean isIllegalUse(IReference reference) {
+	boolean isIllegalUse(IReference reference, IProgressMonitor monitor) {
 		IApiProblemDetector[] detectors = fAnalyzer.getProblemDetectors(reference.getReferenceKind());
 		for (IApiProblemDetector detector : detectors) {
+			if (monitor.isCanceled()) {
+				break;
+			}
 			if (detector.considerReference(reference)) {
 				Reference ref = (Reference) reference;
 				ref.setFlags(IReference.F_ILLEGAL);
 				try {
-					IApiProblem pb = ((AbstractProblemDetector) detector).checkAndCreateProblem(reference);
+					IApiProblem pb = ((AbstractProblemDetector) detector).checkAndCreateProblem(reference, monitor);
 					if (pb != null && !isFiltered(pb)) {
 						ref.addProblems(pb);
 					} else {
@@ -253,6 +258,7 @@
 					}
 				} catch (CoreException e) {
 					ApiPlugin.log(e);
+					AbstractProblemDetector.checkIfDisposed(reference.getMember().getApiComponent(), monitor);
 				}
 				return true;
 			}