1
1
/*
2
- * Copyright 2012-2020 the original author or authors.
2
+ * Copyright 2012-2021 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.
16
16
17
17
package org .springframework .boot .env ;
18
18
19
+ import java .util .OptionalInt ;
20
+ import java .util .OptionalLong ;
19
21
import java .util .Random ;
20
22
import java .util .UUID ;
23
+ import java .util .function .BiPredicate ;
24
+ import java .util .function .Function ;
25
+ import java .util .function .Predicate ;
21
26
22
27
import org .apache .commons .logging .Log ;
23
28
import org .apache .commons .logging .LogFactory ;
24
29
25
30
import org .springframework .core .env .ConfigurableEnvironment ;
26
31
import org .springframework .core .env .PropertySource ;
27
32
import org .springframework .core .env .StandardEnvironment ;
33
+ import org .springframework .util .Assert ;
28
34
import org .springframework .util .DigestUtils ;
29
35
import org .springframework .util .StringUtils ;
30
36
44
50
* suffix whose syntax is:
45
51
* <p>
46
52
* {@code OPEN value (,max) CLOSE} where the {@code OPEN,CLOSE} are any character and
47
- * {@code value,max} are integers. If {@code max} is provided then {@code value} is the
48
- * minimum value and {@code max} is the maximum (exclusive).
53
+ * {@code value,max} are integers. If {@code max} is not provided, then 0 is used as the
54
+ * lower bound and {@code value} is the upper bound. If {@code max} is provided then
55
+ * {@code value} is the minimum value and {@code max} is the maximum (exclusive).
49
56
*
50
57
* @author Dave Syer
51
58
* @author Matt Benson
59
+ * @author Madhura Bhave
52
60
* @since 1.0.0
53
61
*/
54
62
public class RandomValuePropertySource extends PropertySource <Random > {
@@ -113,22 +121,21 @@ private String getRange(String type, String prefix) {
113
121
}
114
122
115
123
private int getNextIntInRange (String range ) {
116
- String [] tokens = StringUtils . commaDelimitedListToStringArray (range );
117
- int start = Integer . parseInt ( tokens [ 0 ] );
118
- if (tokens . length == 1 ) {
119
- return getSource (). nextInt ( start );
124
+ Range < Integer > intRange = Range . get (range , Integer :: parseInt , ( t ) -> t > 0 , 0 , ( t1 , t2 ) -> t1 < t2 );
125
+ OptionalInt first = getSource (). ints ( 1 , intRange . getMin (), intRange . getMax ()). findFirst ( );
126
+ if (! first . isPresent () ) {
127
+ throw new RuntimeException ( "Could not get random number for range '" + range + "'" );
120
128
}
121
- return start + getSource (). nextInt ( Integer . parseInt ( tokens [ 1 ]) - start );
129
+ return first . getAsInt ( );
122
130
}
123
131
124
132
private long getNextLongInRange (String range ) {
125
- String [] tokens = StringUtils .commaDelimitedListToStringArray (range );
126
- if (tokens .length == 1 ) {
127
- return Math .abs (getSource ().nextLong () % Long .parseLong (tokens [0 ]));
133
+ Range <Long > longRange = Range .get (range , Long ::parseLong , (t ) -> t > 0L , 0L , (t1 , t2 ) -> t1 < t2 );
134
+ OptionalLong first = getSource ().longs (1 , longRange .getMin (), longRange .getMax ()).findFirst ();
135
+ if (!first .isPresent ()) {
136
+ throw new RuntimeException ("Could not get random number for range '" + range + "'" );
128
137
}
129
- long lowerBound = Long .parseLong (tokens [0 ]);
130
- long upperBound = Long .parseLong (tokens [1 ]) - lowerBound ;
131
- return lowerBound + Math .abs (getSource ().nextLong () % upperBound );
138
+ return first .getAsLong ();
132
139
}
133
140
134
141
private Object getRandomBytes () {
@@ -143,4 +150,39 @@ public static void addToEnvironment(ConfigurableEnvironment environment) {
143
150
logger .trace ("RandomValuePropertySource add to Environment" );
144
151
}
145
152
153
+ static final class Range <T extends Number > {
154
+
155
+ private final T min ;
156
+
157
+ private final T max ;
158
+
159
+ private Range (T min , T max ) {
160
+ this .min = min ;
161
+ this .max = max ;
162
+
163
+ }
164
+
165
+ static <T extends Number > Range <T > get (String range , Function <String , T > parse , Predicate <T > boundValidator ,
166
+ T defaultMin , BiPredicate <T , T > rangeValidator ) {
167
+ String [] tokens = StringUtils .commaDelimitedListToStringArray (range );
168
+ T token1 = parse .apply (tokens [0 ]);
169
+ if (tokens .length == 1 ) {
170
+ Assert .isTrue (boundValidator .test (token1 ), "Bound must be positive." );
171
+ return new Range <>(defaultMin , token1 );
172
+ }
173
+ T token2 = parse .apply (tokens [1 ]);
174
+ Assert .isTrue (rangeValidator .test (token1 , token2 ), "Lower bound must be less than upper bound." );
175
+ return new Range <>(token1 , token2 );
176
+ }
177
+
178
+ T getMin () {
179
+ return this .min ;
180
+ }
181
+
182
+ T getMax () {
183
+ return this .max ;
184
+ }
185
+
186
+ }
187
+
146
188
}
0 commit comments