// ********************************************************************** // // Copyright (c) 2003-2010 ZeroC, Inc. All rights reserved. // // This copy of Ice is licensed to you under the terms described in the // ICE_LICENSE file included in this distribution. // // ********************************************************************** package Ice; /** * An AsyncResult object is the return value of an asynchronous invocation. * With this object, an application can obtain several attributes of the * invocation and discover its outcome. **/ public class AsyncResult { protected AsyncResult(IceInternal.Instance instance, String op, IceInternal.CallbackBase del) { _instance = instance; _operation = op; _is = new IceInternal.BasicStream(instance, false, false); _os = new IceInternal.BasicStream(instance, false, false); _state = 0; _exception = null; _callback = del; } /** * Returns the communicator that sent the invocation. * * @return The communicator. **/ public Communicator getCommunicator() { return null; } /** * Returns the connection that that was used for the invocation. * * @return The connection. **/ public Connection getConnection() { return null; } /** * Returns the proxy that that was used to call the <code>begin_</code> method. * * @return The proxy. **/ public ObjectPrx getProxy() { return null; } /** * Indicates whether the result of an invocation is available. * * @return True if the result is available, which means a call to the <code>end_</code> * method will not block. The method returns false if the result is not yet available. **/ public final boolean isCompleted() { synchronized(_monitor) { return (_state & Done) > 0; } } /** * Blocks the caller until the result of the invocation is available. **/ public final void waitForCompleted() { synchronized(_monitor) { while((_state & Done) == 0) { try { _monitor.wait(); } catch(InterruptedException ex) { } } } } /** * When you call the <code>begin_</code> method, the Ice run time attempts to * write the corresponding request to the client-side transport. If the * transport cannot accept the request, the Ice run time queues the request * for later transmission. This method returns true if, at the time it is called, * the request has been written to the local transport (whether it was initially * queued or not). Otherwise, if the request is still queued, this method returns * false. * * @return True if the request has been sent, or false if the request is queued. **/ public final boolean isSent() { synchronized(_monitor) { return (_state & Sent) > 0; } } /** * Blocks the caller until the request has been written to the client-side transport. **/ public final void waitForSent() { synchronized(_monitor) { while((_state & (Sent | Done)) == 0) { try { _monitor.wait(); } catch(InterruptedException ex) { } } } } /** * This method returns true if a request was written to the client-side * transport without first being queued. If the request was initially * queued, this method returns false (independent of whether the request * is still in the queue or has since been written to the client-side transport). * * @return True if the request was sent without being queued, or false * otherwise. **/ public final boolean sentSynchronously() { return _sentSynchronously; // No lock needed, immutable once __send() is called } /** * Returns the name of the operation. * * @return The operation name. **/ public final String getOperation() { return _operation; } public final IceInternal.BasicStream __os() { return _os; } public final IceInternal.BasicStream __is() { return _is; } public final boolean __wait() { synchronized(_monitor) { if((_state & EndCalled) > 0) { throw new java.lang.IllegalArgumentException("end_ method called more than once"); } _state |= EndCalled; while((_state & Done) == 0) { try { _monitor.wait(); } catch(InterruptedException ex) { } } if(_exception != null) { //throw (LocalException)_exception.fillInStackTrace(); throw _exception; } return (_state & OK) > 0; } } public final void __throwUserException() throws UserException { try { _is.startReadEncaps(); _is.throwException(); } catch(UserException ex) { _is.endReadEncaps(); throw ex; } } public final void __exceptionAsync(final LocalException ex) { // // This is called when it's not safe to call the exception callback synchronously // from this thread. Instead the exception callback is called asynchronously from // the client thread pool. // try { _instance.clientThreadPool().execute(new IceInternal.DispatchWorkItem(_instance) { public void run() { __exception(ex); } }); } catch(CommunicatorDestroyedException exc) { throw exc; // CommunicatorDestroyedException is the only exception that can propagate directly. } } public final void __exception(LocalException ex) { synchronized(_monitor) { _state |= Done; _exception = ex; _monitor.notifyAll(); } if(_callback != null) { try { _callback.__completed(this); } catch(RuntimeException exc) { __warning(exc); } } } protected final void __sentInternal() { // // Note: no need to change the _state here, specializations are responsible for // changing the state. // if(_callback != null) { try { _callback.__sent(this); } catch(RuntimeException ex) { __warning(ex); } } } public final void __sentAsync() { // // This is called when it's not safe to call the sent callback synchronously // from this thread. Instead the exception callback is called asynchronously from // the client thread pool. // try { _instance.clientThreadPool().execute(new IceInternal.DispatchWorkItem(_instance) { public void run() { __sentInternal(); } }); } catch(CommunicatorDestroyedException exc) { } } public static void __check(AsyncResult r, ObjectPrx prx, String operation) { __check(r, operation); if(r.getProxy() != prx) { throw new IllegalArgumentException("Proxy for call to end_" + operation + " does not match proxy that was used to call corresponding begin_" + operation + " method"); } } public static void __check(AsyncResult r, Connection con, String operation) { __check(r, operation); if(r.getConnection() != con) { throw new IllegalArgumentException("Connection for call to end_" + operation + " does not match connection that was used to call corresponding begin_" + operation + " method"); } } public static void __check(AsyncResult r, Communicator com, String operation) { __check(r, operation); if(r.getCommunicator() != com) { throw new IllegalArgumentException("Communicator for call to end_" + operation + " does not match communicator that was used to call corresponding " + "begin_" + operation + " method"); } } protected static void __check(AsyncResult r, String operation) { if(r == null) { throw new IllegalArgumentException("AsyncResult == null"); } else if(r.getOperation() != operation) // Do NOT use equals() here - we are comparing reference equality { throw new IllegalArgumentException("Incorrect operation for end_" + operation + " method: " + r.getOperation()); } } protected final void __response() { // // Note: no need to change the _state here, specializations are responsible for // changing the state. // if(_callback != null) { try { _callback.__completed(this); } catch(RuntimeException ex) { __warning(ex); } } } protected final void __warning(RuntimeException ex) { if(_instance.initializationData().properties.getPropertyAsIntWithDefault("Ice.Warn.AMICallback", 1) > 0) { String s = "exception raised by AMI callback:\n" + IceInternal.Ex.toString(ex); _instance.initializationData().logger.warning(s); } } protected IceInternal.Instance _instance; protected String _operation; protected java.lang.Object _monitor = new java.lang.Object(); protected IceInternal.BasicStream _is; protected IceInternal.BasicStream _os; protected static final byte OK = 0x1; protected static final byte Done = 0x2; protected static final byte Sent = 0x4; protected static final byte EndCalled = 0x8; protected byte _state; protected boolean _sentSynchronously; protected LocalException _exception; private IceInternal.CallbackBase _callback; }