Package org.jboss.fresh.util

Source Code of org.jboss.fresh.util.UniqueNumberGenerator

package org.jboss.fresh.util;

import java.lang.StringBuffer;

/**
* @author $Author: boky $
* @version $Revision: 4634 $
*/
public final class UniqueNumberGenerator {
   protected static long lastUserUniqueIDTime = Long.MIN_VALUE;

  /**
   * This method returns a string of random 36-based numbers thats exacly <code>length</code> long.
   * @param length Required length of the string
   * @return A string of random 36-base based numbers with a length of <code>length</code>.
   */
  public static String getRandomValue(int length) {
    StringBuffer result = new StringBuffer();
    for (int i = 0; i < length; i++) {
      int v = Math.abs(RandomGUID.myRand.nextInt()) % 36;
      result.append(Long.toString(v, 36));
    }
    return result.toString();
  }

  /**
   * Same as calling {@link #getRandomValue} only that it uses the {@link java.security.SecureRandom}
   * for randomness. It is about 3.5-times slower, so use it only when you need really strong
   * randomness!
   * @see #getRandomValue
   */
  public static String getStrongRandomValue(int length) {
    StringBuffer result = new StringBuffer();
    for (int i = 0; i < length; i++) {
      int v = Math.abs(RandomGUID.mySecureRand.nextInt()) % 36;
      result.append(Long.toString(v, 36));
    }
    return result.toString();
  }

  /**
   * This is a 'lite' version of {@link #getUniqueID}. While this value is should be globally
   * unique, it is not guaranteed. It is much shorter and therefore chances of same
   * two values appearing is much greater. If you use it and want it to be server-unique,
   * make sure that it is not called more that once in each milisecond.
   * @return the random value
   */
  public static String getRandomID() {
    long d = System.currentTimeMillis();                      // retrieve current date
    String D = Long.toString(d, 36);                          // Compact it as much as possible (use the highest available base)
    String id;                                                // generated id

    while (D.length() < 4) {                                  // The stamp will not be longer than 12 characters
      D = '0' + D;
    }                                                         // start with the current time stamp
    StringBuffer sb = new StringBuffer();

      int i = Math.abs(RandomGUID.myRand.nextInt());
    sb.append(Integer.toString(i, 16));
    sb.append(getRandomValue(sb.length()-8));
      sb.append('-').append(D.substring(D.length() - 4));

    id = sb.toString();

    return id;
  }

  /**
   * Same as calling {@link #getRandomID} only that it uses the {@link java.security.SecureRandom}
   * for randomness. It is about 3.5-times slower, so use it only when you need really strong
   * randomness!
   * @see #getRandomID
   */
  public static String getSecureRandomID() {
    long d = System.currentTimeMillis();                      // retrieve current date
    String D = Long.toString(d, 36);                          // Compact it as much as possible (use the highest available base)
    String id;                                                // generated id

    while (D.length() < 4) {                                  // The stamp will not be longer than 12 characters
      D = '0' + D;
    }                                                         // start with the current time stamp
    StringBuffer sb = new StringBuffer();

      int i = Math.abs(RandomGUID.mySecureRand.nextInt());
    sb.append(Integer.toString(i, 16));
    sb.append(getRandomValue(sb.length()-8));
      sb.append('-').append(D.substring(D.length() - 4));

    id = sb.toString();

    return id;
  }

  /**
   * Convenience shorthand method for {@link #getRandomID} and {@link #getSecureRandomID}. Essentially
   * returns the result of this evaluation: <code>secure ? getSecureRandomID() : getRandomID()</code>.
   * @param secure Tell whether to return secure or nonsecure-generated ID.
   * @return The same as calling {@link #getRandomID} or {@link #getSecureRandomID}
   * @see #getRandomID
   * @see #getSecureRandomID
   */
  public static String getRandomID(boolean secure) {
    return secure ? getSecureRandomID() : getRandomID();

  }

  /**
   * <p>This method will create a unique (quite short) identifier, which may be used be presented to the
   * end user. How is this different from {@link #getUniqueID()} and {@link #getRandomID()} and
   * {@link #getGUID()}? Well in the following:<ul>
   * <li>Careful consideration has been put in making the number as short as possible</li>
   * <li>It is not guaranteed to be word-wide unique (but will be locally unique)</li>
   * <li>It includes a checksum so you may check for its validness using {@link #isValidUserUniqueID}</li>
   * <li>It's user presentable</li>
   * </ul></p>
   * <p><strong>Note:</strong> As with most random number generators, this method also uses <em>system's
   * current time</em> only that it's even more dependant on it. So <strong>double check</strong> that
   * your system time is set correctly to avoid duplication of IDs. There is a small safety built in
   * (the chances of collission are 1:1679616 if you modify your system time, they drop to around 1:1296
   * if you don't restart your JVM after changing the time), but don't you be counting very much on it.</p>
   *
   * @return A new, unique, {@link String}.
   */
  public static synchronized String getUserUniqueID() {
    long d = System.currentTimeMillis();
    while(d==lastUserUniqueIDTime) {
      try {
        Thread.sleep(1);
      } catch (InterruptedException e) {
        // do nothing
      }
      // make sure it's unike
      d = System.currentTimeMillis();
    }
    lastUserUniqueIDTime = d;
    String D = Long.toString(d, 36);
    while (D.length() < 8) {
      D = '0' + D;
    }
    StringBuffer sb = new StringBuffer(RandomGUID.myShortCode);
    sb.append(D);
    sb.append(getRandomValue(2));
    sb.append(twoLetterChecksum(sb.toString()));
    return sb.toString().toLowerCase();

  }

  /**
   * Check if given string is a valid userUnique ID or not (whether it was
   * created by {@link #getUserUniqueID()} or not).
   * @param userUniqueID The ID.
   * @return If <tt>null</tt> returns <tt>false</tt>, otherwise checks if the
   *  checksum matches.
   */
  public static boolean isValidUserUniqueID(String userUniqueID) {
 
    // todo: check why test for 'dwe98ahsnlga100', 'l0e98akjxrhc100' failed.
 
    if(userUniqueID==null) {
      return false;
    }
    if(userUniqueID.length()!=14) {
      return false;
    }
    final String s = userUniqueID.toLowerCase();

    return twoLetterChecksum(s.substring(0, 12)).equalsIgnoreCase(s.substring(12, 14));
  }

  /**
   * Calculate a two-letter checksum from given string. Checksum
   * <strong>is not case sensitive</strong>
   * @param s The string to calculate checksum from
   * @return The calculated checksum
   */
  public static String twoLetterChecksum(String s) {
    // note: 36^2 = 1296
    // 1291 (prime) < 1296 < 1297 (prime)
    int sum = 0;
    int i = 0;
    s = s.toLowerCase();
    for(int j = 0; j < s.length(); j++) {
      if(++i > 37) {
        i = 1;
      }
      sum += (int) s.charAt(j) * i;
    }
    String res = Integer.toString(sum % 1291, 36).toLowerCase();
    if(res.length() < 2) {
      return '0' + res;
    } else {
      return res;
    }
  }

  /**
   * Genaretes an unique ID that ought to be globally unique. Format of the key is
   * <code>XXXXXXXXXXXXX-YYYYYY-ZZZZZ</code> where XXXX is the machine id (does not
   * change while running on the same JVM on the same computer), YYYY is the random
   * key and ZZZZ is the current timestamp.
   *
   * @return    The uniqueID value
   */
  public static String getUniqueID() {
    // Chances of two processes generating the same ID are astronomical,
    // since we use a current timestamp + 8 random bytes from
    // SHA1 algorithm.
    // 30 bits = 1.073.741.824 different combinations for each milisecond.
    long d = System.currentTimeMillis();                      // retrieve current date
    String D = Long.toString(d, 36);                          // Compact it as much as possible (use the highest available base)
    String id;                                                // generated id

    while (D.length() < 6) {                                 // The stamp will not be longer than 12 characters
      D = '0' + D;
    }                                                         // start with the current time stamp

    D = D.substring(D.length() - 6);

    StringBuffer sb = new StringBuffer(RandomGUID.machineID);

    if (RandomGUID.myRand != null) {                                        // and a few random bytes
      long l = Math.abs(RandomGUID.myRand.nextLong());

      sb.append(Long.toString(l, 32));

      sb.append('-');
    }

    id = sb.append(D).toString();

    return id;
  }

  /**
   * Same as calling {@link #getUniqueID} only that it uses the {@link java.security.SecureRandom}
   * for randomness. It is about 3.5-times slower, so use it only when you need really strong
   * randomness!
   * @see #getUniqueID
   */
  public static String getSecureUniqueID() {
    // Chances of two processes generating the same ID are astronomical,
    // since we use a current timestamp + 8 random bytes from
    // SHA1 algorithm.
    // 30 bits = 1.073.741.824 different combinations for each milisecond.
    long d = System.currentTimeMillis();                      // retrieve current date
    String D = Long.toString(d, 36);                          // Compact it as much as possible (use the highest available base)
    String id;                                                // generated id

    while (D.length() < 6) {                                 // The stamp will not be longer than 12 characters
      D = '0' + D;
    }                                                         // start with the current time stamp

    D = D.substring(D.length() - 6);

    StringBuffer sb = new StringBuffer(RandomGUID.machineID);

    if (RandomGUID.mySecureRand != null) {                                        // and a few random bytes
      long l = Math.abs(RandomGUID.mySecureRand.nextLong());

      sb.append(Long.toString(l, 32));

      sb.append('-');
    }

    id = sb.append(D).toString();

    return id;
  }

  /**
   * Convenience shorthand method for {@link #getUniqueID} and {@link #getSecureUniqueID}. Essentially
   * returns the result of this evaluation: <code>secure ? getSecureUniqueID() : getUniqueID()</code>.
   * @param secure Tell whether to return secure or nonsecure-generated GUID.
   * @return The same as calling {@link #getUniqueID} or {@link #getSecureUniqueID}
   * @see #getUniqueID
   * @see #getSecureUniqueID
   */
  public static String getUniqueID(boolean secure) {
    return secure ? getSecureUniqueID() : getUniqueID();
  }

  /**
   * Uses {@link RandomGUID} to construct a Globbally Unique Identifier. In general,
   * {@link #getUniqueID} will produce faster results. Since Java cannot read MAC address
   * of the network card, the current IP address is used. This is combined with
   * session information (the startup time of JVM, or more exacly, the first use of this class),
   * machine information (JVM version, working folder, JVM folder etc.), some random
   * values and current time to generate a globally unique ID. The retrieved number
   * <strong>will not</strong> contai any curly braces.
   * @return GUID in the standard GUID format (example: C2FEEEAC-CFCD-11D1-8B05-00600806D9B6)
   *  without the curly braces.
   */
   public static String getGUID() {
     RandomGUID r = new RandomGUID(false);
      return r.toString();
  }

  /**
   * Same as calling {@link #getGUID} only that it uses {@link java.security.SecureRandom}, therefore
   * this method is 3.5 times slower!. Use it when you need true randomness.
   * @return GUID in the standard GUID format (example: C2FEEEAC-CFCD-11D1-8B05-00600806D9B6)
   *  without the curly braces.
   */
  public static String getSecureGUID() {
    RandomGUID r = new RandomGUID(true);
    return r.toString();
  }

  /**
   * Convenience shorthand method for {@link #getGUID} and {@link #getSecureGUID}. Essentially returns
   * the result of this evaluation: <code>secure ? getSecureGUID() : getGUID()</code>.
   * @param secure Tell whether to return secure or nonsecure-generated GUID.
   * @return An GUID in standard GUID format (example: C2FEEEAC-CFCD-11D1-8B05-00600806D9B6)
   * @see #getGUID
   * @see #getSecureGUID
   */
  public static String getGUID(boolean secure) {
    return secure ? getSecureGUID() : getGUID();
  }
}
TOP

Related Classes of org.jboss.fresh.util.UniqueNumberGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.