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