Package org.rzo.netty.ahessian.rpc.client

Source Code of org.rzo.netty.ahessian.rpc.client.HessianProxyFuture

package org.rzo.netty.ahessian.rpc.client;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import org.jboss.netty.util.Timeout;
import org.rzo.netty.ahessian.Constants;
import org.rzo.netty.ahessian.rpc.callback.Callback;
import org.rzo.netty.ahessian.rpc.callback.CallbackReplyMessage;
import org.rzo.netty.ahessian.rpc.callback.ClientCallback;
import org.rzo.netty.ahessian.rpc.message.HessianRPCReplyMessage;

/**
* Future object returned when executing a remote method invocation.
* <br>
* Note: within a continuation scenario, get() will return the last result received.
* Results sent by the server will override the result available on the client.
*/
public class HessianProxyFuture implements Future<Object>, Constants
{
 
  /** indicates if the invocation has been completed */
  private boolean          _done      = false;
 
  /** TODO indicates if the invocation has been canceled or timed out. */
  private boolean          _canceled    = false;
 
  /** result of the invocation. */
  private HessianRPCReplyMessage  _result      = null;

  private Lock      _lock      = new ReentrantLock();
  private Condition    _resultReceived  = _lock.newCondition();
  private Collection<Runnable> _listeners = Collections.synchronizedCollection(new ArrayList<Runnable>());
  private volatile Map<Long, ClientCallback> _callbacks = Collections.synchronizedMap(new HashMap());
  private volatile Timeout _timeout = null;

  /* (non-Javadoc)
   * @see java.util.concurrent.Future#cancel(boolean)
   */
 
  public boolean cancel(boolean mayInterruptIfRunning)
  {
    _canceled = true;
    return true;
  }

  /* (non-Javadoc)
   * @see java.util.concurrent.Future#get()
   */
 
  public Object get() throws InterruptedException, ExecutionException
  {
    Object result = null;
    _lock.lock();
    try
    {
      while (_result == null)
      {
        _resultReceived.await();
      }
      if (_result.getFault() != null)
        throw new ExecutionException(_result.getFault());
      else
        return _result.getValue();
    }
    finally
    {
      _lock.unlock();
    }
  }

  /* (non-Javadoc)
   * @see java.util.concurrent.Future#get(long, java.util.concurrent.TimeUnit)
   */
 
  public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
  {
    Object result = null;
    _lock.lock();
    try
    {
      if (_result == null)
        _resultReceived.await(timeout, unit);
      if (_result == null)
        throw new TimeoutException();
      if (_result.getFault() != null)
        throw new ExecutionException(_result.getFault());
      else
        return _result.getValue();
    }
    finally
    {
      _lock.unlock();
    }
  }

  /* (non-Javadoc)
   * @see java.util.concurrent.Future#isCancelled()
   */
 
  public boolean isCancelled()
  {
    return _canceled;
  }

  /* (non-Javadoc)
   * @see java.util.concurrent.Future#isDone()
   */
 
  public boolean isDone()
  {
    return _done;
  }

  protected synchronized void set(HessianRPCReplyMessage message)
  {
    _lock.lock();
    if (_timeout != null)
      _timeout.cancel();
    try
    {
      if (message instanceof CallbackReplyMessage)
      {
        handleCallbackReply((CallbackReplyMessage)message);         
      }
      else
      {
      _done = true;
      _result = message;
      _resultReceived.signal();
      callListners();
      }
    }
    finally
    {
      _lock.unlock();
    }
  }
 
  private void handleCallbackReply(CallbackReplyMessage message)
  {
    Long callbackId = message.getCallbackId();
    if (callbackId == null)
      return;
    ClientCallback callback = _callbacks.get(callbackId);
    if (callback == null)
    {
      System.out.println("no callback found for "+callbackId);
      return;
    }
    callback.invoke(message);
    if (message.isDone())
    {
      _callbacks.remove(callbackId);
      //System.out.println("removed callback "+callbackId);
    }
   
  }

  private void callListners()
  {
    synchronized(_listeners)
    {
      for (Runnable listener : _listeners)
        listener.run();
    }
  }

  /**
   * Adds the listener.
   *
   * @param listener the listener
   */
  public void addListener(Runnable listener)
  {
    _lock.lock();
    if (isDone())
      listener.run();
    else
      _listeners.add(listener);
    _lock.unlock();
  }

  /**
   * Removes the listener.
   *
   * @param listener the listener
   */
  public void removeListener(Runnable listener)
  {
    _listeners.remove(listener);
  }

  public void handleCallbacks(Object[] args)
  {
    if (args == null)
      return;
    for (int i=0; i<args.length; i++)
    {
      if (args[i] instanceof Callback)
      {
        ClientCallback c = new ClientCallback((Callback)args[i]);
        _callbacks.put(c.getId(), c);
        args[i] = c;
      }
    }
     
  }
 
  public boolean hasCallbacks()
  {
    return _callbacks.size() != 0;
  }

  public void setTimeout(Timeout timeout)
  {
    _timeout = timeout;
  }

  public void timedOut()
  {
    _lock.lock();
    _timeout = null;
    try
    {
      this.set(new HessianRPCReplyMessage(null, new TimeoutException(),null));
    }
    finally
    {
      _lock.unlock();
    }
  }

}
TOP

Related Classes of org.rzo.netty.ahessian.rpc.client.HessianProxyFuture

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.