/******************************************************************************* * Copyright (c) 2007, 2014 compeople AG 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: * compeople AG - initial API and implementation *******************************************************************************/ package org.eclipse.riena.ui.core.uiprocess; import java.util.concurrent.Callable; import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.riena.core.util.Nop; /** * Executes a {@code Callable}. * * @since 3.0 */ public final class UIExecutor { private UIExecutor() { Nop.reason("Utility"); //$NON-NLS-1$ } /** * Same as {@link executeLively(final Callable<T> callable, final boolean * user)} but {@code user} is false. * * @param <T> * the result type of the {@code Callable} * @param callable * the {@code Callable} to run in background * @return the result of the {@code Callable} * @throws RuntimeException * the possible exception of the {@code Callable} * * @see executeLively(final Callable<T> callable, final boolean user) * @since 3.0 */ public static <T> T executeLively(final Callable<T> callable) { return executeLively(callable, false); } /** * Execute the given {@code Callable} in the background and return when * finished but keep the UI lively.<br> * If executing the {@code Callable} caused an exception this will be * re-thrown. * * @param <T> * the result type of the {@code Callable} * @param callable * the {@code Callable} to run in background * @param user * Sets whether or not this {@code Callable} has been directly * initiated by a UI end user. These jobs may be presented * differently in the UI. * @return the result of the {@code Callable} * @throws RuntimeException * the possible exception of the {@code Callable} * * @since 3.0 */ public static <T> T executeLively(final Callable<T> callable, final boolean user) { final BackgroundProcess<T> process = new BackgroundProcess<T>(callable, user); process.start(); UISynchronizer.createSynchronizer().readAndDispatch(new Callable<Boolean>() { public Boolean call() throws Exception { return process.isFinished(); } }); if (process.getError() != null) { throw new RuntimeException("Exception while executing callable.", process.getError()); //$NON-NLS-1$ } return process.getResult(); } private static class BackgroundProcess<T> extends UIProcess { private final AtomicBoolean finished = new AtomicBoolean(false); private final Callable<T> callable; private T result; private Throwable error; public BackgroundProcess(final Callable<T> callable, final boolean user) { super("UIExecutor", user); //$NON-NLS-1$ this.callable = callable; } @Override public boolean runJob(final IProgressMonitor monitor) { try { result = callable.call(); } catch (final Throwable e) { this.error = e; } finally { finished.set(true); } return true; } private boolean isFinished() { return finished.get(); } private T getResult() { return result; } private Throwable getError() { return error; } } }