/* **************************************************************************

  $Archive: /njcl_v2rmi/src/com/novell/service/session/util/JVMUID.java $
  $Revision: 13 $
  $Modtime: 11/15/00 3:43p $

  Copyright (c) 1997 Novell, Inc.  All Rights Reserved.

  THIS WORK IS  SUBJECT  TO  U.S.  AND  INTERNATIONAL  COPYRIGHT  LAWS  AND
  TREATIES.   NO  PART  OF  THIS  WORK MAY BE  USED,  PRACTICED,  PERFORMED
  COPIED, DISTRIBUTED, REVISED, MODIFIED, TRANSLATED,  ABRIDGED, CONDENSED,
  EXPANDED,  COLLECTED,  COMPILED,  LINKED,  RECAST, TRANSFORMED OR ADAPTED
  WITHOUT THE PRIOR WRITTEN CONSENT OF NOVELL, INC. ANY USE OR EXPLOITATION
  OF THIS WORK WITHOUT AUTHORIZATION COULD SUBJECT THE PERPETRATOR TO
  CRIMINAL AND CIVIL LIABILITY.

****************************************************************************/
package com.novell.service.session.util;

import java.util.Hashtable;
import java.util.Enumeration;
import java.util.Random;
import com.novell.service.session.util.InvalidUIDException;
import java.rmi.server.UID;

/** @internal
 */
public class JVMUID
{
   // Always access debug via final static...hopefully a final static of
   // false will be optimized out by the compiler
   final static private boolean DEBUG = false;
   final static private boolean S_DEBUG = false; // May have side effects

   Hashtable uids;
   Random rand;
   short simpleUID = 1;

   private static JVMUID singletonInstance;

   private JVMUID
   (
   )
   {
      this.uids = new Hashtable();
      this.rand = new Random();
   }

   /**
    * Create a new, UID
    */
   public UID createUID
   (
   )
   {
      synchronized (this.uids)
      {
         UID uid;
         uid = nextUID();
         return uid;
      }
   }

   /**
    * Create a new UID with associated storage
    */
   public UID createUIDStorage
   (
   )
   {
      synchronized (this.uids)
      {
         UID uid;
         uid = nextUID();
         // Temporary placeholder using this...
         // means no data written yet
         this.uids.put(uid, this);
         return uid;
      }
   }

   /**
    * Store an object at a specific UID.
    * @exception InvalidUIDException When the UID is invalid.
    */
   public void write
   (
      UID uid,
      Object data
   )
   throws InvalidUIDException
   {
      synchronized (this.uids)
      {
         Object o = this.uids.get(uid);
         // UID invalid if no entry or if entry doesn't point to this
         if (null != o && this == o)
         {
            this.uids.remove(uid);
            this.uids.put(uid, data);
         }
         else
            throw new InvalidUIDException();
      }
   }

   /**
    * Return an Object from a specific UID.
    * @exception InvalidUIDException When the UID is invalid.
    */
   public Object read
   (
      UID uid
   )
   throws InvalidUIDException
   {
      String data = null;
      synchronized (this.uids)
      {
         Object o = this.uids.get(uid);
         // UID invalid if no entry or if entry points to this
         if (null != o && this != o)
         {
            data = (String)this.uids.get(uid);
         }
         else
            throw new InvalidUIDException();
      }
      return data;
   }

   /**
    * Remove a UID entry.
    * @exception InvalidUIDException When the UID is invalid.
    */
   public void remove
   (
      UID uid
   )
   throws InvalidUIDException
   {
      synchronized (this.uids)
      {
         this.uids.remove(uid);
      }
   }

   /**
    * Return a singleton instance of JVMUID.
    */
   public static JVMUID getInstance
   (
   )
   {
      if (null == singletonInstance)
      {
         singletonInstance = new JVMUID();
      }
      return singletonInstance;
   }

   private UID nextUID
   (
   )
   {
      return new UID(simpleUID++);
   }

   public void dump()
   {
      if (DEBUG)
      {
         synchronized (this.uids)
         {
            Debug.println("UIDS:");
            Enumeration enum = uids.keys();
            while (enum.hasMoreElements())
            {
               UID uid = (UID)enum.nextElement();
               Object o = uids.get(uid);
               Debug.println(uid + " : " + o);
            }
         }
      }
   }
}

