2222import com .google .common .collect .ImmutableSet ;
2323import com .google .common .collect .Iterables ;
2424import gnu .trove .set .hash .THashSet ;
25-
2625import org .apache .lucene .util .BytesRef ;
2726import org .apache .lucene .util .UnicodeUtil ;
27+ import org .elasticsearch .ElasticSearchIllegalStateException ;
2828import org .elasticsearch .common .io .FastStringReader ;
2929
3030import java .io .BufferedReader ;
31+ import java .io .IOException ;
32+ import java .security .SecureRandom ;
3133import java .util .*;
3234
3335/**
@@ -48,24 +50,32 @@ public class Strings {
4850 private static final char EXTENSION_SEPARATOR = '.' ;
4951
5052 public static void tabify (int tabs , String from , StringBuilder to ) throws Exception {
51- BufferedReader reader = new BufferedReader (new FastStringReader (from ));
52- String line ;
53- while ((line = reader .readLine ()) != null ) {
54- for (int i = 0 ; i < tabs ; i ++) {
55- to .append ('\t' );
53+ final BufferedReader reader = new BufferedReader (new FastStringReader (from ));
54+ try {
55+ String line ;
56+ while ((line = reader .readLine ()) != null ) {
57+ for (int i = 0 ; i < tabs ; i ++) {
58+ to .append ('\t' );
59+ }
60+ to .append (line ).append ('\n' );
5661 }
57- to .append (line ).append ('\n' );
62+ } finally {
63+ reader .close ();
5864 }
5965 }
6066
6167 public static void spaceify (int spaces , String from , StringBuilder to ) throws Exception {
62- BufferedReader reader = new BufferedReader (new FastStringReader (from ));
63- String line ;
64- while ((line = reader .readLine ()) != null ) {
65- for (int i = 0 ; i < spaces ; i ++) {
66- to .append (' ' );
68+ final BufferedReader reader = new BufferedReader (new FastStringReader (from ));
69+ try {
70+ String line ;
71+ while ((line = reader .readLine ()) != null ) {
72+ for (int i = 0 ; i < spaces ; i ++) {
73+ to .append (' ' );
74+ }
75+ to .append (line ).append ('\n' );
6776 }
68- to .append (line ).append ('\n' );
77+ } finally {
78+ reader .close ();
6979 }
7080 }
7181
@@ -1479,17 +1489,6 @@ private static boolean isEmpty(Object[] array) {
14791489 return (array == null || array .length == 0 );
14801490 }
14811491
1482- /**
1483- * Return <code>true</code> if the supplied Collection is <code>null</code>
1484- * or empty. Otherwise, return <code>false</code>.
1485- *
1486- * @param collection the Collection to check
1487- * @return whether the given Collection is empty
1488- */
1489- private static boolean isEmpty (Collection collection ) {
1490- return (collection == null || collection .isEmpty ());
1491- }
1492-
14931492 private Strings () {
14941493
14951494 }
@@ -1504,4 +1503,49 @@ public static byte[] toUTF8Bytes(CharSequence charSequence, BytesRef spare) {
15041503 System .arraycopy (spare .bytes , spare .offset , bytes , 0 , bytes .length );
15051504 return bytes ;
15061505 }
1506+
1507+ private static class SecureRandomHolder {
1508+ private static final SecureRandom INSTANCE = new SecureRandom ();
1509+ }
1510+
1511+ /**
1512+ * Returns a Base64 encoded version of a Version 4.0 compatible UUID
1513+ * as defined here: http://www.ietf.org/rfc/rfc4122.txt
1514+ */
1515+ public static String randomBase64UUID () {
1516+ return randomBase64UUID (SecureRandomHolder .INSTANCE );
1517+ }
1518+
1519+ /**
1520+ * Returns a Base64 encoded version of a Version 4.0 compatible UUID
1521+ * randomly initialized by the given {@link Random} instance
1522+ * as defined here: http://www.ietf.org/rfc/rfc4122.txt
1523+ */
1524+ public static String randomBase64UUID (Random random ) {
1525+ final byte [] randomBytes = new byte [16 ];
1526+ random .nextBytes (randomBytes );
1527+
1528+ /* Set the version to version 4 (see http://www.ietf.org/rfc/rfc4122.txt)
1529+ * The randomly or pseudo-randomly generated version.
1530+ * The version number is in the most significant 4 bits of the time
1531+ * stamp (bits 4 through 7 of the time_hi_and_version field).*/
1532+ randomBytes [6 ] &= 0x0f ; /* clear the 4 most significant bits for the version */
1533+ randomBytes [6 ] |= 0x40 ; /* set the version to 0100 / 0x40 */
1534+
1535+ /* Set the variant:
1536+ * The high field of th clock sequence multiplexed with the variant.
1537+ * We set only the MSB of the variant*/
1538+ randomBytes [8 ] &= 0x3f ; /* clear the 2 most significant bits */
1539+ randomBytes [8 ] |= 0x80 ; /* set the variant (MSB is set)*/
1540+ try {
1541+ byte [] encoded = Base64 .encodeBytesToBytes (randomBytes , 0 , randomBytes .length , Base64 .URL_SAFE );
1542+ // we know the bytes are 16, and not a multi of 3, so remove the 2 padding chars that are added
1543+ assert encoded [encoded .length - 1 ] == '=' ;
1544+ assert encoded [encoded .length - 2 ] == '=' ;
1545+ // we always have padding of two at the end, encode it differently
1546+ return new String (encoded , 0 , encoded .length - 2 , Base64 .PREFERRED_ENCODING );
1547+ } catch (IOException e ) {
1548+ throw new ElasticSearchIllegalStateException ("should not be thrown" );
1549+ }
1550+ }
15071551}
0 commit comments