/*
* SonarLint for Eclipse
* Copyright (C) 2015-2017 SonarSource SA
* sonarlint@sonarsource.com
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonarlint.eclipse.tests.common;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.jobs.IJobManager;
import org.eclipse.core.runtime.jobs.Job;
import org.junit.Assert;
/**
* Inspired by m2e
*
*/
public class JobHelpers {
private static final int POLLING_DELAY = 10;
public static void waitForJobsToComplete() {
try {
waitForJobsToComplete(new NullProgressMonitor());
} catch (Exception ex) {
throw new IllegalStateException(ex);
}
}
public static void waitForJobsToComplete(IProgressMonitor monitor) throws InterruptedException, CoreException {
waitForBuildJobs();
/*
* First, make sure refresh job gets all resource change events
*
* Resource change events are delivered after WorkspaceJob#runInWorkspace returns
* and during IWorkspace#run. Each change notification is delivered by
* only one thread/job, so we make sure no other workspaceJob is running then
* call IWorkspace#run from this thread.
*
* Unfortunately, this does not catch other jobs and threads that call IWorkspace#run
* so we have to hard-code workarounds
*
* See http://www.eclipse.org/articles/Article-Resource-deltas/resource-deltas.html
*/
IWorkspace workspace = ResourcesPlugin.getWorkspace();
IJobManager jobManager = Job.getJobManager();
jobManager.suspend();
try {
Job[] jobs = jobManager.find(null);
for (int i = 0; i < jobs.length; i++) {
if (jobs[i] instanceof WorkspaceJob || jobs[i].getClass().getName().endsWith("JREUpdateJob")) {
jobs[i].join();
}
}
workspace.run(new IWorkspaceRunnable() {
public void run(IProgressMonitor monitor) {
}
}, workspace.getRoot(), 0, monitor);
} finally {
jobManager.resume();
}
waitForBuildJobs();
}
private static void waitForBuildJobs() {
waitForJobs(BuildJobMatcher.INSTANCE, 60 * 1000);
}
public static void waitForJobs(IJobMatcher matcher, int maxWaitMillis) {
final long limit = System.currentTimeMillis() + maxWaitMillis;
while (true) {
Job job = getJob(matcher);
if (job == null) {
return;
}
boolean timeout = System.currentTimeMillis() > limit;
Assert.assertFalse("Timeout while waiting for completion of job: " + job, timeout);
job.wakeUp();
try {
Thread.sleep(POLLING_DELAY);
} catch (InterruptedException e) {
// ignore and keep waiting
}
}
}
private static Job getJob(IJobMatcher matcher) {
Job[] jobs = Job.getJobManager().find(null);
for (Job job : jobs) {
if (matcher.matches(job)) {
return job;
}
}
return null;
}
public static interface IJobMatcher {
boolean matches(Job job);
}
static class LaunchJobMatcher implements IJobMatcher {
public static final IJobMatcher INSTANCE = new LaunchJobMatcher();
public boolean matches(Job job) {
return job.getClass().getName().matches("(.*\\.DebugUIPlugin.*)");
}
}
static class BuildJobMatcher implements IJobMatcher {
public static final IJobMatcher INSTANCE = new BuildJobMatcher();
public boolean matches(Job job) {
return (job instanceof WorkspaceJob) || job.getClass().getName().matches("(.*\\.AutoBuild.*)")
|| job.getClass().getName().endsWith("JREUpdateJob");
}
}
}