Skip to content

Commit b923c2c

Browse files
committed
Bit of tweaking of Variant 7 generation, update "Jug" helper class
1 parent c2424e8 commit b923c2c

File tree

8 files changed

+95
-56
lines changed

8 files changed

+95
-56
lines changed

release-notes/CREDITS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ Pascal Schumacher (PascalSchumacher@github)
118118
Hal Hildebrand (Hellblazer@github)
119119
* Contributed #41: Add support for Proposed type v6 (reordered timestamp)
120120
[4.1.0]
121+
* Contributed #46: Add support for Proposed type v7 (epoch-based time uuid)
122+
[4.1.0]
121123

122124
Paul Galbraith (pgalbraith@github)
123125
* Contributed #52: Add `Generators.egressTimeBasedGenerator()` method that constructs

release-notes/VERSION

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ Releases
88

99
#41: Add support for Proposed type v6 (reordered timestamp)
1010
(contributed by Hal H)
11+
#46: Add support for Proposed type v7 (epoch-based time uuid)
12+
(contributed by Hal H)
1113
#52: Add `Generators.egressTimeBasedGenerator()` method that constructs `TimedBasedGenerator`
1214
with a sensible choice of interface
1315
(contributed by Paul G)

src/main/java/com/fasterxml/uuid/Jug.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ public class Jug
3131
TYPES.put("time-based", "t");
3232
TYPES.put("random-based", "r");
3333
TYPES.put("name-based", "n");
34+
TYPES.put("reordered-time-based", "o"); // Variant 6
35+
TYPES.put("epoch-time-based", "e"); // Variant 7
3436
}
3537

3638
protected final static HashMap<String,String> OPTIONS = new HashMap<String,String>();
@@ -67,7 +69,9 @@ protected static void printUsage()
6769
System.err.println("And type is one of:");
6870
System.err.println(" time-based / t: generate UUID based on current time and optional\n location information (defined with -e option)");
6971
System.err.println(" random-based / r: generate UUID based on the default secure random number generator");
70-
System.err.println(" name-based / n: generate UUID based on the na the default secure random number generator");
72+
System.err.println(" name-based / n: generate UUID based on MD5 hash of given String ('name')");
73+
System.err.println(" reordered-time-based / o: generate UUID based on current time and optional\n location information (defined with -e option)");
74+
System.err.println(" epoch-based / e: generate UUID based on current time (as 'epoch') and random number");
7175
}
7276

7377
private static void printMap(Map<String,String> m, PrintStream out, boolean option)
@@ -223,6 +227,9 @@ public static void main(String[] args)
223227

224228
switch (typeC) {
225229
case 't': // time-based
230+
case 'o': // reordered-time-based (Variant 6)
231+
// 30-Jun-2022, tatu: Is this true? My former self must have had his
232+
// reasons so leaving as is but... odd.
226233
usesRnd = true;
227234
// No address specified? Need a dummy one...
228235
if (addr == null) {
@@ -235,7 +242,9 @@ public static void main(String[] args)
235242
System.out.println(")");
236243
}
237244
}
238-
noArgGenerator = Generators.timeBasedGenerator(addr);
245+
noArgGenerator = (typeC == 't')
246+
? Generators.timeBasedGenerator(addr)
247+
: Generators.timeBasedReorderedGenerator(addr);
239248
break;
240249
case 'r': // random-based
241250
usesRnd = true;
@@ -247,6 +256,16 @@ public static void main(String[] args)
247256
noArgGenerator = Generators.randomBasedGenerator(r);
248257
}
249258
break;
259+
case 'e': // epoch-time-based
260+
usesRnd = true;
261+
{
262+
SecureRandom r = new SecureRandom();
263+
if (verbose) {
264+
System.out.print("(using secure random generator, info = '"+r.getProvider().getInfo()+"')");
265+
}
266+
noArgGenerator = Generators.timeBasedEpochGenerator(r);
267+
}
268+
break;
250269
case 'n': // name-based
251270
if (nameSpace == null) {
252271
System.err.println("--name-space (-s) - argument missing when using method that requires it, exiting.");

src/main/java/com/fasterxml/uuid/impl/GeneratorImplBase.java

Lines changed: 0 additions & 8 deletions
This file was deleted.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package com.fasterxml.uuid.impl;
2+
3+
import java.security.SecureRandom;
4+
5+
/**
6+
* Trivial helper class that uses class loading as synchronization
7+
* mechanism for lazy instantiation of the shared secure random
8+
* instance.
9+
*/
10+
public final class LazyRandom
11+
{
12+
private final static SecureRandom shared = new SecureRandom();
13+
14+
public static SecureRandom sharedSecureRandom() {
15+
return shared;
16+
}
17+
}

src/main/java/com/fasterxml/uuid/impl/RandomBasedGenerator.java

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ public RandomBasedGenerator(Random rnd)
7676
@Override
7777
public UUID generate()
7878
{
79-
/* 14-Oct-2010, tatu: Surprisingly, variant for reading byte array is
80-
* tad faster for SecureRandom... so let's use that then
81-
*/
79+
// 14-Oct-2010, tatu: Surprisingly, variant for reading byte array is
80+
// tad faster for SecureRandom... so let's use that then
81+
8282
long r1, r2;
8383

8484
if (_secureRandom) {
@@ -114,24 +114,4 @@ private final static long _toInt(byte[] buffer, int offset)
114114
+ ((buffer[++offset] & 0xFF) << 8)
115115
+ (buffer[++offset] & 0xFF);
116116
}
117-
118-
/*
119-
/**********************************************************************
120-
/* Helper classes
121-
/**********************************************************************
122-
*/
123-
124-
/**
125-
* Trivial helper class that uses class loading as synchronization
126-
* mechanism for lazy instantiation of the shared secure random
127-
* instance.
128-
*/
129-
protected final static class LazyRandom
130-
{
131-
private final static SecureRandom shared = new SecureRandom();
132-
133-
public static SecureRandom sharedSecureRandom() {
134-
return shared;
135-
}
136-
}
137117
}
Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
package com.fasterxml.uuid.impl;
22

3-
4-
import java.nio.ByteBuffer;
53
import java.security.SecureRandom;
64
import java.util.Random;
75
import java.util.UUID;
86

97
import com.fasterxml.uuid.NoArgGenerator;
108
import com.fasterxml.uuid.UUIDType;
11-
import com.fasterxml.uuid.impl.RandomBasedGenerator.LazyRandom;
129

1310
/**
1411
* Implementation of UUID generator that uses time/location based generation
@@ -21,29 +18,27 @@
2118
* {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer} (or
2219
* equivalent).
2320
*
24-
* @since 3.1
21+
* @since 4.1
2522
*/
2623
public class TimeBasedEpochGenerator extends NoArgGenerator
2724
{
28-
2925
/*
3026
/**********************************************************************
3127
/* Configuration
3228
/**********************************************************************
3329
*/
3430

35-
3631
/**
3732
* Random number generator that this generator uses.
3833
*/
3934
protected final Random _random;
40-
35+
4136
/*
4237
/**********************************************************************
4338
/* Construction
4439
/**********************************************************************
4540
*/
46-
41+
4742
/**
4843
* @param rnd Random number generator to use for generating UUIDs; if null,
4944
* shared default generator is used. Note that it is strongly recommend to
@@ -58,7 +53,7 @@ public TimeBasedEpochGenerator(Random rnd)
5853
}
5954
_random = rnd;
6055
}
61-
56+
6257
/*
6358
/**********************************************************************
6459
/* Access to config
@@ -67,25 +62,58 @@ public TimeBasedEpochGenerator(Random rnd)
6762

6863
@Override
6964
public UUIDType getType() { return UUIDType.TIME_BASED_EPOCH; }
70-
65+
7166
/*
7267
/**********************************************************************
7368
/* UUID generation
7469
/**********************************************************************
7570
*/
76-
71+
7772
@Override
7873
public UUID generate()
7974
{
80-
ByteBuffer buff = ByteBuffer.allocate(2 * 8);
8175
final long rawTimestamp = System.currentTimeMillis();
82-
final byte[] buffer = new byte[10];
83-
_random.nextBytes(buffer);
84-
buff.position(6);
85-
buff.put(buffer);
86-
buff.position(0);
87-
buff.putLong(rawTimestamp << 16);
88-
buff.flip();
89-
return UUIDUtil.constructUUID(UUIDType.TIME_BASED_EPOCH, buff.array());
76+
final byte[] rnd = new byte[10];
77+
_random.nextBytes(rnd);
78+
79+
// Use only 48 lowest bits as per spec, next 16 bit from random
80+
// (note: UUIDUtil.constuctUUID will add "version" so it's only 12
81+
// actual random bits)
82+
long l1 = (rawTimestamp << 16) | _toShort(rnd, 8);
83+
84+
// And then the other 64 bits of random; likewise UUIDUtil.constructUUID
85+
// will overwrite first 2 random bits so it's "only" 62 bits
86+
long l2 = _toLong(rnd, 0);
87+
88+
// and as per above, this call fills in "variant" and "version" bits
89+
return UUIDUtil.constructUUID(UUIDType.TIME_BASED_EPOCH, l1, l2);
90+
}
91+
92+
/*
93+
/**********************************************************************
94+
/* Internal methods
95+
/**********************************************************************
96+
*/
97+
98+
protected final static long _toLong(byte[] buffer, int offset)
99+
{
100+
long l1 = _toInt(buffer, offset);
101+
long l2 = _toInt(buffer, offset+4);
102+
long l = (l1 << 32) + ((l2 << 32) >>> 32);
103+
return l;
104+
}
105+
106+
private final static long _toInt(byte[] buffer, int offset)
107+
{
108+
return (buffer[offset] << 24)
109+
+ ((buffer[++offset] & 0xFF) << 16)
110+
+ ((buffer[++offset] & 0xFF) << 8)
111+
+ (buffer[++offset] & 0xFF);
112+
}
113+
114+
private final static long _toShort(byte[] buffer, int offset)
115+
{
116+
return ((buffer[offset] & 0xFF) << 8)
117+
+ (buffer[++offset] & 0xFF);
90118
}
91119
}

src/main/java/com/fasterxml/uuid/impl/TimeBasedReorderedGenerator.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,14 @@
1515
* {@link com.fasterxml.uuid.ext.FileBasedTimestampSynchronizer} (or
1616
* equivalent).
1717
*
18-
* @since 3.1
18+
* @since 4.1
1919
*/
2020
public class TimeBasedReorderedGenerator extends NoArgGenerator
2121
{
22-
2322
public static int BYTE_OFFSET_TIME_HIGH = 0;
2423
public static int BYTE_OFFSET_TIME_MID = 4;
2524
public static int BYTE_OFFSET_TIME_LOW = 7;
26-
25+
2726
/*
2827
/**********************************************************************
2928
/* Configuration

0 commit comments

Comments
 (0)