001 /*
002 * Copyright 1996-2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.rmi.dgc;
027
028 import java.io.*;
029 import java.net.*;
030 import java.rmi.server.UID;
031 import java.security.*;
032
033 /**
034 * A VMID is a identifier that is unique across all Java virtual
035 * machines. VMIDs are used by the distributed garbage collector
036 * to identify client VMs.
037 *
038 * @version 1.27, 05/05/07
039 * @author Ann Wollrath
040 * @author Peter Jones
041 */
042 public final class VMID implements java.io.Serializable {
043
044 /** array of bytes uniquely identifying this host */
045 private static byte[] localAddr = computeAddressHash();
046
047 /**
048 * @serial array of bytes uniquely identifying host created on
049 */
050 private byte[] addr;
051
052 /**
053 * @serial unique identifier with respect to host created on
054 */
055 private UID uid;
056
057 /** indicate compatibility with JDK 1.1.x version of class */
058 private static final long serialVersionUID = -538642295484486218L;
059
060 /**
061 * Create a new VMID. Each new VMID returned from this constructor
062 * is unique for all Java virtual machines under the following
063 * conditions: a) the conditions for uniqueness for objects of
064 * the class <code>java.rmi.server.UID</code> are satisfied, and b) an
065 * address can be obtained for this host that is unique and constant
066 * for the lifetime of this object. <p>
067 */
068 public VMID() {
069 addr = localAddr;
070 uid = new UID();
071 }
072
073 /**
074 * Return true if an accurate address can be determined for this
075 * host. If false, reliable VMID cannot be generated from this host
076 * @return true if host address can be determined, false otherwise
077 * @deprecated
078 */
079 @Deprecated
080 public static boolean isUnique() {
081 return true;
082 }
083
084 /**
085 * Compute hash code for this VMID.
086 */
087 public int hashCode() {
088 return uid.hashCode();
089 }
090
091 /**
092 * Compare this VMID to another, and return true if they are the
093 * same identifier.
094 */
095 public boolean equals(Object obj) {
096 if (obj instanceof VMID) {
097 VMID vmid = (VMID) obj;
098 if (!uid.equals(vmid.uid))
099 return false;
100 if ((addr == null) ^ (vmid.addr == null))
101 return false;
102 if (addr != null) {
103 if (addr.length != vmid.addr.length)
104 return false;
105 for (int i = 0; i < addr.length; ++i)
106 if (addr[i] != vmid.addr[i])
107 return false;
108 }
109 return true;
110 } else {
111 return false;
112 }
113 }
114
115 /**
116 * Return string representation of this VMID.
117 */
118 public String toString() {
119 StringBuffer result = new StringBuffer();
120 if (addr != null)
121 for (int i = 0; i < addr.length; ++i) {
122 int x = (int) (addr[i] & 0xFF);
123 result.append((x < 0x10 ? "0" : "")
124 + Integer.toString(x, 16));
125 }
126 result.append(':');
127 result.append(uid.toString());
128 return result.toString();
129 }
130
131 /**
132 * Compute the hash an IP address. The hash is the first 8 bytes
133 * of the SHA digest of the IP address.
134 */
135 private static byte[] computeAddressHash() {
136
137 /*
138 * Get the local host's IP address.
139 */
140 byte[] addr = (byte[]) java.security.AccessController
141 .doPrivileged(new PrivilegedAction() {
142 public Object run() {
143 try {
144 return InetAddress.getLocalHost()
145 .getAddress();
146 } catch (Exception e) {
147 }
148 return new byte[] { 0, 0, 0, 0 };
149 }
150 });
151
152 byte[] addrHash;
153 final int ADDR_HASH_LENGTH = 8;
154
155 try {
156 /*
157 * Calculate message digest of IP address using SHA.
158 */
159 MessageDigest md = MessageDigest.getInstance("SHA");
160 ByteArrayOutputStream sink = new ByteArrayOutputStream(64);
161 DataOutputStream out = new DataOutputStream(
162 new DigestOutputStream(sink, md));
163 out.write(addr, 0, addr.length);
164 out.flush();
165
166 byte digest[] = md.digest();
167 int hashlength = Math.min(ADDR_HASH_LENGTH, digest.length);
168 addrHash = new byte[hashlength];
169 System.arraycopy(digest, 0, addrHash, 0, hashlength);
170
171 } catch (IOException ignore) {
172 /* can't happen, but be deterministic anyway. */
173 addrHash = new byte[0];
174 } catch (NoSuchAlgorithmException complain) {
175 throw new InternalError(complain.toString());
176 }
177 return addrHash;
178 }
179 }
|