View Javadoc
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