X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fmethod%2FAsyncResultImpl.java;fp=bundles%2Forg.simantics.databoard%2Fsrc%2Forg%2Fsimantics%2Fdataboard%2Fmethod%2FAsyncResultImpl.java;h=2c6ad9e8b425938dab225daae5ff746166832581;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.databoard/src/org/simantics/databoard/method/AsyncResultImpl.java b/bundles/org.simantics.databoard/src/org/simantics/databoard/method/AsyncResultImpl.java new file mode 100644 index 000000000..2c6ad9e8b --- /dev/null +++ b/bundles/org.simantics.databoard/src/org/simantics/databoard/method/AsyncResultImpl.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * Copyright (c) 2010 Association for Decentralized Information Management in + * Industry THTH ry. + * 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: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.databoard.method; + +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.simantics.databoard.adapter.AdaptException; +import org.simantics.databoard.adapter.Adapter; +import org.simantics.databoard.method.MethodInterface.AsyncRequestStatus; +import org.simantics.databoard.method.MethodInterface.AsyncResult; +import org.simantics.databoard.method.MethodInterface.ExecutionError; +import org.simantics.databoard.method.MethodInterface.InvokeListener; + +public class AsyncResultImpl implements AsyncResult { + + /** + * Log4J Error logger. + * Security settings are logged with DEBUG level. + * Unexpected errors are logged with ERROR level. + */ + static Logger LOGGER = Logger.getLogger("AsyncResultImpl"); + + InvokeException invokeException; + Object executionError; + + Object response; + + InvokeListener listener; + + // Optional adapters + Adapter responseAdapter, errorAdapter; + + Semaphore sleeper = new Semaphore(0); + + public AsyncResultImpl() { + } + + @Override + public Object getExecutionError() { + return executionError; + } + + @Override + public InvokeException getInvokeException() { + return invokeException; + } + + public void setInvokeException(final InvokeException error) + { + this.invokeException = error; + final InvokeListener l = listener; + sleeper.release(Integer.MAX_VALUE); + + if (l != null) { + // TODO use executor instead + new Thread() { + public void run() { + try { + l.onException((Exception) error.getCause()); + } catch (RuntimeException e) { + LOGGER.log(Level.SEVERE, "Unexpected runtime exception", e); + } + }; + }.start(); + } + + } + + public void setResponse(Object response) { + if (responseAdapter!=null) { + try { + response = responseAdapter.adapt(response); + } catch (AdaptException e) { + setInvokeException( new InvokeException("Failed to adapt the respose "+response, e) ); + return; + } + } + + this.response = response; + final InvokeListener l = listener; + sleeper.release(Integer.MAX_VALUE); + + if (l != null) { + // TODO use executor instead + new Thread() { + public void run() { + try { + l.onCompleted(AsyncResultImpl.this.response); + } catch (RuntimeException e) { + LOGGER.log(Level.SEVERE, "Unexpected runtime exception", e); + } + }; + }.start(); + } + } + + public void setExecutionError(Object executionError) { + + if (errorAdapter!=null) { + // Adapt execution error using adapter + try { + executionError = errorAdapter.adapt(executionError); + } catch (AdaptException e) { + // Unable to adapt execution error. This is now an invokcation error + setInvokeException(new InvokeException("Execution and Invoke failed. Failed to adapt executionError ("+executionError+")", e)); + return; + } + } + + this.executionError = executionError; + final InvokeListener l = listener; + sleeper.release(Integer.MAX_VALUE); + + if (l != null) { + // TODO use executor instead + new Thread() { + public void run() { + l.onExecutionError(AsyncResultImpl.this.executionError); + // TODO Capture runtimeException, push to log4j + }; + }.start(); + } + } + + + @Override + public Object getResponse() { + return response; + } + + @Override + public AsyncRequestStatus getStatus() { + if (invokeException!=null || executionError!=null) + return AsyncRequestStatus.Failed; + if (response!=null) + return AsyncRequestStatus.Succeed; + return AsyncRequestStatus.Waiting; + } + + @Override + public void setListener(InvokeListener listener) { + // FIXME event is lost if error/result is set at the same time + if (listener!=null) { + if (response!=null) listener.onCompleted(response); + if (invokeException!=null) listener.onException((Exception)invokeException.getCause()); + if (executionError!=null) listener.onExecutionError(executionError); + } + this.listener = listener; + } + + @Override + public Object waitForResponse() throws InvokeException, ExecutionError, InterruptedException { + sleeper.acquire(); + if (response!=null) return response; + if (invokeException!=null) throw invokeException; + if (executionError!=null) throw new ExecutionError(executionError); + return null; + } + + @Override + public Object waitForResponse(long timeout, TimeUnit unit) + throws InvokeException, ExecutionError, InterruptedException { + sleeper.tryAcquire(timeout, unit); + if (response!=null) return response; + if (invokeException!=null) throw invokeException; + if (executionError!=null) throw new ExecutionError(executionError); + return null; + } + + public void setResponseAdapter(Adapter responseAdapter) { + this.responseAdapter = responseAdapter; + } + + public void setErrorAdapter(Adapter errorAdapter) { + this.errorAdapter = errorAdapter; + } + +} +