blob: a7558b84017fc9b57cfcb9ae7d7af353d44533f7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2013 Christian Pontesegger and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Christian Pontesegger - initial API and implementation
*******************************************************************************/
package org.eclipse.ease;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
/**
* A ScriptResult is a container for a script execution. As execution often occurs detached from the System thread, the result object contains an indicator for
* pending and finished results. Results itself may contain an object or an exception.
*/
public class ScriptResult implements Future<Object> {
/** Special void object for script methods not returning a result. */
public static final Object VOID = new Object() {
@Override
public String toString() {
return "<void>";
}
};
private Object fResult = null;
private ScriptExecutionException fException = null;
private boolean fIsDone = false;
/**
* Set the result to be stored.
*
* @param result
* object to be stored
*/
public final void setResult(final Object result) {
synchronized (this) {
if (isDone())
throw new IllegalArgumentException("ScriptResult already completed");
fResult = result;
fIsDone = true;
notifyAll();
}
}
/**
* Set an exception to be stored for this result.
*
* @param e
* exception to be stored
*/
public final void setException(final ScriptExecutionException e) {
synchronized (this) {
if (isDone())
throw new IllegalArgumentException("ScriptResult already completed");
fException = e;
fIsDone = true;
notifyAll();
}
}
@Override
public final String toString() {
try {
final Object result = get();
return ((result == null) ? "[null]" : fResult.toString());
} catch (final ExecutionException e) {
return "Exception: " + e.getLocalizedMessage();
}
}
@Override
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
@Override
public boolean isCancelled() {
return false;
}
@Override
public boolean isDone() {
synchronized (this) {
return fIsDone;
}
}
@Override
public Object get() throws ExecutionException {
waitForResult();
return getResultOrThrow();
}
@Override
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
waitForResult(unit.toMillis(timeout));
return getResultOrThrow();
}
public Object get(long milliSeconds) throws InterruptedException, ExecutionException, TimeoutException {
return get(milliSeconds, TimeUnit.MILLISECONDS);
}
private Object getResultOrThrow() throws ScriptExecutionException {
synchronized (this) {
if (fException != null)
throw fException;
return fResult;
}
}
/**
* Blocks execution until the execution result is ready.
*
* @deprecated use {@link #get()}
*/
@Deprecated
public void waitForResult() throws ExecutionException {
// instead of removing this method should be marked 'private'
synchronized (this) {
while (!isDone()) {
try {
wait();
} catch (final InterruptedException e) {
throw new ScriptEngineInterruptedException(e);
}
}
}
}
/**
* Blocks execution until the execution result is ready or the timeout is reached. Once this method returns you still need to query {@link #isReady()} as
* the timeout might have depleted.
*
* @param milliseconds
* the maximum time to wait in milliseconds.
* @deprecated use {@link #get(long, TimeUnit)}
*/
@Deprecated
public void waitForResult(long milliseconds) throws InterruptedException, TimeoutException {
// instead of removing this method should be marked 'private'
final long waitUntil = System.currentTimeMillis() + milliseconds;
synchronized (this) {
while (!isDone() && (System.currentTimeMillis() < waitUntil))
wait(waitUntil - System.currentTimeMillis());
if (!isDone())
throw new TimeoutException(String.format("Result not ready after %d milliseconds", milliseconds));
}
}
/**
* Verify that this ScriptResult is processed. If the result is ready, execution of the underlying script is done.
*
* @return true when processing is done
* @deprecated use {@link #isDone()}
*/
@Deprecated
public final boolean isReady() {
return isDone();
}
/**
* Get the result value stored.
*
* @return result value
* @deprecated use {@link #get()}
*/
@Deprecated
public final Object getResult() {
try {
return get();
} catch (final ExecutionException e) {
throw new RuntimeException("Execution failed", e);
}
}
/**
* Get the exception stored within this result.
*
* @return stored exception or null
* @deprecated use {@link #get()}
*/
@Deprecated
public final Throwable getException() {
try {
get();
throw new RuntimeException("Execution did not throw an exception");
} catch (final ExecutionException e) {
return e;
}
}
/**
* Checks whether this result contains an exception.
*
* @return true when this result contains an exception
* @deprecated use {@link #get()}
*/
@Deprecated
public final boolean hasException() {
try {
get();
return false;
} catch (final ExecutionException e) {
return true;
}
}
}