/******************************************************************************* | |
* Copyright (c) 2009 by SAP AG, Walldorf. | |
* 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: | |
* SAP AG - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.jst.ws.jaxws.testutils.threading; | |
import java.lang.reflect.InvocationTargetException; | |
import org.eclipse.core.runtime.IProgressMonitor; | |
import org.eclipse.jface.operation.IRunnableWithProgress; | |
import org.eclipse.jface.operation.ModalContext; | |
import org.eclipse.jst.ws.jaxws.utils.ContractChecker; | |
import org.eclipse.swt.widgets.Display; | |
/** | |
* Utility to execute runnable instances in a separate thread. Implementation is pretty similar to {@link ModalContext} but it uses {@link TestContextThread} to perform forking | |
* | |
* @author Danail Branekov | |
* | |
*/ | |
public class TestContext | |
{ | |
/** | |
* Executes the operation specified in the caller or in a {@link TestContextThread} thread depending on the <code>fork</code> value. In case the caller of this method is a {@link TestContextThread} instance, the execution of the <code>operation</code> is performed in the current thread no matter | |
* of the <code>fork</code> value | |
* | |
* @param operation | |
* the operation; must not be null | |
* @param fork | |
* true to perform the <code>operation</code> in a {@link TestContextThread}; false to perform the <code>operation</code> in the current thread | |
* @param monitor | |
* progress monitor | |
* @param display TODO | |
* @throws InvocationTargetException | |
* @throws InterruptedException | |
*/ | |
public static void run(final IRunnableWithProgress operation, final boolean fork, final IProgressMonitor monitor, final Display display) throws InvocationTargetException, InterruptedException | |
{ | |
ContractChecker.nullCheckParam(operation, "operation"); | |
final boolean willFork = !isInTestContextThread() && fork; | |
if (willFork) | |
{ | |
runInTestContextThread(operation, monitor, display); | |
} else | |
{ | |
runInCurrentThread(operation, monitor); | |
} | |
} | |
/** | |
* Runs the operation in the current thread | |
* | |
* @param operation | |
* the operation | |
* @throws InvocationTargetException | |
* if a {@link Throwable} has been thrown during operation execution. The exception wraps that {@link Throwable} | |
*/ | |
private static void runInCurrentThread(final IRunnableWithProgress operation, final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException | |
{ | |
operation.run(monitor); | |
} | |
/** | |
* Runs the operation in a {@link TestContextThread}. | |
* | |
* @param runnable | |
* operation | |
* @throws InvocationTargetException | |
* if the {@link TestContextThread} finished with error | |
* @see TestContextThread#getError() | |
*/ | |
private static void runInTestContextThread(final IRunnableWithProgress runnable, final IProgressMonitor monitor, final Display display) throws InvocationTargetException | |
{ | |
final TestContextThread contextThread = new TestContextThread(runnable, monitor, display); | |
contextThread.start(); | |
contextThread.block(); | |
if (contextThread.getError() != null) | |
{ | |
if(contextThread.getError() instanceof InvocationTargetException) { | |
throw (InvocationTargetException)contextThread.getError(); | |
} | |
else { | |
throw new InvocationTargetException(contextThread.getError()); | |
} | |
} | |
} | |
/** | |
* Checks whether the current thread is instance of {@link TestContextThread} | |
*/ | |
private static boolean isInTestContextThread() | |
{ | |
final Thread t = Thread.currentThread(); | |
return t instanceof TestContextThread; | |
} | |
} |