/* gnuIcCurrent.java --
   Copyright (C) 2005 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package gnu.CORBA.Interceptor;

import gnu.CORBA.CDR.BufferedCdrOutput;
import gnu.CORBA.Poa.ORB_1_4;

import org.omg.CORBA.Any;
import org.omg.CORBA.BAD_INV_ORDER;
import org.omg.CORBA.TCKind;
import org.omg.CORBA.portable.InputStream;
import org.omg.CORBA.portable.ObjectImpl;
import org.omg.PortableInterceptor.Current;
import org.omg.PortableInterceptor.CurrentHelper;
import org.omg.PortableInterceptor.InvalidSlot;

import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;

/**
 * Supports the "Interceptor current" concept, providing the slot value
 * information for the current thread. When making the invocation, this
 * information is copied to the Current, returned by ClientRequestInfo.
 *
 * There is only one instance of this class per ORB. It maintains a thread to
 * information map.
 *
 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
 */
public class gnuIcCurrent extends ObjectImpl implements Current
{
  /**
   * Use serialVersionUID for interoperability.
   */
  private static final long serialVersionUID = 1;

  /**
   * The ORB, controllin this Current. It provides data about the required size
   * of the slot array.
   */
  final ORB_1_4 orb;

  /**
   * The table, mapping threads to records.
   */
  private Hashtable threads = new Hashtable();

  /**
   * An empty array when no slots are defined, computed once.
   */
  static final Any[] NO_SLOTS = new Any[ 0 ];

  /**
   * Create the IC current.
   */
  public gnuIcCurrent(ORB_1_4 an_orb)
  {
    orb = an_orb;
  }

  /**
   * Get the array of POA current repository ids.
   *
   * @return a single member array, containing value, returned by the
   * {@link CurrentHelper#id}, normally
   * "IDL:omg.org/PortableInterceptor/Current:1.0".
   */
  public String[] _ids()
  {
    return new String[] { CurrentHelper.id() };
  }

  /**
   * Add the entry to the map.
   */
  public void put(Thread t, Any[] record)
  {
    synchronized (threads)
      {
        threads.put(t, record);

        // Remove non-running threads, avoiding memory leak.
        if (threads.size() > 12)
          {
            Iterator it = threads.entrySet().iterator();
            while (it.hasNext())
              {
                Map.Entry e = (Map.Entry) it.next();
                Thread tx = (Thread) e.getKey();
                if (!tx.isAlive())
                  {
                    it.remove();
                  }
              }
          }
      }
  }

  /**
   * Check if this thread is registered.
   */
  public boolean has(Thread t)
  {
    synchronized (threads)
      {
        return threads.containsKey(t);
      }
  }

  /**
   * Remove the entry from the map.
   */
  public void remove(Thread t)
  {
    synchronized (threads)
      {
        threads.remove(t);
      }
  }

  /**
   * Get array of all slots, as it is applicable for the current thread. If the
   * slots were not previously allocated, they are allocated during this call.
   */
  Any[] get_slots()
  {
    Any[] r;
    synchronized (threads)
      {
        r = (Any[]) threads.get(Thread.currentThread());
        if (r == null)
          {
            r = new Any[ orb.icSlotSize ];

            for (int i = 0; i < r.length; i++)
              {
                Any a = orb.create_any();
                a.type(orb.get_primitive_tc(TCKind.tk_null));
                r [ i ] = a;
              }

            put(Thread.currentThread(), r);
          }
        return r;
      }
  }

  /**
       * Get copu array of all slots, as it is applicable for the current thread. If
   * the slots were not previously allocated, they are allocated during this
   * call.
   */
  public Any[] clone_slots()
  {
    if (orb.icSlotSize == 0)
      {
        return NO_SLOTS;
      }
    else
      {
        Any[] r = get_slots();
        Any[] copy = new Any[ r.length ];

        BufferedCdrOutput buf = new BufferedCdrOutput();
        buf.setOrb(orb);

        for (int i = 0; i < copy.length; i++)
          {
            r [ i ].write_value(buf);
          }

        InputStream input = buf.create_input_stream();

        for (int i = 0; i < copy.length; i++)
          {
            copy [ i ] = orb.create_any();
            copy [ i ].read_value(input, r [ i ].type());
          }

        return copy;
      }
  }

  /**
   * Get value for the slot with the given id. If the array of Currents has not
   * been yet allocated for the current thread, it is allocated during the
   * invocation of this method.
   */
  public Any get_slot(int slot_id) throws InvalidSlot, BAD_INV_ORDER
  {
    try
      {
        return get_slots() [ slot_id ];
      }
    catch (ArrayIndexOutOfBoundsException e)
      {
        throw new InvalidSlot("Slot " + slot_id);
      }
  }

  /**
   * Set value for the slot with the given id. If the array of Currents has not
   * been yet allocated for the current thread, it is allocated during the
   * invocation of this method.
   */
  public void set_slot(int slot_id, Any data)
    throws InvalidSlot, BAD_INV_ORDER
  {
    try
      {
        get_slots() [ slot_id ] = data;
      }
    catch (ArrayIndexOutOfBoundsException e)
      {
        throw new InvalidSlot("Slot " + slot_id);
      }
  }
}