001: package org.obe.runtime.tool;
002:
003: import org.obe.client.api.tool.Parameter;
004: import org.obe.client.api.tool.ToolAgent;
005: import org.obe.client.api.tool.ToolInvocation;
006: import org.obe.engine.EngineContext;
007: import org.obe.spi.WorkflowContext;
008: import org.obe.xpdl.model.data.ParameterMode;
009:
010: import java.io.IOException;
011: import java.io.Serializable;
012: import java.io.Writer;
013: import java.lang.reflect.InvocationTargetException;
014:
015: /**
016: * Abstract base implementation for a ToolAgent.
017: *
018: * @author Adrian Price
019: */
020: public abstract class AbstractToolAgent implements ToolAgent,
021: Serializable {
022: private static final long serialVersionUID = -2568946818713089632L;
023: protected transient int _status = WAITING;
024: private transient Thread _thread;
025:
026: protected AbstractToolAgent() {
027: }
028:
029: public final int invokeApplication(ToolInvocation ti)
030: throws InvocationTargetException {
031:
032: if (_status != WAITING)
033: throw new IllegalStateException();
034: _status = RUNNING;
035:
036: int ret = -1;
037: try {
038: _thread = Thread.currentThread();
039: ret = _invokeApplication(ti);
040: for (int i = 0; i < ti.parameters.length; i++) {
041: Parameter parameter = ti.parameters[i];
042: if (parameter.getMode() == ParameterMode.IN)
043: parameter.setValue(null);
044: }
045: _status = FINISHED;
046: } catch (InterruptedException e) {
047: _status = TERMINATED;
048: } catch (InvocationTargetException e) {
049: _status = ERROR;
050: throw e;
051: } catch (RuntimeException e) {
052: _status = ERROR;
053: throw e;
054: }
055: return ret;
056: }
057:
058: public void renderInvocationScript(ToolInvocation ti, Writer writer)
059: throws IOException {
060:
061: throw new UnsupportedOperationException("The "
062: + getClass().getName()
063: + " tool agent does not support browsers");
064: }
065:
066: /**
067: * Performs the actual tool invocation. Implementations <em>must</em> block
068: * until tool execution is complete, and must re-throw any
069: * </code>java.lang.InterruptedException</code> caught, because this
070: * exception informs the {@link ToolAgent#invokeApplication} method that the
071: * tool has been terminated. Implementations <em>must</em> update the
072: * values of INOUT and OUT parameters if they changed as a result of tool
073: * execution. There is no need to clear IN parameter values, because this is
074: * done automatically by {@link ToolAgent#invokeApplication}.
075: *
076: * @param ti Tool invocation details and parameters.
077: * @return The tool's exit code. One of {@link #EXIT_NORMAL},
078: * {@link #EXIT_CANCEL}.
079: * @throws InterruptedException if {@link #terminateApp()} was called.
080: * @throws InvocationTargetException If any other exception occurred while
081: * invoking the tool.
082: */
083: protected abstract int _invokeApplication(ToolInvocation ti)
084: throws InterruptedException, InvocationTargetException;
085:
086: /**
087: * Describes the workflow context in which the tool is being invoked.
088: * <p/>
089: * <em>N.B. This method will return <code>null</code> if the tool agent was
090: * invoked by a remote client.</em>
091: *
092: * @return The workflow context, if known.
093: */
094: protected static WorkflowContext getWorkflowContext() {
095: return EngineContext.peekContext();
096: }
097:
098: public int requestAppStatus() {
099: return _status;
100: }
101:
102: public final void terminateApp() {
103: if (_status == ACTIVE)
104: _thread.interrupt();
105: else
106: throw new IllegalStateException();
107: }
108: }
|