1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy.utility;
17
18 import java.util.Random;
19
20 /**
21  * A provider of randomized {@link java.lang.String} values.
22  */

23 public class RandomString {
24
25     /**
26      * The default length of a randomized {@link java.lang.String}.
27      */

28     public static final int DEFAULT_LENGTH = 8;
29
30     /**
31      * The symbols which are used to create a random {@link java.lang.String}.
32      */

33     private static final char[] SYMBOL;
34
35     /**
36      * The amount of bits to extract out of an integer for each key generated.
37      */

38     private static final int KEY_BITS;
39
40     /*
41      * Creates the symbol array.
42      */

43     static {
44         StringBuilder symbol = new StringBuilder();
45         for (char character = '0'; character <= '9'; character++) {
46             symbol.append(character);
47         }
48         for (char character = 'a'; character <= 'z'; character++) {
49             symbol.append(character);
50         }
51         for (char character = 'A'; character <= 'Z'; character++) {
52             symbol.append(character);
53         }
54         SYMBOL = symbol.toString().toCharArray();
55         int bits = Integer.SIZE - Integer.numberOfLeadingZeros(SYMBOL.length);
56         KEY_BITS = bits - (Integer.bitCount(SYMBOL.length) == bits ? 0 : 1);
57     }
58
59     /**
60      * A provider of random values.
61      */

62     private final Random random;
63
64     /**
65      * The length of the random strings that are created by this instance.
66      */

67     private final int length;
68
69     /**
70      * Creates a random {@link java.lang.String} provider where each {@link java.lang.String} is of
71      * {@link net.bytebuddy.utility.RandomString#DEFAULT_LENGTH} length.
72      */

73     public RandomString() {
74         this(DEFAULT_LENGTH);
75     }
76
77     /**
78      * Creates a random {@link java.lang.String} provider where each value is of the given length.
79      *
80      * @param length The length of the random {@link String}.
81      */

82     public RandomString(int length) {
83         if (length <= 0) {
84             throw new IllegalArgumentException("A random string's length cannot be zero or negative");
85         }
86         this.length = length;
87         random = new Random();
88     }
89
90     /**
91      * Creates a random {@link java.lang.String} of {@link net.bytebuddy.utility.RandomString#DEFAULT_LENGTH} length.
92      *
93      * @return A random {@link java.lang.String}.
94      */

95     public static String make() {
96         return make(DEFAULT_LENGTH);
97     }
98
99     /**
100      * Creates a random {@link java.lang.String} of the given {@code length}.
101      *
102      * @param length The length of the random {@link String}.
103      * @return A random {@link java.lang.String}.
104      */

105     public static String make(int length) {
106         return new RandomString(length).nextString();
107     }
108
109     /**
110      * Represents an integer value as a string hash. This string is not technically random but generates a fixed character
111      * sequence based on the hash provided.
112      *
113      * @param value The value to represent as a string.
114      * @return A string representing the supplied value as a string.
115      */

116     public static String hashOf(int value) {
117         char[] buffer = new char[(Integer.SIZE / KEY_BITS) + ((Integer.SIZE % KEY_BITS) == 0 ? 0 : 1)];
118         for (int index = 0; index < buffer.length; index++) {
119             buffer[index] = SYMBOL[(value >>> index * KEY_BITS) & (-1 >>> (Integer.SIZE - KEY_BITS))];
120         }
121         return new String(buffer);
122     }
123
124     /**
125      * Creates a new random {@link java.lang.String}.
126      *
127      * @return A random {@link java.lang.String} of the given length for this instance.
128      */

129     public String nextString() {
130         char[] buffer = new char[length];
131         for (int index = 0; index < length; index++) {
132             buffer[index] = SYMBOL[random.nextInt(SYMBOL.length)];
133         }
134         return new String(buffer);
135     }
136 }
137