1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
26
27
28
29
30
31
32
33
34
35
36
37
38
39 public final class VersionOneGenerator implements IdentifierGenerator, Constants {
40
41
42 private static final int NODE_ID_BYTE_LENGTH = 6;
43
44
45 private static final int CLOCK_HI_VARIANT_BYTE8 = 8;
46
47 private static final int CLOCK_LOW_BYTE9 = 9;
48
49 private static final int NODE_ID_BYTE10 = 10;
50
51
52 private static final String DEFAULT_NODEMANAGER_IMPL = NodeManagerImpl.class.getName();
53
54
55 private NodeManager manager;
56
57
58
59
60 private static VersionOneGenerator generator;
61
62
63
64
65 private VersionOneGenerator() {
66 super();
67 manager = (NodeManager) DiscoverSingleton.find( NodeManager.class, DEFAULT_NODEMANAGER_IMPL);
68 }
69
70
71
72
73
74
75 public static VersionOneGenerator getInstance() {
76 if (generator == null) {
77 generator = new VersionOneGenerator();
78 }
79 return generator;
80 }
81
82
83
84
85 public Object nextIdentifier() {
86 return nextUUID();
87 }
88
89
90
91
92
93
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
115 System.arraycopy(timeBytes, TIME_LOW_TS_POS, rawUUID, TIME_LOW_START_POS, TIME_LOW_BYTE_LEN);
116
117 System.arraycopy(timeBytes, TIME_MID_TS_POS, rawUUID, TIME_MID_START_POS, TIME_MID_BYTE_LEN);
118
119 System.arraycopy(timeBytes, TIME_HI_TS_POS, rawUUID, TIME_HI_START_POS, TIME_HI_BYTE_LEN);
120
121 rawUUID[6] |= 0x10;
122
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 }