package org.jactr.core.runtime.controller.impl; /* * default logging */ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.concurrent.Callable; import java.util.concurrent.Future; import java.util.concurrent.FutureTask; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.jactr.core.runtime.event.ACTRRuntimeEvent; import org.jactr.core.runtime.event.IACTRRuntimeListener; /** * the runtime listener is responsible for triggering the appropriate conditions * in the default controller * * @author harrison */ public class RuntimeListener implements IACTRRuntimeListener { /** * Logger definition */ static private final transient Log LOGGER = LogFactory .getLog(RuntimeListener.class); final private RuntimeState _state; final private Collection<RuntimeFuture> _startFutures; final private Collection<RuntimeFuture> _stopFutures; final private Collection<RuntimeFuture> _suspendFutures; final private Collection<RuntimeFuture> _resumeFutures; final private Lock _lock = new ReentrantLock(); private Exception _stopException; public RuntimeListener(RuntimeState state) { _state = state; _startFutures = new ArrayList<RuntimeFuture>(); _stopFutures = new ArrayList<RuntimeFuture>(); _suspendFutures = new ArrayList<RuntimeFuture>(); _resumeFutures = new ArrayList<RuntimeFuture>(); } private Future<Boolean> newFuture(Collection<RuntimeFuture> container) { RuntimeFuture future = new RuntimeFuture(); container.add(future); return future; } private void triggerFutures(Collection<RuntimeFuture> container, boolean succeeded, Exception exception) { try { _lock.lock(); for (Iterator<RuntimeFuture> iterator = container.iterator(); iterator .hasNext();) { RuntimeFuture futureTask = iterator.next(); iterator.remove(); futureTask.set(succeeded, exception); } } finally { _lock.unlock(); } } public Future<Boolean> getStartFuture() { if (_state.isRunning()) return new RuntimeFuture(true, null); try { _lock.lock(); return newFuture(_startFutures); } finally { _lock.unlock(); } } public Future<Boolean> getStopFuture() { if (!_state.isRunning()) return new RuntimeFuture(true, _stopException); try { _lock.lock(); return newFuture(_stopFutures); } finally { _lock.unlock(); } } public Future<Boolean> getSuspendFuture() { if (!_state.isRunning()) return new RuntimeFuture(false, new IllegalStateException( "Runtime is not running, cannot be suspended")); if (_state.isSuspended()) return new RuntimeFuture(true, null); try { _lock.lock(); return newFuture(_suspendFutures); } finally { _lock.unlock(); } } public Future<Boolean> getResumeFuture() { if (!_state.isRunning()) return new RuntimeFuture(false, new IllegalStateException( "Runtime is not running, cannot be resumed")); if (!_state.isSuspended()) return new RuntimeFuture(true, null); try { _lock.lock(); return newFuture(_resumeFutures); } finally { _lock.unlock(); } } public void modelAdded(ACTRRuntimeEvent event) { } public void modelRemoved(ACTRRuntimeEvent event) { } public void runtimeResumed(ACTRRuntimeEvent event) { triggerFutures(_resumeFutures, true, null); } public void runtimeStarted(ACTRRuntimeEvent event) { _stopException = null; triggerFutures(_startFutures, true, null); } public void runtimeStopped(ACTRRuntimeEvent event) { _stopException = event.getException(); triggerFutures(_stopFutures, true, event.getException()); } public void runtimeSuspended(ACTRRuntimeEvent event) { triggerFutures(_suspendFutures, true, null); } private class RuntimeFuture extends FutureTask<Boolean> { public RuntimeFuture() { super(new Callable<Boolean>() { public Boolean call() { return null; } }); } public RuntimeFuture(boolean succeeded, Exception e) { this(); set(succeeded, e); } public void set(boolean succeeded, Exception e) { if (e != null) setException(e); else set(succeeded); } } }