2 * Copyright (c) 2001-2007 Sun Microsystems, Inc. All rights reserved.
4 * The Sun Project JXTA(TM) Software License
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * 3. The end-user documentation included with the redistribution, if any, must
17 * include the following acknowledgment: "This product includes software
18 * developed by Sun Microsystems, Inc. for JXTA(TM) technology."
19 * Alternately, this acknowledgment may appear in the software itself, if
20 * and wherever such third-party acknowledgments normally appear.
22 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
23 * not be used to endorse or promote products derived from this software
24 * without prior written permission. For written permission, please contact
25 * Project JXTA at http://www.jxta.org.
27 * 5. Products derived from this software may not be called "JXTA", nor may
28 * "JXTA" appear in their name, without prior written permission of Sun.
30 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
32 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN
33 * MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
36 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
39 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * JXTA is a registered trademark of Sun Microsystems, Inc. in the United
42 * States and other countries.
44 * Please see the license information page at :
45 * <http://www.jxta.org/project/www/license.html> for instructions on use of
46 * the license in source files.
48 * ====================================================================
50 * This software consists of voluntary contributions made by many individuals
51 * on behalf of Project JXTA. For more information on Project JXTA, please see
52 * http://www.jxta.org.
54 * This license is based on the BSD license adopted by the Apache Foundation.
57 package net.jxta.impl.id.UUID;
60 import java.security.SecureRandom;
61 import java.util.GregorianCalendar;
62 import java.util.Random;
63 import java.util.Calendar;
64 import java.util.TimeZone;
66 import java.util.logging.Logger;
67 import java.util.logging.Level;
68 import net.jxta.logging.Logging;
72 * A Factory for generating random UUIDs.
74 * @see net.jxta.impl.id.UUID.UUID
76 public final class UUIDFactory {
81 private static final transient Logger LOG = Logger.getLogger(UUIDFactory.class.getName());
84 * The point at which the Gregorian calendar rules are used, measured in
85 * milliseconds from the standard epoch. Default is October 15, 1582
86 * (Gregorian) 00:00:00 UTC or -12219292800000L.
88 static final long GREGORIAN_MILLIS_OFFSET = 12219292800000L;
91 * offset of this computer relative to utc
93 private long utc_offset = 0L;
96 * Time at which we last generated a version 1 UUID in relative
97 * milliseconds from 00:00:00.00, 15 October 1582 UTC.
99 private long lastTimeSequence = 0L;
102 * Count of how many version 1 UUIDs we have generated at this time
105 private long inSequenceCounter = 0L;
108 * pseudo random value to prevent clock collisions on the same computer.
110 private long clock_seq = 0L;
113 * pseudo random value. If available, this should be seeded with the MAC
114 * address of a local network interface.
116 private long node = 0L;
119 * Random number generator for UUID generation.
121 private Random randNum = null;
124 * We have to catch exceptions from construct of JRandom so we
125 * have to init it inline.
127 private static UUIDFactory factory = new UUIDFactory();
130 * Generate a new random UUID value. The UUID returned is a version 4 IETF
131 * variant random UUID.
133 * <p/>This member must be synchronized because it makes use of shared
136 * @return UUID returns a version 4 IETF variant random UUID.
138 public synchronized static UUID newUUID() {
140 return newUUID(factory.randNum.nextLong(), factory.randNum.nextLong());
144 * Returns a formatted time sequence field containing the elapsed time in
145 * 100 nano units since 00:00:00.00, 15 October 1582. Since the normal
146 * clock resolution is coarser than 100 nano than this value, the lower
147 * bits are generated in sequence for each call within the same milli.
149 * @return time sequence value
151 private synchronized long getTimeSequence() {
152 long now = (System.currentTimeMillis() - GREGORIAN_MILLIS_OFFSET + utc_offset) * 10000L; // convert to 100 nano units;
154 if (now > lastTimeSequence) {
155 lastTimeSequence = now;
156 // XXX bondolo@jxta.org It might be better to set this to a random
157 // value and just watch for rollover. The reason is that there may
158 // be more than one instance running on the same computer which is
159 // generating UUIDs, but is not excluded by our synchronization.
160 // A random value would reduce collisions.
161 inSequenceCounter = 0;
164 if (inSequenceCounter >= 10000L) {
165 // we allow the clock to skew forward rather than wait. It's
166 // really unlikely that anyone will be continuously generating
167 // more than 10k UUIDs per milli for very long.
168 lastTimeSequence += 10000L;
169 inSequenceCounter = 0;
173 return (lastTimeSequence + inSequenceCounter);
177 * Generate a new UUID value. The UUID returned is a version 1 IETF
180 * <p/>The node value used is currently a random value rather than the
181 * normal ethernet MAC address because the MAC address is not directly
182 * accessible in to java.
184 * @return UUID returns a version 1 IETF variant UUID.
186 public static UUID newSeqUUID() {
187 long mostSig = 0L, leastSig = 0L;
189 long timeSeq = factory.getTimeSequence();
191 mostSig |= (timeSeq & 0x0FFFFFFFFL) << 32;
192 mostSig |= ((timeSeq >> 32) & 0x0FFFFL) << 16;
193 mostSig |= (0x01L) << 12; // version 1;
194 mostSig |= ((timeSeq >> 48) & 0x00FFFL);
196 leastSig |= (0x02L) << 62; // ietf variant
197 leastSig |= ((factory.clock_seq >> 8) & 0x03FL) << 56;
198 leastSig |= (factory.clock_seq & 0x0FFL) << 48;
199 leastSig |= factory.node & 0x0FFFFFFFFFFFFL;
201 return new UUID(mostSig, leastSig);
205 * Generate a new UUID value. The values provided are masked to produce a
206 * version 4 IETF variant random UUID.
208 * @param bytes the 128 bits of the UUID
209 * @return UUID returns a version 4 IETF variant random UUID.
211 public static UUID newUUID(byte[] bytes) {
212 if (bytes.length != 16) {
213 throw new IllegalArgumentException("bytes must be 16 bytes in length");
218 for (int i = 0; i < 8; i++) {
219 mostSig = (mostSig << 8) | (bytes[i] & 0xff);
224 for (int i = 8; i < 16; i++) {
225 leastSig = (leastSig << 8) | (bytes[i] & 0xff);
228 return newUUID(mostSig, leastSig);
232 * Generate a new UUID value. The values provided are masked to produce a
233 * version 3 IETF variant UUID.
235 * @param mostSig High-long of UUID value.
236 * @param leastSig Low-long of UUID value.
237 * @return UUID returns a version 3 IETF variant random UUID.
239 public static UUID newHashUUID(long mostSig, long leastSig) {
241 mostSig &= 0xFFFFFFFFFFFF0FFFL;
242 mostSig |= 0x0000000000003000L; // version 3
243 leastSig &= 0x3FFFFFFFFFFFFFFFL;
244 leastSig |= 0x8000000000000000L; // IETF variant
246 return new UUID(mostSig, leastSig);
250 * Generate a new UUID value. The values provided are masked to produce a
251 * version 4 IETF variant random UUID.
253 * @param mostSig High-long of UUID value.
254 * @param leastSig Low-long of UUID value.
255 * @return UUID returns a version 4 IETF variant random UUID.
257 public static UUID newUUID(long mostSig, long leastSig) {
259 mostSig &= 0xFFFFFFFFFFFF0FFFL;
260 mostSig |= 0x0000000000004000L; // version 4
261 leastSig &= 0x3FFFFFFFFFFFFFFFL;
262 leastSig |= 0x8000000000000000L; // IETF variant
264 leastSig &= 0xFFFF7FFFFFFFFFFFL;
265 leastSig |= 0x0000800000000000L; // multicast bit
267 return new UUID(mostSig, leastSig);
273 private UUIDFactory() {
275 randNum = new SecureRandom();
277 String[] tz_ids = TimeZone.getAvailableIDs(0);
278 Calendar gregorianCalendar = new GregorianCalendar();
280 // FIXME 20031024 bondolo@jxta.org In theory we should be doing this
281 // EVERY time we generate a UUID. In practice because of we use a random
282 // clock_seq we don't have to.
283 utc_offset = gregorianCalendar.get(Calendar.ZONE_OFFSET) + gregorianCalendar.get(Calendar.DST_OFFSET);
285 // Generate a random clock seq
286 clock_seq = randNum.nextInt() & 0x03FFL;
288 // Generate a random node ID since we can't get the MAC Address
289 node = (randNum.nextLong() & 0x0000FFFFFFFFFFFFL);
290 node |= 0x0000800000000000L; // mask in the multicast bit since we don't know if its unique.