Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
VersionOneGenerator |
|
| 1.75;1.75 |
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 | 3 | 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 | 1 | super(); |
67 | 1 | manager = (NodeManager) DiscoverSingleton.find( NodeManager.class, DEFAULT_NODEMANAGER_IMPL); |
68 | 1 | } |
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 | 1 | if (generator == null) { |
77 | 1 | generator = new VersionOneGenerator(); |
78 | } | |
79 | 1 | return generator; |
80 | } | |
81 | ||
82 | /** | |
83 | * @see org.apache.commons.id.IdentifierGenerator#nextIdentifier() | |
84 | */ | |
85 | public Object nextIdentifier() { | |
86 | 0 | 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 | 1 | byte[] rawUUID = new byte[UUID_BYTE_LENGTH]; |
97 | 1 | long time = 0; |
98 | 1 | short clockSq = 0; |
99 | 1 | Node node = manager.currentNode(); |
100 | 2 | while (time < 1) { |
101 | try { | |
102 | 1 | manager.lockNode(node); |
103 | 1 | time = node.getUUIDTime(); |
104 | 1 | clockSq = node.getClockSequence(); |
105 | 1 | System.arraycopy(node.getNodeIdentifier(), 0, rawUUID, NODE_ID_BYTE10, NODE_ID_BYTE_LENGTH); |
106 | 1 | manager.releaseNode(node); |
107 | 0 | } catch (OverClockedException e) { |
108 | 0 | node = manager.nextAvailableNode(); |
109 | } finally { | |
110 | 1 | manager.releaseNode(node); |
111 | 1 | } |
112 | 1 | } |
113 | 1 | byte[] timeBytes = Bytes.toBytes(time); |
114 | //Copy time low | |
115 | 1 | System.arraycopy(timeBytes, TIME_LOW_TS_POS, rawUUID, TIME_LOW_START_POS, TIME_LOW_BYTE_LEN); |
116 | //Copy time mid | |
117 | 1 | System.arraycopy(timeBytes, TIME_MID_TS_POS, rawUUID, TIME_MID_START_POS, TIME_MID_BYTE_LEN); |
118 | //Copy time hi | |
119 | 1 | System.arraycopy(timeBytes, TIME_HI_TS_POS, rawUUID, TIME_HI_START_POS, TIME_HI_BYTE_LEN); |
120 | //Set version | |
121 | 1 | rawUUID[6] |= 0x10; // 0001 0000 |
122 | //Set clock sequence | |
123 | 1 | rawUUID[CLOCK_HI_VARIANT_BYTE8] = (byte) ((clockSq & 0x3F00) >>> 8); |
124 | 1 | rawUUID[CLOCK_HI_VARIANT_BYTE8] |= 0x80; |
125 | 1 | rawUUID[CLOCK_LOW_BYTE9] = (byte) (clockSq & 0xFF); |
126 | ||
127 | 1 | return new UUID(rawUUID); |
128 | } | |
129 | } |