1. /*
  2. * @(#)VMID.java 1.16 00/02/02
  3. *
  4. * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.rmi.dgc;
  11. import java.io.*;
  12. import java.net.*;
  13. import java.rmi.server.UID;
  14. import java.security.*;
  15. /**
  16. * A VMID is a identifier that is unique across all Java virtual
  17. * machines. VMIDs are used by the distributed garbage collector
  18. * to identify client VMs.
  19. *
  20. * @version 1.16, 02/02/00
  21. * @author Ann Wollrath
  22. * @author Peter Jones
  23. */
  24. public final class VMID implements java.io.Serializable {
  25. /** array of bytes uniquely identifying this host */
  26. private static byte[] localAddr = computeAddressHash();
  27. /**
  28. * @serial array of bytes uniquely identifying host created on
  29. */
  30. private byte[] addr;
  31. /**
  32. * @serial unique identifier with respect to host created on
  33. */
  34. private UID uid;
  35. /** indicate compatibility with JDK 1.1.x version of class */
  36. private static final long serialVersionUID = -538642295484486218L;
  37. /**
  38. * Create a new VMID. Each new VMID returned from this constructor
  39. * is unique for all Java virtual machines under the following
  40. * conditions: a) the conditions for uniqueness for objects of
  41. * the class <code>java.rmi.server.UID</code> are satisfied, and b) an
  42. * address can be obtained for this host that is unique and constant
  43. * for the lifetime of this object. <p>
  44. */
  45. public VMID() {
  46. addr = localAddr;
  47. uid = new UID();
  48. }
  49. /**
  50. * Return true if an accurate address can be determined for this
  51. * host. If false, reliable VMID cannot be generated from this host
  52. * @return true if host address can be determined, false otherwise
  53. * @deprecated
  54. */
  55. public static boolean isUnique() {
  56. return true;
  57. }
  58. /**
  59. * Compute hash code for this VMID.
  60. */
  61. public int hashCode() {
  62. return uid.hashCode();
  63. }
  64. /**
  65. * Compare this VMID to another, and return true if they are the
  66. * same identifier.
  67. */
  68. public boolean equals(Object obj) {
  69. if (obj instanceof VMID) {
  70. VMID vmid = (VMID) obj;
  71. if (!uid.equals(vmid.uid))
  72. return false;
  73. if ((addr == null) ^ (vmid.addr == null))
  74. return false;
  75. if (addr != null) {
  76. if (addr.length != vmid.addr.length)
  77. return false;
  78. for (int i = 0; i < addr.length; ++ i)
  79. if (addr[i] != vmid.addr[i])
  80. return false;
  81. }
  82. return true;
  83. } else {
  84. return false;
  85. }
  86. }
  87. /**
  88. * Return string representation of this VMID.
  89. */
  90. public String toString() {
  91. StringBuffer result = new StringBuffer();
  92. if (addr != null)
  93. for (int i = 0; i < addr.length; ++ i) {
  94. int x = (int) (addr[i] & 0xFF);
  95. result.append((x < 0x10 ? "0" : "") +
  96. Integer.toString(x, 16));
  97. }
  98. result.append(':');
  99. result.append(uid.toString());
  100. return result.toString();
  101. }
  102. /**
  103. * Compute the hash an IP address. The hash is the first 8 bytes
  104. * of the SHA digest of the IP address.
  105. */
  106. private static byte[] computeAddressHash() {
  107. /*
  108. * Get the local host's IP address.
  109. */
  110. byte[] addr = (byte[]) java.security.AccessController.doPrivileged(
  111. new PrivilegedAction() {
  112. public Object run() {
  113. try {
  114. return InetAddress.getLocalHost().getAddress();
  115. } catch (Exception e) {
  116. }
  117. return new byte[] { 0, 0, 0, 0 };
  118. }
  119. });
  120. byte[] addrHash;
  121. final int ADDR_HASH_LENGTH = 8;
  122. try {
  123. /*
  124. * Calculate message digest of IP address using SHA.
  125. */
  126. MessageDigest md = MessageDigest.getInstance("SHA");
  127. ByteArrayOutputStream sink = new ByteArrayOutputStream(64);
  128. DataOutputStream out = new DataOutputStream(
  129. new DigestOutputStream(sink, md));
  130. out.write(addr, 0, addr.length);
  131. out.flush();
  132. byte digest[] = md.digest();
  133. int hashlength = Math.min(ADDR_HASH_LENGTH, digest.length);
  134. addrHash = new byte[hashlength];
  135. System.arraycopy(digest, 0, addrHash, 0, hashlength);
  136. } catch (IOException ignore) {
  137. /* can't happen, but be deterministic anyway. */
  138. addrHash = new byte[0];
  139. } catch (NoSuchAlgorithmException complain) {
  140. throw new InternalError(complain.toString());
  141. }
  142. return addrHash;
  143. }
  144. }