/* VMIdManager.java -- A reference/example implementation of a manager for
   JDWP object/reference type IDs

   Copyright (C) 2005, 2006 Free Software Foundation

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
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.classpath.jdwp;

import gnu.classpath.jdwp.exception.InvalidClassException;
import gnu.classpath.jdwp.exception.InvalidObjectException;
import gnu.classpath.jdwp.id.*;

import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.Hashtable;

/**
 * This class manages objects and referencetypes that are reported
 * to the debugger. All objects and referencetypes reported to the
 * debugger should go through this manager.
 *
 * A brief summary of what an <code>IdManager</code> must provide:
 *
 * <code>
 * public ObjectId getObjectId (Object theObject);
 * public ObjectId get (long id);
 * public ObjectId readObjectId (ByteBuffer bb);
 * public ReferenceTypeId getReferenceTypeId (Class clazz);
 * public ReferenceTypeId getReferenceType (long id);
 * public ReferenceTypeId readReferenceTypeId (ByteBuffer bb);
 * </code>
 *
 * See the javadoc on these methods later in this file for more
 * information on these functions.
 *
 * <b>NOTE:</b> All IDs handled by the ID manager (all object and reference
 * type IDs) are assumed to be of type <code>long</code>.
 *
 * <b>NOTE:</b> This class does not manage virtual machine-specific types,
 * like methods, fields, and frames. These already have unique IDs within
 * the virtual machine and do not need further abstraction here.
 *
 * @author Keith Seitz  (keiths@redhat.com)
 */
public class VMIdManager
{
  // This factory generates ids for objects and types that may
  // be sent to a debugger.
  private static class IdFactory
  {
    // ID of last object / referencetype
    private static Object _idLock = new Object ();
    private static Object _ridLock = new Object ();
    private static long _lastId = 0;
    private static long _lastRid = 0;

    // A list of all ID types
    private static HashMap _idList = new HashMap ();

    // Initialize the id list with known types
    static
    {
      // ObjectId and ArrayId are special cases. See newObjectId.
      _idList.put (ClassLoaderId.typeClass, ClassLoaderId.class);
      _idList.put (ClassObjectId.typeClass, ClassObjectId.class);
      _idList.put (StringId.typeClass, StringId.class);
      _idList.put (ThreadId.typeClass, ThreadId.class);
      _idList.put (ThreadGroupId.typeClass, ThreadGroupId.class);
    }

    /**
     * Returns a new id for the given object
     *
     * @param obj  SoftReference of the object for which an id is desired
     * @returns a suitable object id
     */
    public static ObjectId newObjectId (SoftReference obj)
    {
      ObjectId id = null;
      Object object = obj.get ();

      // Special case: arrays
      if (object.getClass ().isArray ())
	id = new ArrayId ();
      else
	{
	  // Loop through all classes until we hit baseclass
	  Class myClass;
	  for (myClass = object.getClass (); myClass != null;
	       myClass = myClass.getSuperclass ())
	    {
	      Class clz = (Class) _idList.get (myClass);
	      if (clz != null)
		{
		  try
		    {
		      id = (ObjectId) clz.newInstance ();
		      synchronized (_idLock)
			{
			  id.setId (++_lastId);
			}
		      id.setReference (obj);
		      return id;
		    }
		  catch (InstantiationException ie)
		    {
		      // This really should not happen
		      throw new RuntimeException ("cannot create new ID", ie);
		    }
		  catch (IllegalAccessException iae)
		    {
		      // This really should not happen
		      throw new RuntimeException ("illegal access of ID", iae);
		    }
		}
	    }

	  /* getSuperclass returned null and no matching ID type found.
	     So it must derive from Object. */
	  id = new ObjectId ();
	}

      synchronized (_idLock)
	{
	  id.setId (++_lastId);
	}
      id.setReference (obj);
      return id;
    }

    /**
     * Returns a new reference type id for the given class
     *
     * @param ref  SoftReference to the desired type
     * @returns a suitable reference type id or null when the
     * reference is cleared.
     */
    public static ReferenceTypeId newReferenceTypeId (SoftReference ref)
    {
      ReferenceTypeId id;
      Class clazz = (Class) ref.get ();
      if (clazz == null)
	return null;

      if (clazz.isArray ())
	id = new ArrayReferenceTypeId ();
      else if (clazz.isInterface ())
	id = new InterfaceReferenceTypeId ();
      else
	id = new ClassReferenceTypeId ();
      id.setReference (ref);
      synchronized (_ridLock)
	{
	  id.setId (++_lastRid);
	}
      return id;
    }
  }

  /**
   * This class is a SoftReferenceIdentity type that is used by
   * the ID manager.
   */
  class ReferenceKey extends SoftReference
  {
    // Hash code of referent
    private int _hash;

    /**
     * Constructs a new <code>ReferenceKey</code> object
     * with the given referent.
     *
     * <p>This constructor should only be used for object lookups
     * by the backend.
     *
     * @param referent  the object to reference
     */
    public ReferenceKey (Object referent)
    {
      super (referent);
      _hash = referent.hashCode ();
    }
    
    /**
     * Constructs a new <code>ReferenceKey</code> object
     * with the given referent and reference queue.
     *
     * <p>The JDWP back-end stores a <code>ReferenceKey</code>
     * with its corresponding <code>JdwpId</code>. This constructor
     * is used by the back-end when adding new IDs to be managed.
     *
     * @param referent  the object to reference
     * @param queue     the queue to which to report garbage collections
     */
    public ReferenceKey (Object referent, ReferenceQueue queue)
    {
      super (referent, queue);
      _hash = referent.hashCode ();
    }
    
    /**
     * Returns the hash code of the referent.
     * This seems hacky, but is required in order to use this class
     * as a hash table key.
     *
     * @returns the hash code of the referent
     */
    public int hashCode ()
    {
      return _hash;
    }

    /**
     * Comparator for keys
     *
     * This method can be used in two ways:
     *
     * <ol>
     *    <li>For table lookups, where we want to compare referents</li>
     *    <li>For clearing GCd objects, where we want to compare the actual
     *        key object (not the referent)</li>
     * </ol>
     */
    public boolean equals (Object obj)
    {
      if (obj instanceof ReferenceKey)
	{
	  ReferenceKey ref = (ReferenceKey) obj;
	  
	  /* First check if the two references are the same.
	     If they are, that means we must be clearing GCd objects. */
	  if (this == obj)
	    return true;
	  
	  return (ref.get () == get ());
	}
      
      return false;
    }
  }
  
  // instance of VMIdManager
  private static VMIdManager _idm = new VMIdManager ();

  // A reference queue for our objects
  private ReferenceQueue _refQueue;

  // Mapping of objects (ReferenceKey) to IDs (ObjectId)
  private Hashtable _oidTable;

  // Mapping of ID numbers (Long) to IDs (ObjectId)
  private Hashtable _idTable;

  /* Mapping of class (ReferenceKey) to IDs (ReferenceTypeId) for reference
     types. Unlike other types, reference id types are NEVER released. */
  private Hashtable _classTable;

  // Mapping of ID numbers (Long) to reference type IDs (ReferenceTypeId)
  private Hashtable _ridTable;

  /**
   * Gets the instance of VMIdManager, constructing a new one
   * if none currently exists.
   */
  public static VMIdManager getDefault ()
  {
    return _idm;
  }

  // Constructs a new <code>IdManager</code>
  private VMIdManager ()
  {
    _refQueue = new ReferenceQueue ();
    _oidTable = new Hashtable (50);
    _idTable = new Hashtable (50);
    _classTable = new Hashtable (20);
    _ridTable = new Hashtable (20);
  }

  // Updates the object ID table, removing IDs whose objects have
  // been garbage collected.
  private void _update ()
  {
    Reference ref;
    while ((ref = _refQueue.poll ()) != null)
      {
	ObjectId id = (ObjectId) _oidTable.get (ref);
	_oidTable.remove (ref);
	_idTable.remove (new Long (id.getId ()));
      }
  }

  /**
   * Returns an id for the given object, adding it
   * if it does not have an id.
   *
   * @param theObject  the object to get an ID/add
   * @returns  the ID of the object
   */
  public ObjectId getObjectId (Object theObject)
  {
    ReferenceKey ref = new ReferenceKey (theObject, _refQueue);
    ObjectId id = (ObjectId) _oidTable.get (ref);
    if (id == null)
      {
	// update the tables -- this is an arbitrary place to put this
	_update ();

	// Object not found. Make new id for it
	id = IdFactory.newObjectId (ref);
	_oidTable.put (ref, id);
	_idTable.put (new Long (id.getId ()), id);
      }

    return id;
  }

  /**
   * Returns the <code>JdwpId</code> for a given ID. Unlike
   * <code>getId</code>, it throws an exception if the ID is not
   * known.
   *
   * @param id  the numerical ID of the desired <code>JdwpId</code>
   * @throws InvalidObjectException if the ID is not found
   */
  public ObjectId get (long id)
    throws InvalidObjectException
  {
    ObjectId oid = (ObjectId) _idTable.get (new Long (id));
    if (oid == null)
      throw new InvalidObjectException (id);
 
    return oid;
  }

  public ObjectId readObjectId (ByteBuffer bb)
    throws InvalidObjectException
  {
    long id = bb.getLong ();
    return get (id);
  }

  /**
   * Gets the reference type id for the given class, creating
   * a new one if it does not already have an id
   *
   * @param clazz  the class for which to get an ID
   * @returns  the ID of the class
   */
  public ReferenceTypeId getReferenceTypeId (Class clazz)
  {
    ReferenceKey ref = new ReferenceKey (clazz);
    ReferenceTypeId id = (ReferenceTypeId)_classTable.get (ref);
    if (id == null)
      {
	// Object not found. Make new id for it
	id = IdFactory.newReferenceTypeId (ref);
	_classTable.put (ref, id);
	_ridTable.put (new Long (id.getId ()), id);
      }

    return id;
  }

  /**
   * Returns the <code>ReferenceTypeId</code> for a given ID. Unlike
   * <code>getReferenceTypeId</code>, it throws an exception if the ID is not
   * known.
   *
   * @param id  the numerical ID of the desired reference type
   * @throws InvalidClassException if the ID is not found
   */
  public ReferenceTypeId getReferenceType (long id)
    throws InvalidClassException
  {
    ReferenceTypeId rid = (ReferenceTypeId) _ridTable.get (new Long (id));
    if (rid == null)
      throw new InvalidClassException (id);
 
    return rid;
  }

  public ReferenceTypeId readReferenceTypeId (ByteBuffer bb)
    throws InvalidClassException
  {
    long id = bb.getLong ();
    return getReferenceType (id);
  }
}
