/******************************************************************************* * 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; } } }