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