1. /*
  2. * @(#)VMID.java 1.18 03/01/23
  3. *
  4. * Copyright 2003 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.18, 01/23/03
  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. * @deprecated
  51. */
  52. public static boolean isUnique() {
  53. return true;
  54. }
  55. /**
  56. * Compute hash code for this VMID.
  57. */
  58. public int hashCode() {
  59. return uid.hashCode();
  60. }
  61. /**
  62. * Compare this VMID to another, and return true if they are the
  63. * same identifier.
  64. */
  65. public boolean equals(Object obj) {
  66. if (obj instanceof VMID) {
  67. VMID vmid = (VMID) obj;
  68. if (!uid.equals(vmid.uid))
  69. return false;
  70. if ((addr == null) ^ (vmid.addr == null))
  71. return false;
  72. if (addr != null) {
  73. if (addr.length != vmid.addr.length)
  74. return false;
  75. for (int i = 0; i < addr.length; ++ i)
  76. if (addr[i] != vmid.addr[i])
  77. return false;
  78. }
  79. return true;
  80. } else {
  81. return false;
  82. }
  83. }
  84. /**
  85. * Return string representation of this VMID.
  86. */
  87. public String toString() {
  88. StringBuffer result = new StringBuffer();
  89. if (addr != null)
  90. for (int i = 0; i < addr.length; ++ i) {
  91. int x = (int) (addr[i] & 0xFF);
  92. result.append((x < 0x10 ? "0" : "") +
  93. Integer.toString(x, 16));
  94. }
  95. result.append(':');
  96. result.append(uid.toString());
  97. return result.toString();
  98. }
  99. /**
  100. * Compute the hash an IP address. The hash is the first 8 bytes
  101. * of the SHA digest of the IP address.
  102. */
  103. private static byte[] computeAddressHash() {
  104. /*
  105. * Get the local host's IP address.
  106. */
  107. byte[] addr = (byte[]) java.security.AccessController.doPrivileged(
  108. new PrivilegedAction() {
  109. public Object run() {
  110. try {
  111. return InetAddress.getLocalHost().getAddress();
  112. } catch (Exception e) {
  113. }
  114. return new byte[] { 0, 0, 0, 0 };
  115. }
  116. });
  117. byte[] addrHash;
  118. final int ADDR_HASH_LENGTH = 8;
  119. try {
  120. /*
  121. * Calculate message digest of IP address using SHA.
  122. */
  123. MessageDigest md = MessageDigest.getInstance("SHA");
  124. ByteArrayOutputStream sink = new ByteArrayOutputStream(64);
  125. DataOutputStream out = new DataOutputStream(
  126. new DigestOutputStream(sink, md));
  127. out.write(addr, 0, addr.length);
  128. out.flush();
  129. byte digest[] = md.digest();
  130. int hashlength = Math.min(ADDR_HASH_LENGTH, digest.length);
  131. addrHash = new byte[hashlength];
  132. System.arraycopy(digest, 0, addrHash, 0, hashlength);
  133. } catch (IOException ignore) {
  134. /* can't happen, but be deterministic anyway. */
  135. addrHash = new byte[0];
  136. } catch (NoSuchAlgorithmException complain) {
  137. throw new InternalError(complain.toString());
  138. }
  139. return addrHash;
  140. }
  141. }