/******************************************************************************* * Copyright (c) 2012, 2014 Wind River Systems, Inc. and others. All rights reserved. * This program and the accompanying materials are 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: * Wind River Systems - initial API and implementation *******************************************************************************/ package org.eclipse.tcf.te.runtime.processes; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubProgressMonitor; import org.eclipse.tcf.te.runtime.interfaces.callback.ICallback; import org.eclipse.tcf.te.runtime.utils.StatusHelper; /** * Basic process launcher implementation. * <p> * The associated callback is called after <code>launch()</code> finishes. The throwable which will * be associated to the callback at the time of invocation is either any exception thrown by the * <code>launch()</code> method or if no exception has been thrown, the associated error if any * (call <code>setError(Throwable)</code> to associated an error). * <p> * In case a <code>IProgressMonitor</code> is given, a new <code>SubProgressMonitor</code> will be * opened for the launching stage. The <code>SubProgressMonitor</code> will use the given number of * ticks from the parent progress monitor. */ public abstract class ProcessLauncher implements Runnable { private ICallback callback; private IProgressMonitor progress; private Throwable error; /** * Constructor. * * @param progress The progress monitor to provide progress feedback to the user or <code>null</code>. * @param callback The callback to invoke if the launch finished or <code>null</code>. * @param ticksToUse The number of ticks to use for the sub progress monitor. */ public ProcessLauncher(IProgressMonitor progress, ICallback callback, int ticksToUse) { this.callback = callback; if (progress != null) { this.progress = new SubProgressMonitor(progress, ticksToUse); } else { this.progress = new NullProgressMonitor(); } setError(null); } /** * Returns the associated error. This error will be passed to the callback if the launch has * finished. */ public Throwable getError() { return error; } /** * Associated the given error to pass to the callback if the launch finishes. * * @param error The error to pass or <code>null</code>. */ public void setError(Throwable error) { this.error = error; } /** * Starts the task with the given name. The task will consume the given number of ticks till * finished. * * @param taskName The task name for set for the task. * @param ticks The number of ticks till the task finishes. * * @throws OperationCanceledException If the progress monitor has been canceled in the meantime. */ protected void progressBeginTask(String taskName, int ticks) throws OperationCanceledException { progressCancelCheck(); progress.beginTask(taskName, ticks); } /** * Check if the progress monitor has been canceled already. If yes, the method will throw an * <code>OperationCanceledExceptions</code> * * @throws OperationCanceledException If the progress monitor has been canceled in the meantime. */ protected void progressCancelCheck() throws OperationCanceledException { if (progress.isCanceled()) { throw new OperationCanceledException(); } } /** * Move the given amount of ticks forward in progress. * * @param ticks The amount of ticks to set as worked. * @throws OperationCanceledException If the progress monitor has been canceled in the meantime. */ protected void progressWorked(int ticks) throws OperationCanceledException { progressCancelCheck(); progress.worked(ticks); } /** * Set the given sub task name to the progress monitor. * * @param subTask The sub task name to set. * @throws OperationCanceledException If the progress monitor has been canceled in the meantime. */ protected void progressSubtask(String subTask) throws OperationCanceledException { progressCancelCheck(); progress.subTask(subTask); } /** * Set the progress monitor done. */ protected void progressDone() { progress.done(); } /* (non-Javadoc) * @see java.lang.Runnable#run() */ @Override public final void run() { Throwable error = null; try { launch(); } catch (Throwable throwable) { error = throwable; } finally { if (error == null) { error = getError(); } } // invoke the callback if any is associated. if (callback != null) { callback.done(ProcessLauncher.this, StatusHelper.getStatus(error)); } // Re-throw any Error except assertion errors ! NEVER REMOVE THIS ! if ((error instanceof Error) && !(error instanceof AssertionError)) { throw (Error) error; } } /** * Override to execute the launch. * * @throws Throwable In case something went wrong, the method may throw the problem wrapped * within a <code>Throwable</code>. */ public abstract void launch() throws Throwable; }