Coverage Report - org.apache.commons.id.uuid.VersionFourGenerator
 
Classes in this File Line Coverage Branch Coverage Complexity
VersionFourGenerator
75%
27/36
70%
7/10
2
 
 1  
 /*
 2  
  * Licensed to the Apache Software Foundation (ASF) under one or more
 3  
  * contributor license agreements.  See the NOTICE file distributed with
 4  
  * this work for additional information regarding copyright ownership.
 5  
  * The ASF licenses this file to You under the Apache License, Version 2.0
 6  
  * (the "License"); you may not use this file except in compliance with
 7  
  * the License.  You may obtain a copy of the License at
 8  
  *
 9  
  *      http://www.apache.org/licenses/LICENSE-2.0
 10  
  *
 11  
  * Unless required by applicable law or agreed to in writing, software
 12  
  * distributed under the License is distributed on an "AS IS" BASIS,
 13  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14  
  * See the License for the specific language governing permissions and
 15  
  * limitations under the License.
 16  
  */
 17  
 package org.apache.commons.id.uuid;
 18  
 
 19  
 import org.apache.commons.id.IdentifierGenerator;
 20  
 
 21  
 import java.security.NoSuchAlgorithmException;
 22  
 import java.security.NoSuchProviderException;
 23  
 import java.security.SecureRandom;
 24  
 import java.util.Random;
 25  
 
 26  
 /**
 27  
  * <p>Class is responsible for generating version 4 UUID's per RFC 4122.
 28  
  * This class attempts to use a java.security.SecureRandom with
 29  
  * the following instantiation
 30  
  * <code>SecureRandom.getInstance("SHA1PRNG", "SUN")</code>. If neither secure
 31  
  * random implementation is avialable or an Exception is raised a java.util.Random
 32  
  * is used.</p>
 33  
  * <p>Note: Instantiation of SecureRandom is an expensive operation. The
 34  
  * constructor therefore creates a static member to hold the SecureRandom.
 35  
  * The first call to getInstance may take time; subsequent calls should return
 36  
  * quickly.</p>
 37  
  *
 38  
  * @author Commons-Id team
 39  
  * @version $Revision: 480488 $ $Date: 2006-11-29 08:57:26 +0000 (Wed, 29 Nov 2006) $
 40  
  *
 41  
  */
 42  
 public final class VersionFourGenerator implements IdentifierGenerator, Constants {
 43  
 
 44  
         /** Random used to generate UUID's */
 45  1
         private static final Random regularRandom = new Random();
 46  
 
 47  
         /** SecureRandom used to generate UUID's */
 48  
         private static Random secureRandom;
 49  
 
 50  
         /** The pseudo-random number generator to use */
 51  1
         private static String usePRNG = "SHA1PRNG";
 52  
 
 53  
         /** The pseudo-random number generator package name to use */
 54  1
         private static String usePRNGPackage = "SUN";
 55  
         
 56  
         private static VersionFourGenerator generator;
 57  
 
 58  
         /**
 59  
          * <p>Constructs a new VersionFourGenerator.</p>
 60  
          */
 61  
         public VersionFourGenerator() {
 62  3
             super();
 63  3
         }
 64  
 
 65  
         /**
 66  
          * <p>Returns a singleton instance of the version four UUID generator.</p>
 67  
          *
 68  
          * @return the singleton instance of the version four UUID generator.
 69  
          */
 70  
         public static VersionFourGenerator getInstance() {
 71  1
                 if (generator == null) {
 72  1
                     generator = new VersionFourGenerator();
 73  
                 }
 74  1
                 return generator;
 75  
         }
 76  
 
 77  
         /**
 78  
          * <p>Returns a new version four UUID.</p>
 79  
          *
 80  
          * @return Object a new version 4 UUID.
 81  
          */
 82  
         public Object nextIdentifier() {
 83  5
             return nextUUID(false);
 84  
         }
 85  
 
 86  
         /**
 87  
          * <p>Returns a new version four UUID.</p>
 88  
          * <p>This overloaded method may produce both UUID's using a <code>SecureRandom</code> as well as using normal
 89  
          * <code>Random</code>
 90  
          * </p>
 91  
          *
 92  
          * @param secure indicates whether or not to use <code>SecureRandom</code> in generating the random bits.
 93  
          * @return a new version four UUID that was generated by either a <code>Random</code> or <code>SecureRandom</code>.
 94  
          */
 95  
         public Object nextIdentifier(boolean secure)  {
 96  5
             return nextUUID(secure);
 97  
         }
 98  
 
 99  
         /**
 100  
         * <p>Returns a new version four UUID.</p>
 101  
         *
 102  
         * @return Object a new version 4 UUID.
 103  
         */
 104  
         public UUID nextUUID() {
 105  
             //Call nextUUID with secure = false
 106  1
             return nextUUID(false);
 107  
         }
 108  
 
 109  
         /**
 110  
          * <p>Returns a new version four UUID using either <code>SecureRandom</code> or <code>Random</code>.</p>
 111  
          *
 112  
          * @param secure boolean flag indicating whether to use <code>SecureRandom</code> or <code>Random</code>.
 113  
          * @return a new version four UUID using either <code>SecureRandom</code> or <code>Random</code>.
 114  
          */
 115  
         private UUID nextUUID(boolean secure) {
 116  11
             byte[] raw = new byte[UUID_BYTE_LENGTH];
 117  11
             if (secure) {
 118  
                 //Initialize the secure random if null.
 119  5
                 if (secureRandom == null) {
 120  
                     try {
 121  1
                         if (usePRNGPackage != null) {
 122  1
                             secureRandom = SecureRandom.getInstance(usePRNG, usePRNGPackage);
 123  1
                         } else {
 124  0
                             secureRandom = SecureRandom.getInstance(usePRNG);
 125  
                         }
 126  0
                     } catch (NoSuchAlgorithmException nsae) {
 127  0
                         secure = false; //Fail back to default PRNG/Random
 128  0
                     } catch (NoSuchProviderException nspe) {
 129  0
                         secure = false; //Fail back to default PRNG/Random
 130  1
                     }
 131  
                 }
 132  5
                 if (secureRandom != null) { 
 133  5
                     secureRandom.nextBytes(raw); 
 134  5
                 }                
 135  
             } else {
 136  6
                 regularRandom.nextBytes(raw);
 137  
             }
 138  
 
 139  11
             raw[TIME_HI_AND_VERSION_BYTE_6] &= 0x0F;
 140  11
             raw[TIME_HI_AND_VERSION_BYTE_6] |= (UUID.VERSION_FOUR << 4);
 141  
 
 142  11
             raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] &= 0x3F; //0011 1111
 143  11
             raw[CLOCK_SEQ_HI_AND_RESERVED_BYTE_8] |= 0x80; //1000 0000
 144  
 
 145  11
             return new UUID(raw);
 146  
         }
 147  
 
 148  
        /**
 149  
         * <p>Allows clients to set the pseudo-random number generator implementation used when generating a version four uuid with
 150  
         * the secure option. The secure option uses a <code>SecureRandom</code>. The packageName string may be null to specify
 151  
         * no preferred package.</p>
 152  
         *
 153  
         * @param prngName the pseudo-random number generator implementation name. For example "SHA1PRNG".
 154  
         * @param packageName the package name for the PRNG provider. For example "SUN".
 155  
         */
 156  
        public static void setPRNGProvider(String prngName, String packageName) {
 157  0
            VersionFourGenerator.usePRNG = prngName;
 158  0
            VersionFourGenerator.usePRNGPackage = packageName;
 159  0
            VersionFourGenerator.secureRandom = null;
 160  0
        }
 161  
     }