com.ajjpj.afoundation.util.AUUID Maven / Gradle / Ivy
package com.ajjpj.afoundation.util;
import javax.xml.bind.DatatypeConverter;
import java.nio.ByteBuffer;
import java.security.SecureRandom;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
/**
* This is a far more efficient alternative to using java.com.ajjpj.abase.com.ajjpj.abase.util.UUID.randomUUID(), which uses a SecureRandom and
* uses excessive amounts of time. It creates a 20 byte identifier that is pretty sure to be unique.
*
* NB: This class does not produce 'real' UUID (i.e. its results do not conform to RFC 4122).
*
* NB: The ids generated by this class are neither uniformly distributed, nor do they have any other of the
* security related properties that java.lang.UUID.randomUUID() has.
*
* NB: This implementation assumes that the system time progresses monotonously, i.e. it never moves 'backwards'.
*
* @author arno
*/
public class AUUID {
private static final byte[] jvmIdentifier = createUniquePart();
private static final AtomicInteger counter = new AtomicInteger(0);
private final byte[] data;
public static AUUID createRandom() {
final int count = counter.incrementAndGet();
final long timestamp = System.currentTimeMillis();
final ByteBuffer result = ByteBuffer.allocate(20);
result.put(jvmIdentifier);
result.putLong(timestamp);
result.putInt(count);
return fromBytes(result.array());
}
public static AUUID fromBytes(byte[] data) {
return new AUUID(data);
}
public static AUUID fromString(String data) {
return fromBytes(DatatypeConverter.parseBase64Binary(data));
}
private AUUID(byte[] data) {
this.data = data;
}
public byte[] getData() {
return data;
}
public String toString() {
return DatatypeConverter.printBase64Binary(data);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
final AUUID auuid = (AUUID) o;
return Arrays.equals(data, auuid.data);
}
@Override
public int hashCode() {
return data != null ? Arrays.hashCode(data) : 0;
}
private static byte[] createUniquePart() {
final byte[] result = new byte[8];
new SecureRandom().nextBytes(result);
return result;
}
}