/**
 * TransactionManagerCache is a class that caches references to
 * TransactionManager instances available from all reachable lookup
 * service.
 * <br>
 * This source code is copyright 2008 by Patrick May.  All
 * rights reserved.
 *
 * @author Patrick May (patrick@softwarematters.org)
 * @author &copy; 2008 Patrick May.  All rights reserved.
 * @version 1
 */

package org.softwarematters.jini.util;

import java.util.logging.Logger;

import net.jini.core.transaction.server.TransactionManager;

public class TransactionManagerCache
{
  private static final int LOOKUP_RETRY_INTERVAL = 2500;  // 2.5 seconds

  private static Logger logger_
    = Logger.getLogger(TransactionManagerCache.class.getName());

  private ServiceCache serviceCache_ = null;

  /**
   * The full constructor for the TransactionManagerCache class.
   *
   * @param groups The names of the Jini groups to which TransactionManager
   *               instances must belong.
   */
  public TransactionManagerCache(String[] groups)
    {
    serviceCache_ = new ServiceCache(groups,TransactionManager.class);
    }


  /**
   * The default constructor for the TransactionManagerCache class.
   */
  public TransactionManagerCache()
    {
    this(new String[] { "" });  // default to public group
    }


  /**
   * Return a TransactionManager from the cache, if one is available
   * within the specified timeout.
   *
   * @param timeout The maximum time to wait for a TransactionManager,
   *                in milliseconds.
   */
  public TransactionManager transactionManager(long timeout)
    {
    TransactionManager transactionManager = null;

    do
      {
      logger_.info("Checking cache for TransactionManager...");
      transactionManager = (TransactionManager)serviceCache_.service();

      if (transactionManager == null)
        {
        try { Thread.sleep(LOOKUP_RETRY_INTERVAL); }
        catch (InterruptedException e) { }
        }

      timeout -= LOOKUP_RETRY_INTERVAL;
      }
    while ((transactionManager == null) && (timeout >= LOOKUP_RETRY_INTERVAL));

    if (transactionManager == null)
      logger_.info("No TransactionManager instance found, returning null.");
    else
      logger_.info("TransactionManager instance found.");

    return transactionManager;
    }


  /**
   * Return a TransactionManager from the cache, blocking as long as
   * necessary.
   */
  public TransactionManager transactionManager()
    {
    return transactionManager(Long.MAX_VALUE);
    }


  /**
   * A test harness for the TransactionManagerCache class.
   *
   * @param args The command line arguments passed in.
   */
  public static void main(String args[])
    {
    System.setSecurityManager(new java.rmi.RMISecurityManager());

    TransactionManagerCache cache = new TransactionManagerCache();

    TransactionManager manager = null;
    while (manager == null)
      manager = cache.transactionManager();
    }
}  // end TransactionManagerCache

