1
1
/*
2
- * Copyright 2014 the original author or authors.
2
+ * Copyright 2014-2016 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
17
17
18
18
import java .security .NoSuchAlgorithmException ;
19
19
import java .security .SecureRandom ;
20
+ import java .util .Arrays ;
21
+ import java .util .List ;
20
22
import java .util .UUID ;
23
+ import java .util .concurrent .atomic .AtomicReference ;
21
24
22
25
import org .springframework .dao .InvalidDataAccessApiUsageException ;
23
26
import org .springframework .data .util .TypeInformation ;
24
27
import org .springframework .util .ClassUtils ;
28
+ import org .springframework .util .StringUtils ;
25
29
26
30
/**
27
31
* Default implementation of {@link IdentifierGenerator} to generate identifiers of types {@link UUID}, String,
@@ -33,7 +37,7 @@ enum DefaultIdentifierGenerator implements IdentifierGenerator {
33
37
34
38
INSTANCE ;
35
39
36
- private static final String ALGORITHM = "NativePRNGBlocking" ;
40
+ private final AtomicReference < SecureRandom > secureRandom = new AtomicReference < SecureRandom >( null ) ;
37
41
38
42
/*
39
43
* (non-Javadoc)
@@ -50,22 +54,55 @@ public <T> T generateIdentifierOfType(TypeInformation<T> identifierType) {
50
54
} else if (ClassUtils .isAssignable (String .class , type )) {
51
55
return (T ) UUID .randomUUID ().toString ();
52
56
} else if (ClassUtils .isAssignable (Integer .class , type )) {
57
+ return (T ) Integer .valueOf (getSecureRandom ().nextInt ());
58
+ } else if (ClassUtils .isAssignable (Long .class , type )) {
59
+ return (T ) Long .valueOf (getSecureRandom ().nextLong ());
60
+ }
53
61
54
- try {
55
- return (T ) SecureRandom .getInstance (ALGORITHM );
56
- } catch (NoSuchAlgorithmException e ) {
57
- throw new InvalidDataAccessApiUsageException ("Could not create SecureRandom instance." , e );
58
- }
62
+ throw new InvalidDataAccessApiUsageException ("Non gereratable id type...." );
63
+ }
59
64
60
- } else if ( ClassUtils . isAssignable ( Long . class , type ) ) {
65
+ private SecureRandom getSecureRandom ( ) {
61
66
67
+ SecureRandom secureRandom = this .secureRandom .get ();
68
+ if (secureRandom != null ) {
69
+ return secureRandom ;
70
+ }
71
+
72
+ for (String algorithm : OsTools .secureRandomAlgorithmNames ()) {
62
73
try {
63
- return ( T ) Long . valueOf ( SecureRandom .getInstance (ALGORITHM ). nextLong () );
74
+ secureRandom = SecureRandom .getInstance (algorithm );
64
75
} catch (NoSuchAlgorithmException e ) {
65
- throw new InvalidDataAccessApiUsageException ( "Could not create SecureRandom instance." , e );
76
+ // ignore and try next.
66
77
}
67
78
}
68
79
69
- throw new InvalidDataAccessApiUsageException ("Non gereratable id type...." );
80
+ if (secureRandom == null ) {
81
+ throw new InvalidDataAccessApiUsageException (
82
+ String .format ("Could not create SecureRandom instance for one of the algorithms '%s'." ,
83
+ StringUtils .collectionToCommaDelimitedString (OsTools .secureRandomAlgorithmNames ())));
84
+ }
85
+
86
+ this .secureRandom .compareAndSet (null , secureRandom );
87
+
88
+ return secureRandom ;
89
+ }
90
+
91
+ /**
92
+ * @author Christoph Strobl
93
+ * @since 1.1.2
94
+ */
95
+ private static class OsTools {
96
+
97
+ private static final String OPERATING_SYSTEM_NAME = System .getProperty ("os.name" ).toLowerCase ();
98
+
99
+ private static final List <String > SECURE_RANDOM_ALGORITHMS_LINUX_OSX_SOLARIS = Arrays .asList ("NativePRNGBlocking" ,
100
+ "NativePRNGNonBlocking" , "NativePRNG" , "SHA1PRNG" );
101
+ private static final List <String > SECURE_RANDOM_ALGORITHMS_WINDOWS = Arrays .asList ("SHA1PRNG" , "Windows-PRNG" );
102
+
103
+ static List <String > secureRandomAlgorithmNames () {
104
+ return OPERATING_SYSTEM_NAME .indexOf ("win" ) >= 0 ? SECURE_RANDOM_ALGORITHMS_WINDOWS
105
+ : SECURE_RANDOM_ALGORITHMS_LINUX_OSX_SOLARIS ;
106
+ }
70
107
}
71
108
}
0 commit comments