Save This Page
Home » openjdk-7 » java » rmi » server » [javadoc | source]
    1   /*
    2    * Copyright 1996-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   package java.rmi.server;
   26   
   27   import java.io.DataInput;
   28   import java.io.DataOutput;
   29   import java.io.IOException;
   30   import java.io.Serializable;
   31   import java.security.SecureRandom;
   32   
   33   /**
   34    * A <code>UID</code> represents an identifier that is unique over time
   35    * with respect to the host it is generated on, or one of 2<sup>16</sup>
   36    * "well-known" identifiers.
   37    *
   38    * <p>The {@link #UID()} constructor can be used to generate an
   39    * identifier that is unique over time with respect to the host it is
   40    * generated on.  The {@link #UID(short)} constructor can be used to
   41    * create one of 2<sup>16</sup> well-known identifiers.
   42    *
   43    * <p>A <code>UID</code> instance contains three primitive values:
   44    * <ul>
   45    * <li><code>unique</code>, an <code>int</code> that uniquely identifies
   46    * the VM that this <code>UID</code> was generated in, with respect to its
   47    * host and at the time represented by the <code>time</code> value (an
   48    * example implementation of the <code>unique</code> value would be a
   49    * process identifier),
   50    *  or zero for a well-known <code>UID</code>
   51    * <li><code>time</code>, a <code>long</code> equal to a time (as returned
   52    * by {@link System#currentTimeMillis()}) at which the VM that this
   53    * <code>UID</code> was generated in was alive,
   54    * or zero for a well-known <code>UID</code>
   55    * <li><code>count</code>, a <code>short</code> to distinguish
   56    * <code>UID</code>s generated in the same VM with the same
   57    * <code>time</code> value
   58    * </ul>
   59    *
   60    * <p>An independently generated <code>UID</code> instance is unique
   61    * over time with respect to the host it is generated on as long as
   62    * the host requires more than one millisecond to reboot and its system
   63    * clock is never set backward.  A globally unique identifier can be
   64    * constructed by pairing a <code>UID</code> instance with a unique host
   65    * identifier, such as an IP address.
   66    *
   67    * @author      Ann Wollrath
   68    * @author      Peter Jones
   69    * @since       JDK1.1
   70    */
   71   public final class UID implements Serializable {
   72   
   73       private static int hostUnique;
   74       private static boolean hostUniqueSet = false;
   75   
   76       private static final Object lock = new Object();
   77       private static long lastTime = System.currentTimeMillis();
   78       private static short lastCount = Short.MIN_VALUE;
   79   
   80       /** indicate compatibility with JDK 1.1.x version of class */
   81       private static final long serialVersionUID = 1086053664494604050L;
   82   
   83       /**
   84        * number that uniquely identifies the VM that this <code>UID</code>
   85        * was generated in with respect to its host and at the given time
   86        * @serial
   87        */
   88       private final int unique;
   89   
   90       /**
   91        * a time (as returned by {@link System#currentTimeMillis()}) at which
   92        * the VM that this <code>UID</code> was generated in was alive
   93        * @serial
   94        */
   95       private final long time;
   96   
   97       /**
   98        * 16-bit number to distinguish <code>UID</code> instances created
   99        * in the same VM with the same time value
  100        * @serial
  101        */
  102       private final short count;
  103   
  104       /**
  105        * Generates a <code>UID</code> that is unique over time with
  106        * respect to the host that it was generated on.
  107        */
  108       public UID() {
  109   
  110           synchronized (lock) {
  111               if (!hostUniqueSet) {
  112                   hostUnique = (new SecureRandom()).nextInt();
  113                   hostUniqueSet = true;
  114               }
  115               unique = hostUnique;
  116               if (lastCount == Short.MAX_VALUE) {
  117                   boolean interrupted = Thread.interrupted();
  118                   boolean done = false;
  119                   while (!done) {
  120                       long now = System.currentTimeMillis();
  121                       if (now <= lastTime) {
  122                           // wait for time to change
  123                           try {
  124                               Thread.currentThread().sleep(1);
  125                           } catch (InterruptedException e) {
  126                               interrupted = true;
  127                           }
  128                       } else {
  129                           lastTime = now;
  130                           lastCount = Short.MIN_VALUE;
  131                           done = true;
  132                       }
  133                   }
  134                   if (interrupted) {
  135                       Thread.currentThread().interrupt();
  136                   }
  137               }
  138               time = lastTime;
  139               count = lastCount++;
  140           }
  141       }
  142   
  143       /**
  144        * Creates a "well-known" <code>UID</code>.
  145        *
  146        * There are 2<sup>16</sup> possible such well-known ids.
  147        *
  148        * <p>A <code>UID</code> created via this constructor will not
  149        * clash with any <code>UID</code>s generated via the no-arg
  150        * constructor.
  151        *
  152        * @param   num number for well-known <code>UID</code>
  153        */
  154       public UID(short num) {
  155           unique = 0;
  156           time = 0;
  157           count = num;
  158       }
  159   
  160       /**
  161        * Constructs a <code>UID</code> given data read from a stream.
  162        */
  163       private UID(int unique, long time, short count) {
  164           this.unique = unique;
  165           this.time = time;
  166           this.count = count;
  167       }
  168   
  169       /**
  170        * Returns the hash code value for this <code>UID</code>.
  171        *
  172        * @return  the hash code value for this <code>UID</code>
  173        */
  174       public int hashCode() {
  175           return (int) time + (int) count;
  176       }
  177   
  178       /**
  179        * Compares the specified object with this <code>UID</code> for
  180        * equality.
  181        *
  182        * This method returns <code>true</code> if and only if the
  183        * specified object is a <code>UID</code> instance with the same
  184        * <code>unique</code>, <code>time</code>, and <code>count</code>
  185        * values as this one.
  186        *
  187        * @param   obj the object to compare this <code>UID</code> to
  188        *
  189        * @return  <code>true</code> if the given object is equivalent to
  190        * this one, and <code>false</code> otherwise
  191        */
  192       public boolean equals(Object obj) {
  193           if (obj instanceof UID) {
  194               UID uid = (UID) obj;
  195               return (unique == uid.unique &&
  196                       count == uid.count &&
  197                       time == uid.time);
  198           } else {
  199               return false;
  200           }
  201       }
  202   
  203       /**
  204        * Returns a string representation of this <code>UID</code>.
  205        *
  206        * @return  a string representation of this <code>UID</code>
  207        */
  208       public String toString() {
  209           return Integer.toString(unique,16) + ":" +
  210               Long.toString(time,16) + ":" +
  211               Integer.toString(count,16);
  212       }
  213   
  214       /**
  215        * Marshals a binary representation of this <code>UID</code> to
  216        * a <code>DataOutput</code> instance.
  217        *
  218        * <p>Specifically, this method first invokes the given stream's
  219        * {@link DataOutput#writeInt(int)} method with this <code>UID</code>'s
  220        * <code>unique</code> value, then it invokes the stream's
  221        * {@link DataOutput#writeLong(long)} method with this <code>UID</code>'s
  222        * <code>time</code> value, and then it invokes the stream's
  223        * {@link DataOutput#writeShort(int)} method with this <code>UID</code>'s
  224        * <code>count</code> value.
  225        *
  226        * @param   out the <code>DataOutput</code> instance to write
  227        * this <code>UID</code> to
  228        *
  229        * @throws  IOException if an I/O error occurs while performing
  230        * this operation
  231        */
  232       public void write(DataOutput out) throws IOException {
  233           out.writeInt(unique);
  234           out.writeLong(time);
  235           out.writeShort(count);
  236       }
  237   
  238       /**
  239        * Constructs and returns a new <code>UID</code> instance by
  240        * unmarshalling a binary representation from an
  241        * <code>DataInput</code> instance.
  242        *
  243        * <p>Specifically, this method first invokes the given stream's
  244        * {@link DataInput#readInt()} method to read a <code>unique</code> value,
  245        * then it invoke's the stream's
  246        * {@link DataInput#readLong()} method to read a <code>time</code> value,
  247        * then it invoke's the stream's
  248        * {@link DataInput#readShort()} method to read a <code>count</code> value,
  249        * and then it creates and returns a new <code>UID</code> instance
  250        * that contains the <code>unique</code>, <code>time</code>, and
  251        * <code>count</code> values that were read from the stream.
  252        *
  253        * @param   in the <code>DataInput</code> instance to read
  254        * <code>UID</code> from
  255        *
  256        * @return  unmarshalled <code>UID</code> instance
  257        *
  258        * @throws  IOException if an I/O error occurs while performing
  259        * this operation
  260        */
  261       public static UID read(DataInput in) throws IOException {
  262           int unique = in.readInt();
  263           long time = in.readLong();
  264           short count = in.readShort();
  265           return new UID(unique, time, count);
  266       }
  267   }

Save This Page
Home » openjdk-7 » java » rmi » server » [javadoc | source]