/*******************************************************************************
* Copyright (c) 2016 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is 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:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.windup.ui.util;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeoutException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.widgets.Shell;
import org.jboss.tools.common.ui.JobResultFuture;
import org.jboss.tools.foundation.core.jobs.DelegatingProgressMonitor;
import org.jboss.tools.windup.runtime.WindupRuntimePlugin;
import org.jboss.tools.windup.ui.WindupUIPlugin;
public class FutureUtils {
private static final long THREAD_SLEEP = 1 * 1000;
public static IStatus runWithProgress(final Job job, long duration, int totalWork, Shell shell, String taskName) {
final JobResultFuture future = new JobResultFuture(job);
ProgressMonitorDialog dialog = new ProgressMonitorDialog(shell);
try {
dialog.run(true, false, new IRunnableWithProgress() {
@Override
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
if (job instanceof AbstractDelegatingMonitorJob) {
((AbstractDelegatingMonitorJob)job).getDelegatingProgressMonitor().add(monitor);
}
monitor.beginTask(taskName, totalWork);
job.schedule();
try {
waitForFuture(duration, future, monitor);
} catch (ExecutionException e) {
} catch (TimeoutException e) {
} finally {
monitor.done();
}
}
});
} catch (InvocationTargetException | InterruptedException e) {
WindupRuntimePlugin.log(e);
String message = "Error occurred during operation - " + job.getName();
message += ": Exeception is: " + e.getMessage();
return new Status(IStatus.ERROR, WindupUIPlugin.PLUGIN_ID, message);
}
return getStatus(job, future);
}
private static IStatus getStatus(final Job job, final JobResultFuture future) {
if (future.isCancelled()) {
String message = NLS.bind("The operation ''{0}'' was cancelled", job.getName());
WindupUIPlugin.logErrorMessage(message);
return new Status(IStatus.CANCEL, WindupUIPlugin.PLUGIN_ID, message);
}
if (future.isDone()) {
return job.getResult();
}
String message = NLS.bind("The operation ''{0}'' did not complete in a reasonnable amount of time", job.getName());
return new Status(IStatus.ERROR, WindupUIPlugin.PLUGIN_ID, message);
}
public static void waitForFuture(long timeout, Future<?> future, IProgressMonitor monitor)
throws InterruptedException, ExecutionException, TimeoutException {
long startTime = System.currentTimeMillis();
while (!future.isDone()) {
if ((timeout > 0 && isTimeouted(startTime, timeout))
|| monitor.isCanceled()) {
future.cancel(true);
break;
}
Thread.sleep(THREAD_SLEEP);
}
}
private static boolean isTimeouted(long startTime, long timeout) {
return (System.currentTimeMillis() - startTime) > timeout;
}
public static abstract class AbstractDelegatingMonitorJob extends Job {
public static final int OK = 0;
public static final int TIMEOUTED = 1;
protected DelegatingProgressMonitor delegatingMonitor;
public AbstractDelegatingMonitorJob(String name) {
super(name);
this.delegatingMonitor = new DelegatingProgressMonitor();
}
@Override
protected IStatus run(IProgressMonitor monitor) {
delegatingMonitor.add(monitor);
return doRun(delegatingMonitor);
}
public DelegatingProgressMonitor getDelegatingProgressMonitor() {
return delegatingMonitor;
}
protected abstract IStatus doRun(IProgressMonitor monitor);
public boolean isTimeouted(IStatus status){
return status.getCode() == TIMEOUTED;
}
}
}