Java Tutorial/Development/UUID
Содержание
- 1 Create your own basic UUID
- 2 Generates a UUID
- 3 Generates random UUIDs
- 4 Generator for Globally unique Strings
- 5 Get a unique identifier Using java.rmi.dgc.VMID
- 6 ID generator
- 7 Random GUID
- 8 Session ID generator
- 9 Using java.util.concurrent.AtomicLong: A numerical id, start at zero and increment by one.
- 10 Using java.util.UUID
- 11 UUID generator
Create your own basic UUID
/*
Derby - Class org.apache.derby.impl.services.uuid.BasicUUID
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to you under the Apache License, Version 2.0
(the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.StringReader;
public class BasicUUID {
/*
* * Fields of BasicUUID
*/
private long majorId; // only using 48 bits
private long timemillis;
private int sequence;
/*
* * Methods of BasicUUID
*/
/**
* Constructor only called by BasicUUIDFactory.
*/
public BasicUUID(long majorId, long timemillis, int sequence) {
this.majorId = majorId;
this.timemillis = timemillis;
this.sequence = sequence;
}
/**
* Constructor only called by BasicUUIDFactory. Constructs a UUID from the
* string representation produced by toString.
*
* @see BasicUUID#toString
*/
public BasicUUID(String uuidstring) {
StringReader sr = new StringReader(uuidstring);
sequence = (int) readMSB(sr);
long ltimemillis = readMSB(sr) << 32;
ltimemillis += readMSB(sr) << 16;
ltimemillis += readMSB(sr);
timemillis = ltimemillis;
majorId = readMSB(sr);
}
/**
* Constructor only called by BasicUUIDFactory. Constructs a UUID from the
* byte array representation produced by toByteArrayio.
*
* @see BasicUUID#toByteArray
*/
public BasicUUID(byte[] b) {
int lsequence = 0;
for (int ix = 0; ix < 4; ix++) {
lsequence = lsequence << 8;
lsequence = lsequence | (0xff & b[ix]);
}
long ltimemillis = 0;
for (int ix = 4; ix < 10; ix++) {
ltimemillis = ltimemillis << 8;
ltimemillis = ltimemillis | (0xff & b[ix]);
}
long linetaddr = 0;
for (int ix = 10; ix < 16; ix++) {
linetaddr = linetaddr << 8;
linetaddr = linetaddr | (0xff & b[ix]);
}
sequence = lsequence;
timemillis = ltimemillis;
majorId = linetaddr;
}
/*
* Formatable methods
*/
// no-arg constructor, required by Formatable
public BasicUUID() {
super();
}
/**
* Write this out.
*
* @exception IOException
* error writing to log stream
*/
public void writeExternal(ObjectOutput out) throws IOException {
// RESOLVE: write out the byte array instead?
out.writeLong(majorId);
out.writeLong(timemillis);
out.writeInt(sequence);
}
/**
* Read this in
*
* @exception IOException
* error reading from log stream
*/
public void readExternal(ObjectInput in) throws IOException {
majorId = in.readLong();
timemillis = in.readLong();
sequence = in.readInt();
}
private static void writeMSB(char[] data, int offset, long value, int nbytes) {
for (int i = nbytes - 1; i >= 0; i--) {
long b = (value & (255L << (8 * i))) >>> (8 * i);
int c = (int) ((b & 0xf0) >> 4);
data[offset++] = (char) (c < 10 ? c + "0" : (c - 10) + "a");
c = (int) (b & 0x0f);
data[offset++] = (char) (c < 10 ? c + "0" : (c - 10) + "a");
}
}
/**
* Read a long value, msb first, from its character representation in the
* string reader, using "-" or end of string to delimit.
*/
private static long readMSB(StringReader sr) {
long value = 0;
try {
int c;
while ((c = sr.read()) != -1) {
if (c == "-")
break;
value <<= 4;
int nibble;
if (c <= "9")
nibble = c - "0";
else if (c <= "F")
nibble = c - "A" + 10;
else
nibble = c - "a" + 10;
value += nibble;
}
} catch (Exception e) {
}
return value;
}
/*
* * Methods of UUID
*/
/**
* Implement value equality.
*
*/
public boolean equals(Object otherObject) {
if (!(otherObject instanceof BasicUUID))
return false;
BasicUUID other = (BasicUUID) otherObject;
return (this.sequence == other.sequence) && (this.timemillis == other.timemillis)
&& (this.majorId == other.majorId);
}
/**
* Provide a hashCode which is compatible with the equals() method.
*/
public int hashCode() {
long hc = majorId ^ timemillis;
return sequence ^ ((int) (hc >> 4));
}
/**
* Produce a string representation of this UUID which can be passed to
* UUIDFactory.recreateUUID later on to reconstruct it. The funny
* representation is designed to (sort of) match the format of Microsoft"s
* UUIDGEN utility.
*/
public String toString() {
return stringWorkhorse("-");
}
/**
* Produce a string representation of this UUID which is suitable for use as a
* unique ANSI identifier.
*/
public String toANSIidentifier() {
return "U" + stringWorkhorse("X");
}
/**
* Private workhorse of the string making routines.
*
* @param separator
* Character to separate number blocks. Null means do not include a
* separator.
*
* @return string representation of UUID.
*/
public String stringWorkhorse(char separator) {
char[] data = new char[36];
writeMSB(data, 0, (long) sequence, 4);
int offset = 8;
if (separator != 0)
data[offset++] = separator;
long ltimemillis = timemillis;
writeMSB(data, offset, (ltimemillis & 0x0000ffff00000000L) >>> 32, 2);
offset += 4;
if (separator != 0)
data[offset++] = separator;
writeMSB(data, offset, (ltimemillis & 0x00000000ffff0000L) >>> 16, 2);
offset += 4;
if (separator != 0)
data[offset++] = separator;
writeMSB(data, offset, (ltimemillis & 0x000000000000ffffL), 2);
offset += 4;
if (separator != 0)
data[offset++] = separator;
writeMSB(data, offset, majorId, 6);
offset += 12;
return new String(data, 0, offset);
}
/**
* Store this UUID in a byte array. Arrange the bytes in the UUID in the same
* order the code which stores a UUID in a string does.
*
* @see org.apache.derby.catalog.UUID#toByteArray
*/
public byte[] toByteArray() {
byte[] result = new byte[16];
int lsequence = sequence;
result[0] = (byte) (lsequence >>> 24);
result[1] = (byte) (lsequence >>> 16);
result[2] = (byte) (lsequence >>> 8);
result[3] = (byte) lsequence;
long ltimemillis = timemillis;
result[4] = (byte) (ltimemillis >>> 40);
result[5] = (byte) (ltimemillis >>> 32);
result[6] = (byte) (ltimemillis >>> 24);
result[7] = (byte) (ltimemillis >>> 16);
result[8] = (byte) (ltimemillis >>> 8);
result[9] = (byte) ltimemillis;
long linetaddr = majorId;
result[10] = (byte) (linetaddr >>> 40);
result[11] = (byte) (linetaddr >>> 32);
result[12] = (byte) (linetaddr >>> 24);
result[13] = (byte) (linetaddr >>> 16);
result[14] = (byte) (linetaddr >>> 8);
result[15] = (byte) linetaddr;
return result;
}
/**
* Clone this UUID.
*
* @return a copy of this UUID
*/
public BasicUUID cloneMe() {
return new BasicUUID(majorId, timemillis, sequence);
}
public String toHexString() {
return stringWorkhorse((char) 0);
}
}
Generates a UUID
/**************************************************************************************
* Copyright (c) Jonas Bon�r, Alexandre Vasseur. All rights reserved. *
* http://aspectwerkz.codehaus.org *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the LGPL license *
* a copy of which has been included with this distribution in the license.txt file. *
**************************************************************************************/
import java.net.InetAddress;
import java.security.SecureRandom;
/**
* Generates a UUID. <p/>A Universally Unique Identifier (UUID) is a 128 bit number generated according to an algorithm
* that is garanteed to be unique in time A space from all other UUIDs.
*
* @author
*/
public class UuidGenerator {
/**
* Random seeder.
*/
private static SecureRandom s_seeder = null;
/**
* Mid value, needed for calculation.
*/
private static String s_midValue = null;
/**
* Defines if the generator is initialized or not.
*/
private static boolean s_initialized = false;
/**
* Private constructor to prevent subclassing
*/
private UuidGenerator() {
}
/**
* Returns a unique uuid.
*
* @param obj the calling object (this)
* @return a unique uuid
*/
public static String generate(Object obj) {
if (!s_initialized) {
initialize(obj);
}
long timeNow = System.currentTimeMillis();
// get int value as unsigned
int timeLow = (int) timeNow & 0xFFFFFFFF;
int node = s_seeder.nextInt();
return (hexFormat(timeLow, 8) + s_midValue + hexFormat(node, 8));
}
/**
* Initializes the factory.
*
* @param obj
*/
private synchronized static void initialize(final Object obj) {
try {
InetAddress inet = InetAddress.getLocalHost();
byte[] bytes = inet.getAddress();
String hexInetAddress = hexFormat(getInt(bytes), 8);
String thisHashCode = hexFormat(System.identityHashCode(obj), 8);
s_midValue = hexInetAddress + thisHashCode;
s_seeder = new SecureRandom();
s_seeder.nextInt();
} catch (java.net.UnknownHostException e) {
throw new Error("can not initialize the UuidGenerator generator");
}
s_initialized = true;
}
/**
* Utility method.
*
* @param abyte
* @return
*/
private static int getInt(final byte[] abyte) {
int i = 0;
int j = 24;
for (int k = 0; j >= 0; k++) {
int l = abyte[k] & 0xff;
i += (l << j);
j -= 8;
}
return i;
}
/**
* Utility method.
*
* @param i
* @param j
* @return
*/
private static String hexFormat(final int i, final int j) {
String s = Integer.toHexString(i);
return padHex(s, j) + s;
}
/**
* Utility method.
*
* @param str
* @param i
* @return
*/
private static String padHex(final String str, final int i) {
StringBuffer buf = new StringBuffer();
if (str.length() < i) {
for (int j = 0; j < (i - str.length()); j++) {
buf.append("0");
}
}
return buf.toString();
}
}
Generates random UUIDs
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
import java.security.SecureRandom;
/**
*
* RandomUuidFactory is a {@linkplain UuidFactory UuidFactory} that generates
* random UUIDs. This implementation uses the JDK"s java.security.SecureRandom
* to generate sufficiently random values for the UUIDs.
* <br><br>
* This class is a singleton, so it must be constructed through the static
* getInstance() method.
*
* @author Dan Jemiolo (danj)
*
*/
public class RandomUuidFactory
{
private static final RandomUuidFactory _SINGLETON = new RandomUuidFactory();
private static final char[] _HEX_VALUES = new char[] {
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"a", "b", "c", "d", "e", "f"
};
//
// Used to create all random numbers - guarantees unique strings
// during the process lifetime
//
private static final SecureRandom _RNG = new SecureRandom();
/**
*
* The default constructor is explicit so we can make it private and
* require use of getInstance() for instantiation.
*
* @see #getInstance()
*
*/
private RandomUuidFactory()
{
//
// this is just to prevent instantiation
//
}
/**
*
* @return A unique UUID of the form <em>uuid:<b>X</b></em>, where
* <b>X</b> is the generated value.
*
*/
public String createUUID()
{
//
// first get 16 random bytes...
//
byte[] bytes = new byte[16];
_RNG.nextBytes(bytes);
StringBuffer uuid = new StringBuffer(41);
uuid.append("uuid:");
//
// ...then we need to shift so they"re valid hex (0-9, a-f)
//
for (int n = 0; n < 16; ++n)
{
//
// (there"s really no elegant way to add the dashes...)
//
if (n == 4 || n == 6 || n == 8 || n == 10)
uuid.append("-");
//
// shift the bits so they are proper hex
//
int hex = bytes[n] & 255;
uuid.append(_HEX_VALUES[hex >> 4]);
uuid.append(_HEX_VALUES[hex & 15]);
}
return uuid.toString();
}
/**
*
* @return The singleton instance of this class.
*
*/
public static RandomUuidFactory getInstance()
{
return _SINGLETON;
}
}
Generator for Globally unique Strings
/**
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.InetAddress;
import java.net.ServerSocket;
/**
* Generator for Globally unique Strings.
*/
public class UuidGenerator {
private static final String UNIQUE_STUB;
private static int instanceCount;
private static String hostName;
private String seed;
private long sequence;
static {
String stub = "";
boolean canAccessSystemProps = true;
try {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPropertiesAccess();
}
} catch (SecurityException se) {
canAccessSystemProps = false;
}
if (canAccessSystemProps) {
try {
hostName = InetAddress.getLocalHost().getHostName();
ServerSocket ss = new ServerSocket(0);
stub = "/" + ss.getLocalPort() + "-" + System.currentTimeMillis() + "/";
Thread.sleep(100);
ss.close();
} catch (Exception ioe) {
System.out.println("Could not generate unique stub" + ioe);
}
} else {
hostName = "localhost";
stub = "-1-" + System.currentTimeMillis() + "-";
}
UNIQUE_STUB = generateSanitizedId(stub);
}
public UuidGenerator(String prefix) {
synchronized (UNIQUE_STUB) {
this.seed = generateSanitizedId(prefix + UNIQUE_STUB + (instanceCount++) + "-");
}
}
public UuidGenerator() {
this("ID-" + hostName);
}
/**
* As we have to find the hostname as a side-affect of generating a unique
* stub, we allow it"s easy retrevial here
*
* @return the local host name
*/
public static String getHostName() {
return hostName;
}
/**
* Generate a unqiue id
*/
public synchronized String generateId() {
return this.seed + (this.sequence++);
}
/**
* Generate a unique ID - that is friendly for a URL or file system
*
* @return a unique id
*/
public String generateSanitizedId() {
return generateSanitizedId(generateId());
}
/**
* Ensures that the id is friendly for a URL or file system
*
* @param id the unique id
* @return the id as file friendly id
*/
public static String generateSanitizedId(String id) {
id = id.replace(":", "-");
id = id.replace("_", "-");
id = id.replace(".", "-");
id = id.replace("/", "-");
id = id.replace("\\", "-");
return id;
}
}
Get a unique identifier Using java.rmi.dgc.VMID
public class Main {
public static void main(String arg[]) {
System.out.println(new java.rmi.dgc.VMID().toString());
}
}
//4129eb1d7419293f:-148094f1:11fc9788387:-8000
ID generator
/*
GNU LESSER GENERAL PUBLIC LICENSE
Copyright (C) 2006 The Lobo Project
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Contact info: lobochief@users.sourceforge.net
*/
/*
* Created on Jun 7, 2005
*/
import java.util.*;
import java.util.logging.*;
import java.security.*;
import java.math.*;
import java.net.InetAddress;
/**
* @author J. H. S.
*/
public class ID {
private static final Random RANDOM1;
private static final Random RANDOM2;
private static final Random RANDOM3;
private static final long globalProcessID;
private static final Logger logger = Logger.getLogger(ID.class.getName());
static {
long time = System.currentTimeMillis();
long nanoTime = System.nanoTime();
long freeMemory = Runtime.getRuntime().freeMemory();
long addressHashCode;
try {
InetAddress inetAddress;
inetAddress = InetAddress.getLocalHost();
addressHashCode = inetAddress.getHostName().hashCode() ^ inetAddress.getHostAddress().hashCode();
} catch(Exception err) {
logger.log(Level.WARNING, "Unable to get local host information.", err);
addressHashCode = ID.class.hashCode();
}
globalProcessID = time ^ nanoTime ^ freeMemory ^ addressHashCode;
RANDOM1 = new Random(time);
RANDOM2 = new Random(nanoTime);
RANDOM3 = new Random(addressHashCode ^ freeMemory);
}
private ID() {
}
public static long generateLong() {
return Math.abs(RANDOM1.nextLong() ^ RANDOM2.nextLong() ^ RANDOM3.nextLong());
}
public static int generateInt() {
return (int) generateLong();
}
public static byte[] getMD5Bytes(String content) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
return digest.digest(content.getBytes("UTF-8"));
} catch (NoSuchAlgorithmException e) {
throw new IllegalStateException(e);
} catch(java.io.UnsupportedEncodingException uee) {
throw new IllegalStateException(uee);
}
}
public static String getHexString(byte[] bytes) {
// This method cannot change even if it"s wrong.
BigInteger bigInteger = BigInteger.ZERO;
int shift = 0;
for(int i = bytes.length; --i >= 0;) {
BigInteger contrib = BigInteger.valueOf(bytes[i] & 0xFF);
contrib = contrib.shiftLeft(shift);
bigInteger = bigInteger.add(contrib);
shift += 8;
}
return bigInteger.toString(16).toUpperCase();
}
/**
* Gets a process ID that is nearly guaranteed to be globally unique.
*/
public static long getGlobalProcessID() {
return globalProcessID;
}
public static int random(int min, int max) {
if(max <= min) {
return min;
}
return Math.abs(RANDOM1.nextInt()) % (max - min) + min;
}
}
Random GUID
/*
* RandomGUID from http://www.javaexchange.ru/aboutRandomGUID.html
* @version 1.2.1 11/05/02
* @author Marc A. Mnich
*
* From www.JavaExchange.ru, Open Software licensing
*
* 11/05/02 -- Performance enhancement from Mike Dubman.
* Moved InetAddr.getLocal to static block. Mike has measured
* a 10 fold improvement in run time.
* 01/29/02 -- Bug fix: Improper seeding of nonsecure Random object
* caused duplicate GUIDs to be produced. Random object
* is now only created once per JVM.
* 01/19/02 -- Modified random seeding and added new constructor
* to allow secure random feature.
* 01/14/02 -- Added random function seeding with JVM run time
*
*/
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
/*
* In the multitude of java GUID generators, I found none that
* guaranteed randomness. GUIDs are guaranteed to be globally unique
* by using ethernet MACs, IP addresses, time elements, and sequential
* numbers. GUIDs are not expected to be random and most often are
* easy/possible to guess given a sample from a given generator.
* SQL Server, for example generates GUID that are unique but
* sequencial within a given instance.
*
* GUIDs can be used as security devices to hide things such as
* files within a filesystem where listings are unavailable (e.g. files
* that are served up from a Web server with indexing turned off).
* This may be desireable in cases where standard authentication is not
* appropriate. In this scenario, the RandomGUIDs are used as directories.
* Another example is the use of GUIDs for primary keys in a database
* where you want to ensure that the keys are secret. Random GUIDs can
* then be used in a URL to prevent hackers (or users) from accessing
* records by guessing or simply by incrementing sequential numbers.
*
* There are many other possiblities of using GUIDs in the realm of
* security and encryption where the element of randomness is important.
* This class was written for these purposes but can also be used as a
* general purpose GUID generator as well.
*
* RandomGUID generates truly random GUIDs by using the system"s
* IP address (name/IP), system time in milliseconds (as an integer),
* and a very large random number joined together in a single String
* that is passed through an MD5 hash. The IP address and system time
* make the MD5 seed globally unique and the random number guarantees
* that the generated GUIDs will have no discernable pattern and
* cannot be guessed given any number of previously generated GUIDs.
* It is generally not possible to access the seed information (IP, time,
* random number) from the resulting GUIDs as the MD5 hash algorithm
* provides one way encryption.
*
* ----> Security of RandomGUID: <-----
* RandomGUID can be called one of two ways -- with the basic java Random
* number generator or a cryptographically strong random generator
* (SecureRandom). The choice is offered because the secure random
* generator takes about 3.5 times longer to generate its random numbers
* and this performance hit may not be worth the added security
* especially considering the basic generator is seeded with a
* cryptographically strong random seed.
*
* Seeding the basic generator in this way effectively decouples
* the random numbers from the time component making it virtually impossible
* to predict the random number component even if one had absolute knowledge
* of the System time. Thanks to Ashutosh Narhari for the suggestion
* of using the static method to prime the basic random generator.
*
* Using the secure random option, this class compies with the statistical
* random number generator tests specified in FIPS 140-2, Security
* Requirements for Cryptographic Modules, secition 4.9.1.
*
* I converted all the pieces of the seed to a String before handing
* it over to the MD5 hash so that you could print it out to make
* sure it contains the data you expect to see and to give a nice
* warm fuzzy. If you need better performance, you may want to stick
* to byte[] arrays.
*
* I believe that it is important that the algorithm for
* generating random GUIDs be open for inspection and modification.
* This class is free for all uses.
*
*
* - Marc
*/
public class RandomGUID {
public String valueBeforeMD5 = "";
public String valueAfterMD5 = "";
private static Random myRand;
private static SecureRandom mySecureRand;
private static String s_id;
/*
* Static block to take care of one time secureRandom seed.
* It takes a few seconds to initialize SecureRandom. You might
* want to consider removing this static block or replacing
* it with a "time since first loaded" seed to reduce this time.
* This block will run only once per JVM instance.
*/
static {
mySecureRand = new SecureRandom();
long secureInitializer = mySecureRand.nextLong();
myRand = new Random(secureInitializer);
try {
s_id = InetAddress.getLocalHost().toString();
} catch ( UnknownHostException e ) {
e.printStackTrace();
}
}
/*
* Default constructor. With no specification of security option,
* this constructor defaults to lower security, high performance.
*/
public RandomGUID() {
getRandomGUID(false);
}
/*
* Constructor with security option. Setting secure true
* enables each random number generated to be cryptographically
* strong. Secure false defaults to the standard Random function seeded
* with a single cryptographically strong random number.
*/
public RandomGUID(boolean secure) {
getRandomGUID(secure);
}
/*
* Method to generate the random GUID
*/
private void getRandomGUID(boolean secure) {
MessageDigest md5 = null;
StringBuffer sbValueBeforeMD5 = new StringBuffer();
try {
md5 = MessageDigest.getInstance("MD5");
} catch ( NoSuchAlgorithmException e ) {
System.out.println("Error: " + e);
}
try {
long time = System.currentTimeMillis();
long rand = 0;
if ( secure ) {
rand = mySecureRand.nextLong();
} else {
rand = myRand.nextLong();
}
// This StringBuffer can be a long as you need; the MD5
// hash will always return 128 bits. You can change
// the seed to include anything you want here.
// You could even stream a file through the MD5 making
// the odds of guessing it at least as great as that
// of guessing the contents of the file!
sbValueBeforeMD5.append(s_id);
sbValueBeforeMD5.append(":");
sbValueBeforeMD5.append(Long.toString(time));
sbValueBeforeMD5.append(":");
sbValueBeforeMD5.append(Long.toString(rand));
valueBeforeMD5 = sbValueBeforeMD5.toString();
md5.update(valueBeforeMD5.getBytes());
byte[] array = md5.digest();
StringBuffer sb = new StringBuffer();
for ( int j = 0; j < array.length; ++j ) {
int b = array[j] & 0xFF;
if ( b < 0x10 ) {
sb.append("0");
}
sb.append(Integer.toHexString(b));
}
valueAfterMD5 = sb.toString();
} catch ( Exception e ) {
System.out.println("Error:" + e);
}
}
/*
* Convert to the standard format for GUID
* (Useful for SQL Server UniqueIdentifiers, etc.)
* Example: C2FEEEAC-CFCD-11D1-8B05-00600806D9B6
*/
public String toString() {
String raw = valueAfterMD5.toUpperCase();
StringBuffer sb = new StringBuffer();
sb.append(raw.substring(0, 8));
sb.append("-");
sb.append(raw.substring(8, 12));
sb.append("-");
sb.append(raw.substring(12, 16));
sb.append("-");
sb.append(raw.substring(16, 20));
sb.append("-");
sb.append(raw.substring(20));
return sb.toString();
}
/*
* Demonstraton and self test of class
*/
public static void main(String args[]) {
for ( int i = 0; i < 100; i++ ) {
RandomGUID myGUID = new RandomGUID();
System.out.println("Seeding String=" + myGUID.valueBeforeMD5);
System.out.println("rawGUID=" + myGUID.valueAfterMD5);
System.out.println("RandomGUID=" + myGUID.toString());
}
}
}
Session ID generator
/*
* Copyright 2005 Joe Walker
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Revised from dwr
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Random;
/**
* Code to generate page ids.
* IdGenerators are expensive to setup so it is suggested that you share
* instances wherever possible. This action will also enhance security.
* Much of this code is adapted from org.apache.catalina.session.ManagerBase.
* Specifically Revision 1.37 which has been unchanged in the past 18 months.
* I have taken out the /dev/urandom stuff and simplified things to the point
* where we can audit it to work out what might be broken.
* @author Joe Walker [joe at getahead dot ltd dot uk]
*/
public class IdGenerator
{
/**
* Seed the random number
*/
public IdGenerator()
{
// Start with the current system time as a seed
long seed = System.currentTimeMillis();
// Also throw in the system identifier for "this" from toString
char[] entropy = toString().toCharArray();
for (int i = 0; i < entropy.length; i++)
{
//noinspection IntegerMultiplicationImplicitCastToLong
long update = ((byte) entropy[i]) << ((i % 8) * 8);
seed ^= update;
}
random.setSeed(seed);
}
/**
* Generate and return a new session identifier.
* @param length The number of bytes to generate
* @return A new page id string
*/
public synchronized String generateId(int length)
{
byte[] buffer = new byte[length];
// Render the result as a String of hexadecimal digits
StringBuffer reply = new StringBuffer();
int resultLenBytes = 0;
while (resultLenBytes < length)
{
random.nextBytes(buffer);
buffer = getDigest().digest(buffer);
for (int j = 0; j < buffer.length && resultLenBytes < length; j++)
{
byte b1 = (byte) ((buffer[j] & 0xf0) >> 4);
if (b1 < 10)
{
reply.append((char) ("0" + b1));
}
else
{
reply.append((char) ("A" + (b1 - 10)));
}
byte b2 = (byte) (buffer[j] & 0x0f);
if (b2 < 10)
{
reply.append((char) ("0" + b2));
}
else
{
reply.append((char) ("A" + (b2 - 10)));
}
resultLenBytes++;
}
}
return reply.toString();
}
/**
* @return the algorithm
*/
public synchronized String getAlgorithm()
{
return algorithm;
}
/**
* @param algorithm the algorithm to set
*/
public synchronized void setAlgorithm(String algorithm)
{
this.algorithm = algorithm;
digest = null;
}
/**
* Return the MessageDigest object to be used for calculating
* session identifiers. If none has been created yet, initialize
* one the first time this method is called.
* @return The hashing algorithm
*/
private MessageDigest getDigest()
{
if (digest == null)
{
try
{
digest = MessageDigest.getInstance(algorithm);
}
catch (NoSuchAlgorithmException ex)
{
try
{
digest = MessageDigest.getInstance(DEFAULT_ALGORITHM);
}
catch (NoSuchAlgorithmException ex2)
{
digest = null;
throw new IllegalStateException("No algorithms for IdGenerator");
}
}
System.out.println("Using MessageDigest: " + digest.getAlgorithm());
}
return digest;
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*/
@SuppressWarnings({"EmptyMethod"})
@Override
public final String toString()
{
// This is to make the point that we need toString to return something
// that includes some sort of system identifier as does the default.
// Don"t change this unless you really know what you are doing.
return super.toString();
}
/**
* The default message digest algorithm to use if we cannot use
* the requested one.
*/
protected static final String DEFAULT_ALGORITHM = "MD5";
/**
* The message digest algorithm to be used when generating session
* identifiers. This must be an algorithm supported by the
* <code>java.security.MessageDigest</code> class on your platform.
*/
private String algorithm = DEFAULT_ALGORITHM;
/**
* A random number generator to use when generating session identifiers.
*/
private Random random = new SecureRandom();
/**
* Return the MessageDigest implementation to be used when creating session
* identifiers.
*/
private MessageDigest digest = null;
}
Using java.util.concurrent.AtomicLong: A numerical id, start at zero and increment by one.
import java.util.concurrent.atomic.AtomicLong;
public class Main {
public static void main(String[] argv) {
AtomicLong nextId = new AtomicLong();
System.out.println(nextId.getAndIncrement());
}
}
Using java.util.UUID
import java.util.UUID;
public class Main {
public static void main(String arg[]) {
System.out.println(UUID.randomUUID());
}
}
//138a4222-e898-484f-8347-dafc01c5b03b
UUID generator
/*
* Copyright 2004,2005 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Random;
/**
* UUID generator
*/
public class UUIDGenerator {
private static String baseUUID = null;
private static long incrementingValue = 0;
private static Random myRand = null;
/**
* MD5 a random string with localhost/date etc will return 128 bits
* construct a string of 18 characters from those bits.
*
* @return string
*/
public static String getUUID() {
if (baseUUID == null) {
getInitialUUID();
}
long i = ++incrementingValue;
if(i >= Long.MAX_VALUE || i < 0){
incrementingValue = 0;
i = 0;
}
return baseUUID + System.currentTimeMillis() + i;
}
protected static synchronized void getInitialUUID() {
if (baseUUID != null) {
return;
}
if (myRand == null) {
myRand = new Random();
}
long rand = myRand.nextLong();
String sid;
try {
sid = InetAddress.getLocalHost().toString();
} catch (UnknownHostException e) {
sid = Thread.currentThread().getName();
}
StringBuffer sb = new StringBuffer();
sb.append(sid);
sb.append(":");
sb.append(Long.toString(rand));
MessageDigest md5 = null;
try {
md5 = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
//todo have to be properly handled
}
md5.update(sb.toString().getBytes());
byte[] array = md5.digest();
StringBuffer sb2 = new StringBuffer();
for (int j = 0; j < array.length; ++j) {
int b = array[j] & 0xFF;
sb2.append(Integer.toHexString(b));
}
int begin = myRand.nextInt();
if (begin < 0) begin = begin * -1;
begin = begin % 8;
baseUUID = sb2.toString().substring(begin, begin + 18).toUpperCase();
}
}