1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
|
12 | |
|
13 | |
|
14 | |
|
15 | |
|
16 | |
|
17 | |
|
18 | |
package org.apache.commons.id.uuid.state; |
19 | |
|
20 | |
import java.io.IOException; |
21 | |
import java.net.InetAddress; |
22 | |
import java.net.UnknownHostException; |
23 | |
import java.util.Collection; |
24 | |
import java.util.Iterator; |
25 | |
import java.util.Random; |
26 | |
import java.util.StringTokenizer; |
27 | |
|
28 | |
import org.apache.commons.id.DecoderException; |
29 | |
import org.apache.commons.discovery.tools.DiscoverClass; |
30 | |
import org.apache.commons.id.uuid.Bytes; |
31 | |
import org.apache.commons.id.uuid.Constants; |
32 | |
import org.apache.commons.id.uuid.clock.Clock; |
33 | |
import org.apache.commons.id.uuid.clock.OverClockedException; |
34 | |
import org.apache.commons.id.DigestUtils; |
35 | |
import org.apache.commons.id.Hex; |
36 | |
|
37 | |
|
38 | |
|
39 | |
|
40 | |
|
41 | |
|
42 | |
|
43 | |
|
44 | |
public final class StateHelper implements Constants { |
45 | |
|
46 | 3 | public static final String UUID_CLOCK_IMPL_PROPERTY_KEY = Clock.class.getName(); |
47 | |
|
48 | |
|
49 | 1 | public static final String UUID_STATE_IMPL_PROPERTY_KEY = State.class.getName(); |
50 | |
|
51 | |
|
52 | |
public static final int NODE_ID_BYTE_LENGTH = 6; |
53 | |
|
54 | |
|
55 | |
public static final short BYTES_IN_SHORT = 2; |
56 | |
|
57 | |
|
58 | |
public static final short SHIFT_BY_BYTE = 8; |
59 | |
|
60 | |
|
61 | |
public static final short HOSTNAME_MAX_CHAR_LEN = 255; |
62 | |
|
63 | |
|
64 | |
private static final int MULTICAST_BIT_SET = 0x80; |
65 | |
|
66 | |
|
67 | |
private static final short LONG_CHAR_LEN = 19; |
68 | |
|
69 | |
|
70 | |
private static final int BUF_PAGE_SZ = 1024; |
71 | |
|
72 | |
|
73 | |
protected static final String XML_DOC_START = "<?xml version=\"1.0\"" |
74 | |
+ " encoding=\"UTF-8\" ?>" |
75 | |
+ "\n<!DOCTYPE uuidstate [\n" |
76 | |
+ " <!ELEMENT uuidstate (node*)>\n" |
77 | |
+ " <!ELEMENT node EMPTY>\n" |
78 | |
+ " <!ATTLIST node id ID #REQUIRED>\n" |
79 | |
+ " <!ATTLIST node clocksequence CDATA #IMPLIED>\n" |
80 | |
+ " <!ATTLIST node lasttimestamp CDATA #IMPLIED>\n]>" |
81 | |
+ "\n<uuidstate synchInterval=\""; |
82 | |
|
83 | |
|
84 | |
protected static final String XML_DOC_START_END = "\">"; |
85 | |
|
86 | |
protected static final String XML_NODE_TAG_START = "\n\t<node id=\""; |
87 | |
|
88 | |
protected static final String XML_NODE_TAG_AFTER_ID = "\" clocksequence=\""; |
89 | |
|
90 | |
protected static final String XML_NODE_TAG_AFTER_CSEQ = "\" timestamp=\""; |
91 | |
|
92 | |
protected static final String XML_NODE_TAG_END = "\" />"; |
93 | |
|
94 | |
protected static final String XML_DOC_END = "\n</uuidstate>"; |
95 | |
|
96 | |
|
97 | |
private static final short MAC_ADDRESS_TOKEN_COUNT = 6; |
98 | |
|
99 | |
|
100 | |
private static final short MAC_ADDRESS_CHAR_LENGTH = 17; |
101 | |
|
102 | |
|
103 | |
private StateHelper() { |
104 | 0 | super(); |
105 | 0 | } |
106 | |
|
107 | |
|
108 | |
|
109 | |
|
110 | |
|
111 | |
|
112 | |
|
113 | |
public static byte[] randomNodeIdentifier() { |
114 | |
|
115 | 4 | byte[] seed = new byte[UUID_BYTE_LENGTH]; |
116 | |
|
117 | |
|
118 | 4 | int bufSize = (LONG_CHAR_LEN * 2) + HOSTNAME_MAX_CHAR_LEN + (2 * BUF_PAGE_SZ); |
119 | 4 | StringBuffer randInfo = new StringBuffer(bufSize); |
120 | |
|
121 | 4 | long time = 0; |
122 | |
try { |
123 | 4 | time = getClockImpl().getUUIDTime(); |
124 | 0 | } catch (OverClockedException oce) { |
125 | 0 | time = System.currentTimeMillis(); |
126 | 1 | } |
127 | 1 | randInfo.append(time); |
128 | |
|
129 | |
|
130 | |
try { |
131 | 1 | InetAddress address = InetAddress.getLocalHost(); |
132 | 1 | randInfo.append(address.getHostName()); |
133 | 0 | } catch (UnknownHostException ukhe) { |
134 | 0 | randInfo.append("Host Unknown"); |
135 | 1 | } |
136 | |
|
137 | 1 | randInfo.append(new Object().hashCode()); |
138 | |
|
139 | |
|
140 | 1 | Collection info = System.getProperties().values(); |
141 | 1 | Iterator it = info.iterator(); |
142 | 2 | while (it.hasNext()) { |
143 | 1 | randInfo.append(it.next()); |
144 | 1 | } |
145 | |
|
146 | 1 | seed = DigestUtils.md5(randInfo.toString()); |
147 | |
|
148 | |
|
149 | 1 | byte[] raw = new byte[NODE_ID_BYTE_LENGTH]; |
150 | 1 | System.arraycopy(seed, 0, raw, 0, NODE_ID_BYTE_LENGTH); |
151 | |
|
152 | |
|
153 | 1 | raw[0] |= MULTICAST_BIT_SET; |
154 | |
|
155 | 1 | return raw; |
156 | |
} |
157 | |
|
158 | |
|
159 | |
|
160 | |
|
161 | |
|
162 | |
|
163 | |
public static short newClockSequence() { |
164 | 11 | Random random = new Random(); |
165 | 11 | byte[] bytes = new byte[BYTES_IN_SHORT]; |
166 | 11 | random.nextBytes(bytes); |
167 | 11 | return (short) (Bytes.toShort(bytes) & 0x3FFF); |
168 | |
} |
169 | |
|
170 | |
|
171 | |
|
172 | |
|
173 | |
|
174 | |
|
175 | |
public static Clock getClockImpl() { |
176 | 32 | Clock c = null; |
177 | |
try { |
178 | 32 | DiscoverClass dc = new DiscoverClass(); |
179 | 32 | c = (Clock) dc.newInstance( |
180 | |
Clock.class, |
181 | |
Clock.DEFAULT_CLOCK_IMPL); |
182 | 0 | } catch (Exception ex) { |
183 | |
|
184 | 32 | } |
185 | 32 | return c; |
186 | |
} |
187 | |
|
188 | |
|
189 | |
|
190 | |
|
191 | |
|
192 | |
|
193 | |
public static State getStateImpl() { |
194 | 5 | State s = null; |
195 | |
try { |
196 | 5 | DiscoverClass dc = new DiscoverClass(); |
197 | 5 | s = (State) dc.newInstance( |
198 | |
State.class, |
199 | |
State.DEFAULT_STATE_IMPL); |
200 | 0 | } catch (Exception ex) { |
201 | |
|
202 | 5 | } |
203 | 5 | return s; |
204 | |
} |
205 | |
|
206 | |
|
207 | |
|
208 | |
|
209 | |
|
210 | |
|
211 | |
|
212 | |
|
213 | |
|
214 | |
|
215 | |
public static byte[] decodeMACAddress(String address) { |
216 | 25 | StringBuffer buf = new StringBuffer(MAC_ADDRESS_TOKEN_COUNT * 2); |
217 | 25 | StringTokenizer tokens = new StringTokenizer(address, "-"); |
218 | 25 | if (tokens.countTokens() != MAC_ADDRESS_TOKEN_COUNT) { |
219 | 0 | return null; |
220 | |
} else { |
221 | 175 | for (int i = 0; i < MAC_ADDRESS_TOKEN_COUNT; i++) { |
222 | 150 | buf.append(tokens.nextToken()); |
223 | |
} |
224 | |
} |
225 | |
try { |
226 | 25 | char[] c = buf.toString().toCharArray(); |
227 | 25 | return Hex.decodeHex(c); |
228 | 0 | } catch (DecoderException de) { |
229 | 0 | de.printStackTrace(); |
230 | 0 | return null; |
231 | |
} |
232 | |
} |
233 | |
|
234 | |
|
235 | |
|
236 | |
|
237 | |
|
238 | |
|
239 | |
|
240 | |
|
241 | |
|
242 | |
|
243 | |
|
244 | |
public static String encodeMACAddress(byte[] address) throws IOException { |
245 | 11 | char[] chars = Hex.encodeHex(address); |
246 | 11 | StringBuffer buf = new StringBuffer(MAC_ADDRESS_CHAR_LENGTH); |
247 | 143 | for (int i = 0; i < chars.length; i++) { |
248 | 132 | buf.append(chars[i]); |
249 | 132 | if (i != chars.length - 1 && i % 2 != 0) { |
250 | 55 | buf.append("-"); |
251 | |
} |
252 | |
} |
253 | 11 | return buf.toString().toUpperCase(); |
254 | |
} |
255 | |
} |