1 package org.apache.turbine.util.db;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.io.ByteArrayOutputStream;
58 import java.io.OutputStream;
59 import java.util.StringTokenizer;
60 import javax.mail.internet.MimeUtility;
61 import org.apache.turbine.services.resources.TurbineResources;
62 import org.apache.turbine.util.Log;
63 import org.apache.turbine.util.TurbineException;
64
65 /***
66 * <p>This class generates universally unique id's in the form of a String.
67 * The id has three parts. The first is supposed to be location dependent.
68 * The preferred location parameter is an ethernet (MAC) address, but an IP
69 * can be used as well. if none is supplied a Math.random generated number
70 * will be used. This part of the key will be 48 bits in length.
71 * The second part of the key is time related and will be the lower 48 bits
72 * of the long used to signify the time since Jan. 1, 1970. This will
73 * cause key rollover in the year 6429.
74 * The preceding 12 bytes are Base64 encoded with the characters / and *
75 * replaced by _ (underscore) and - (dash). Resulting in 16 characters.
76 * Finally a counter is used to hand out 4095 keys in between each
77 * timestamp.
78 * The resulting id is a String of 18 characters including:
79 * a-z,A-Z,0-9, and the previously mentioned - and _.</p>
80 *
81 * <p>Note this class does not save any state information, so it is important
82 * that time only moves forward to keep the integrity of the ids. We
83 * might want to consider saving some state info.</p>
84 *
85 * <p>To specify the MAC/Ethernet address, add a uuid.address= property to the
86 * TurbineResources.properties file.</p>
87 *
88 * @author <a href="mailto:jmcnally@collab.net">John D. McNally</a>
89 * @version $Id: UUIdGenerator.java,v 1.4 2002/07/11 16:53:21 mpoeschl Exp $
90 */
91 public class UUIdGenerator
92 {
93 private static final String errorString = "uuid.address property in " +
94 "TurbineResources.properties should be a valid IP\n " +
95 "e.g. 18.2.3.100, or an ethernet address e.g. " +
96 "AE:10:3E:de:f5:77 uuid.address was ";
97
98 private byte[] address = new byte[6];
99 private String baseId = null;
100 private int counter = 0;
101
102 /***
103 * Constructor
104 */
105 public UUIdGenerator() throws TurbineException
106 {
107 String addr = TurbineResources.getString("uuid.address");
108 if (addr == null)
109 {
110 Log.info("UUIdGenerator is using a random number as the " +
111 "base for id's. This is not the best method for many " +
112 "purposes, but may be adequate in some circumstances." +
113 " Consider using an IP or ethernet (MAC) address if " +
114 "available. Edit TurbineResources.properties file and " +
115 "add a uuid.address= property.");
116
117 for (int i = 0; i < 6; i++)
118 {
119 address[i] = (byte) (255 * Math.random());
120 }
121 }
122 else
123 {
124 if (addr.indexOf(".") > 0)
125 {
126 // we should have an IP
127 StringTokenizer stok = new StringTokenizer(addr, ".");
128 if (stok.countTokens() != 4)
129 {
130 throw new TurbineException(errorString + addr);
131 }
132 // this is meant to insure that id's made from ip addresses
133 // will not conflict with MAC id's. I think MAC addresses
134 // will never have the highest bit set. Though this should
135 // be investigated further.
136 address[0] = (byte)255;
137 address[1] = (byte)255;
138 int i = 2;
139 try
140 {
141 while (stok.hasMoreTokens())
142 {
143 address[i++] =
144 Integer.valueOf(stok.nextToken(), 16).byteValue();
145 }
146 }
147 catch (Exception e)
148 {
149 throw new TurbineException(errorString + addr, e);
150 }
151 }
152 else if ( addr.indexOf(":") > 0 )
153 {
154 // we should have a MAC
155 StringTokenizer stok = new StringTokenizer(addr, ":");
156 if ( stok.countTokens() != 6 )
157 {
158 throw new TurbineException(errorString + addr);
159 }
160 int i = 0;
161 try
162 {
163 while (stok.hasMoreTokens())
164 {
165 address[i++] = Byte.parseByte(stok.nextToken(), 16);
166 }
167 }
168 catch (Exception e)
169 {
170 throw new TurbineException(errorString + addr, e);
171 }
172 }
173 else
174 {
175 throw new TurbineException(errorString + addr);
176 }
177 }
178 }
179 /***
180 * Generates the new base id
181 */
182 private final void generateNewBaseId() throws Exception
183 {
184 long now = System.currentTimeMillis();
185 byte[] nowBytes = org.apache.java.lang.Bytes.toBytes(now);
186 ByteArrayOutputStream bas = null;
187 OutputStream encodedStream = null;
188 try
189 {
190 bas = new ByteArrayOutputStream(16);
191 encodedStream = MimeUtility.encode(bas, "base64");
192 encodedStream.write(nowBytes);
193 baseId = bas.toString("ISO-8859-1"); // or maybe "US-ASCII"?
194 baseId = baseId.replace('/', '_');
195 baseId = baseId.replace('*', '-');
196 }
197 finally
198 {
199 if (bas != null)
200 {
201 bas.close();
202 }
203 if (encodedStream != null)
204 {
205 encodedStream.close();
206 }
207 }
208 }
209 /***
210 * Gets the id
211 * @return the 18 character id
212 */
213 public String getId() throws Exception
214 {
215 int index = ++counter;
216 if (index > 4095)
217 {
218 synchronized (this)
219 {
220 if (counter > 4095)
221 {
222 generateNewBaseId();
223 counter = 0;
224 }
225 else
226 {
227 index = ++counter;
228 }
229 }
230 }
231 StringBuffer idbuf = new StringBuffer(18);
232 idbuf.append(baseId);
233 idbuf.append(countChar[index / 64]);
234 idbuf.append(countChar[index % 64]);
235 return idbuf.toString();
236 }
237
238 /***
239 * characters used in the ID
240 */
241 private static final char[] countChar =
242 {
243 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
244 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
245 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
246 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','-','_'
247 };
248 }
249
This page was automatically generated by Maven