1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.commons.id.uuid;
18
19 import org.apache.commons.discovery.tools.DiscoverSingleton;
20 import org.apache.commons.id.IdentifierGenerator;
21 import org.apache.commons.id.uuid.clock.OverClockedException;
22 import org.apache.commons.id.uuid.state.Node;
23
24 /**
25 * Class is responsible for generating version 1 UUID's per RFC 4122.
26 * This class attempts to locate the machine's node identifier
27 * first by attempting to loading the properties file UUID.properties
28 * from the system classpath. If the UUID.properties file does not exist
29 * then the generator will create a node identifier from random information as
30 * defined in the
31 * <a href="ftp://ftp.rfc-editor.org/in-notes/rfc4122.txt">RFC 4122:
32 * A Universally Unique IDentifier (UUID) URN Namespace</a>.
33 *
34 * @author Commons-Id team
35 * @version $Revision: 480488 $ $Date: 2006-11-29 08:57:26 +0000 (Wed, 29 Nov 2006) $
36 *
37 */
38
39 public final class VersionOneGenerator implements IdentifierGenerator, Constants {
40
41 /** Positions 10-16: Length of node bytes */
42 private static final int NODE_ID_BYTE_LENGTH = 6;
43
44 /** Position 8: CLOCK_SEQ_LOW byte */
45 private static final int CLOCK_HI_VARIANT_BYTE8 = 8;
46 /** Position 9: CLOCK_SEQ_HIGH and VARIANT byte */
47 private static final int CLOCK_LOW_BYTE9 = 9;
48 /** Positions 10-16: Start of node bytes */
49 private static final int NODE_ID_BYTE10 = 10;
50
51 /** The default NodeManager implementation. */
52 private static final String DEFAULT_NODEMANAGER_IMPL = NodeManagerImpl.class.getName();
53
54 /** The NodeManager implementation */
55 private NodeManager manager;
56
57 /** Singleton instance such that only one instance is accessing the static
58 * fields at any time.
59 */
60 private static VersionOneGenerator generator;
61
62 /**
63 * <p>Private singleton constructor.</p>
64 */
65 private VersionOneGenerator() {
66 super();
67 manager = (NodeManager) DiscoverSingleton.find( NodeManager.class, DEFAULT_NODEMANAGER_IMPL);
68 }
69
70 /**
71 * <p>Returns the singleton instance of the version one UUID generator.</p>
72 *
73 * @return the singleton instance of the version one UUID generator.
74 */
75 public static VersionOneGenerator getInstance() {
76 if (generator == null) {
77 generator = new VersionOneGenerator();
78 }
79 return generator;
80 }
81
82 /**
83 * @see org.apache.commons.id.IdentifierGenerator#nextIdentifier()
84 */
85 public Object nextIdentifier() {
86 return nextUUID();
87 }
88
89 /**
90 * <p>Returns a new version 1 UUID. The method acts upons static variables
91 * and so should be sychronized.</p>
92 *
93 * @return Returns a new version 1 UUID.
94 */
95 public synchronized UUID nextUUID() {
96 byte[] rawUUID = new byte[UUID_BYTE_LENGTH];
97 long time = 0;
98 short clockSq = 0;
99 Node node = manager.currentNode();
100 while (time < 1) {
101 try {
102 manager.lockNode(node);
103 time = node.getUUIDTime();
104 clockSq = node.getClockSequence();
105 System.arraycopy(node.getNodeIdentifier(), 0, rawUUID, NODE_ID_BYTE10, NODE_ID_BYTE_LENGTH);
106 manager.releaseNode(node);
107 } catch (OverClockedException e) {
108 node = manager.nextAvailableNode();
109 } finally {
110 manager.releaseNode(node);
111 }
112 }
113 byte[] timeBytes = Bytes.toBytes(time);
114 //Copy time low
115 System.arraycopy(timeBytes, TIME_LOW_TS_POS, rawUUID, TIME_LOW_START_POS, TIME_LOW_BYTE_LEN);
116 //Copy time mid
117 System.arraycopy(timeBytes, TIME_MID_TS_POS, rawUUID, TIME_MID_START_POS, TIME_MID_BYTE_LEN);
118 //Copy time hi
119 System.arraycopy(timeBytes, TIME_HI_TS_POS, rawUUID, TIME_HI_START_POS, TIME_HI_BYTE_LEN);
120 //Set version
121 rawUUID[6] |= 0x10; // 0001 0000
122 //Set clock sequence
123 rawUUID[CLOCK_HI_VARIANT_BYTE8] = (byte) ((clockSq & 0x3F00) >>> 8);
124 rawUUID[CLOCK_HI_VARIANT_BYTE8] |= 0x80;
125 rawUUID[CLOCK_LOW_BYTE9] = (byte) (clockSq & 0xFF);
126
127 return new UUID(rawUUID);
128 }
129 }