KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > util > IDUtil


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.util;
21
22 import java.net.UnknownHostException JavaDoc;
23 import java.security.MessageDigest JavaDoc;
24 import java.security.NoSuchAlgorithmException JavaDoc;
25
26 import org.apache.cayenne.CayenneRuntimeException;
27
28 /**
29  * helper class to generate pseudo-GUID sequences.
30  *
31  * @author Andrus Adamchik
32  */

33 public class IDUtil {
34     
35     private static final int BITMASK_0 = 0xff;
36     private static final int BITMASK_1 = 0xff << 8;
37     private static final int BITMASK_2 = 0xff << 16;
38     private static final int BITMASK_3 = 0xff << 24;
39     private static final int BITMASK_4 = 0xff << 32;
40     private static final int BITMASK_5 = 0xff << 40;
41     private static final int BITMASK_6 = 0xff << 48;
42     private static final int BITMASK_7 = 0xff << 56;
43
44     // this id sequence needs to be long enough to feel
45
// the gap within the same timestamp millisecond
46
private static volatile int currentId;
47
48     private static MessageDigest JavaDoc md;
49     private static byte[] ipAddress;
50
51     static {
52         try {
53             md = MessageDigest.getInstance("MD5");
54         }
55         catch (NoSuchAlgorithmException JavaDoc e) {
56             throw new CayenneRuntimeException("Can't initialize MessageDigest.", e);
57         }
58
59         try {
60             ipAddress = java.net.InetAddress.getLocalHost().getAddress();
61         }
62         catch (UnknownHostException JavaDoc e) {
63             // use loopback interface
64
ipAddress = new byte[] {
65                     127, 0, 0, 1
66             };
67         }
68     }
69
70     /**
71      * Prints a byte value to a StringBuffer as a double digit hex value.
72      *
73      * @since 1.2
74      */

75     public static void appendFormattedByte(StringBuffer JavaDoc buffer, byte byteValue) {
76         final String JavaDoc digits = "0123456789ABCDEF";
77
78         buffer.append(digits.charAt((byteValue >>> 4) & 0xF));
79         buffer.append(digits.charAt(byteValue & 0xF));
80     }
81
82     /**
83      * @param length the length of returned byte[]
84      * @return A pseudo-unique byte array of the specified length. Length must be at least
85      * 16 bytes, or an exception is thrown.
86      * @since 1.0.2
87      */

88     public synchronized static byte[] pseudoUniqueByteSequence(int length) {
89         if (length < 16) {
90             throw new IllegalArgumentException JavaDoc(
91                     "Can't generate unique byte sequence shorter than 16 bytes: "
92                             + length);
93         }
94
95         if (length == 16) {
96             return pseudoUniqueByteSequence16();
97         }
98
99         byte[] bytes = new byte[length];
100         for (int i = 0; i <= length - 16; i += 16) {
101             byte[] nextSequence = pseudoUniqueByteSequence16();
102             System.arraycopy(nextSequence, 0, bytes, i, 16);
103         }
104
105         // leftovers?
106
int leftoverLen = length % 16;
107         if (leftoverLen > 0) {
108             byte[] nextSequence = pseudoUniqueByteSequence16();
109             System.arraycopy(nextSequence, 0, bytes, length - leftoverLen, leftoverLen);
110         }
111
112         return bytes;
113     }
114
115     public synchronized static byte[] pseudoUniqueSecureByteSequence(int length) {
116         if (length < 16) {
117             throw new IllegalArgumentException JavaDoc(
118                     "Can't generate unique byte sequence shorter than 16 bytes: "
119                             + length);
120         }
121
122         if (length == 16) {
123             return pseudoUniqueSecureByteSequence16();
124         }
125
126         byte[] bytes = new byte[length];
127         for (int i = 0; i <= length - 16; i += 16) {
128             byte[] nextSequence = pseudoUniqueSecureByteSequence16();
129             System.arraycopy(nextSequence, 0, bytes, i, 16);
130         }
131
132         // leftovers?
133
int leftoverLen = length % 16;
134         if (leftoverLen > 0) {
135             byte[] nextSequence = pseudoUniqueSecureByteSequence16();
136             System.arraycopy(nextSequence, 0, bytes, length - leftoverLen, leftoverLen);
137         }
138
139         return bytes;
140     }
141
142     public static final byte[] pseudoUniqueByteSequence8() {
143         byte[] bytes = new byte[8];
144
145         // bytes 0..2 - incrementing #
146
// bytes 3..5 - timestamp high bytes
147
// bytes 6..7 - IP address
148

149         int nextInt = nextInt();
150
151         bytes[0] = (byte) ((nextInt & (0xff << 16)) >>> 16);
152         bytes[1] = (byte) ((nextInt & (0xff << 8)) >>> 8);
153         bytes[2] = (byte) (nextInt & 0xff);
154
155         // append 3 high bytes of timestamp
156

157         long t = System.currentTimeMillis();
158
159         bytes[3] = (byte) ((t & BITMASK_2) >>> 16);
160         bytes[4] = (byte) ((t & BITMASK_1) >>> 8);
161         bytes[5] = (byte) (t & BITMASK_0);
162
163         // append 2 last bytes of IP address
164
System.arraycopy(ipAddress, 2, bytes, 6, 2);
165         return bytes;
166     }
167
168     /**
169      * @return A pseudo unique 16-byte array.
170      */

171     public static final byte[] pseudoUniqueByteSequence16() {
172         byte[] bytes = new byte[16];
173
174         // bytes 0..3 - incrementing #
175
// bytes 4..11 - timestamp
176
// bytes 12..15 - IP address
177

178         int nextInt = nextInt();
179
180         bytes[0] = (byte) ((nextInt & BITMASK_3) >>> 24);
181         bytes[1] = (byte) ((nextInt & BITMASK_2) >>> 16);
182         bytes[2] = (byte) ((nextInt & BITMASK_1) >>> 8);
183         bytes[3] = (byte) (nextInt & BITMASK_0);
184
185         long t = System.currentTimeMillis();
186
187         bytes[4] = (byte) ((t & BITMASK_7) >>> 56);
188         bytes[5] = (byte) ((t & BITMASK_6) >>> 48);
189         bytes[6] = (byte) ((t & BITMASK_5) >>> 40);
190         bytes[7] = (byte) ((t & BITMASK_4) >>> 32);
191         bytes[8] = (byte) ((t & BITMASK_3) >>> 24);
192         bytes[9] = (byte) ((t & BITMASK_2) >>> 16);
193         bytes[10] = (byte) ((t & BITMASK_1) >>> 8);
194         bytes[11] = (byte) (t & BITMASK_0);
195
196         System.arraycopy(ipAddress, 0, bytes, 12, 4);
197         return bytes;
198     }
199
200     /**
201      * @return A pseudo unique digested 16-byte array.
202      */

203     public static byte[] pseudoUniqueSecureByteSequence16() {
204         byte[] bytes = pseudoUniqueByteSequence16();
205
206         synchronized (md) {
207             return md.digest(bytes);
208         }
209     }
210
211     private static final int nextInt() {
212         if (currentId == Integer.MAX_VALUE) {
213             currentId = 0;
214         }
215
216         return currentId++;
217     }
218
219     private IDUtil() {
220     }
221 }
222
Popular Tags