EMMA Coverage Report (generated Sun Mar 01 22:06:14 CET 2015)
[all classes][org.h2.util]

COVERAGE SUMMARY FOR SOURCE FILE [MathUtils.java]

nameclass, %method, %block, %line, %
MathUtils.java100% (2/2)89%  (16/18)79%  (340/432)73%  (80.5/111)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class MathUtils$1100% (1/1)100% (2/2)73%  (24/33)80%  (8.8/11)
run (): void 100% (1/1)70%  (21/30)78%  (7.8/10)
MathUtils$1 (): void 100% (1/1)100% (3/3)100% (1/1)
     
class MathUtils100% (1/1)88%  (14/16)79%  (316/399)72%  (72.8/101)
MathUtils (): void 0%   (0/1)0%   (0/3)0%   (0/2)
warn (String, Throwable): void 0%   (0/1)0%   (0/15)0%   (0/4)
getSecureRandom (): SecureRandom 100% (1/1)49%  (33/67)54%  (14/26)
secureRandomLong (): long 100% (1/1)69%  (11/16)75%  (3/4)
secureRandomInt (int): int 100% (1/1)71%  (12/17)75%  (3/4)
secureRandomBytes (int): byte [] 100% (1/1)73%  (19/26)84%  (6.8/8)
convertLongToInt (long): int 100% (1/1)87%  (13/15)80%  (4/5)
generateAlternativeSeed (): byte [] 100% (1/1)93%  (152/164)83%  (30/36)
<static initializer> 100% (1/1)100% (5/5)100% (1/1)
compareInt (int, int): int 100% (1/1)100% (12/12)100% (1/1)
compareLong (long, long): int 100% (1/1)100% (14/14)100% (1/1)
nextPowerOf2 (int): int 100% (1/1)100% (19/19)100% (4/4)
randomBytes (byte []): void 100% (1/1)100% (4/4)100% (2/2)
randomInt (int): int 100% (1/1)100% (4/4)100% (1/1)
roundUpInt (int, int): int 100% (1/1)100% (9/9)100% (1/1)
roundUpLong (long, long): long 100% (1/1)100% (9/9)100% (1/1)

1/*
2 * Copyright 2004-2014 H2 Group. Multiple-Licensed under the MPL 2.0,
3 * and the EPL 1.0 (http://h2database.com/html/license.html).
4 * Initial Developer: H2 Group
5 */
6package org.h2.util;
7 
8import java.io.ByteArrayOutputStream;
9import java.io.DataOutputStream;
10import java.io.IOException;
11import java.lang.reflect.Method;
12import java.security.SecureRandom;
13import java.util.Random;
14 
15/**
16 * This is a utility class with mathematical helper functions.
17 */
18public class MathUtils {
19 
20    /**
21     * The secure random object.
22     */
23    static SecureRandom cachedSecureRandom;
24 
25    /**
26     * True if the secure random object is seeded.
27     */
28    static volatile boolean seeded;
29 
30    private static final Random RANDOM  = new Random();
31 
32    private MathUtils() {
33        // utility class
34    }
35 
36 
37    /**
38     * Round the value up to the next block size. The block size must be a power
39     * of two. As an example, using the block size of 8, the following rounding
40     * operations are done: 0 stays 0; values 1..8 results in 8, 9..16 results
41     * in 16, and so on.
42     *
43     * @param x the value to be rounded
44     * @param blockSizePowerOf2 the block size
45     * @return the rounded value
46     */
47    public static int roundUpInt(int x, int blockSizePowerOf2) {
48        return (x + blockSizePowerOf2 - 1) & (-blockSizePowerOf2);
49    }
50 
51    /**
52     * Round the value up to the next block size. The block size must be a power
53     * of two. As an example, using the block size of 8, the following rounding
54     * operations are done: 0 stays 0; values 1..8 results in 8, 9..16 results
55     * in 16, and so on.
56     *
57     * @param x the value to be rounded
58     * @param blockSizePowerOf2 the block size
59     * @return the rounded value
60     */
61    public static long roundUpLong(long x, long blockSizePowerOf2) {
62        return (x + blockSizePowerOf2 - 1) & (-blockSizePowerOf2);
63    }
64 
65    private static synchronized SecureRandom getSecureRandom() {
66        if (cachedSecureRandom != null) {
67            return cachedSecureRandom;
68        }
69        // Workaround for SecureRandom problem as described in
70        // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6202721
71        // Can not do that in a static initializer block, because
72        // threads are not started until after the initializer block exits
73        try {
74            cachedSecureRandom = SecureRandom.getInstance("SHA1PRNG");
75            // On some systems, secureRandom.generateSeed() is very slow.
76            // In this case it is initialized using our own seed implementation
77            // and afterwards (in the thread) using the regular algorithm.
78            Runnable runnable = new Runnable() {
79                @Override
80                public void run() {
81                    try {
82                        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
83                        byte[] seed = sr.generateSeed(20);
84                        synchronized (cachedSecureRandom) {
85                            cachedSecureRandom.setSeed(seed);
86                            seeded = true;
87                        }
88                    } catch (Exception e) {
89                        // NoSuchAlgorithmException
90                        warn("SecureRandom", e);
91                    }
92                }
93            };
94 
95            try {
96                Thread t = new Thread(runnable, "Generate Seed");
97                // let the process terminate even if generating the seed is
98                // really slow
99                t.setDaemon(true);
100                t.start();
101                Thread.yield();
102                try {
103                    // normally, generateSeed takes less than 200 ms
104                    t.join(400);
105                } catch (InterruptedException e) {
106                    warn("InterruptedException", e);
107                }
108                if (!seeded) {
109                    byte[] seed = generateAlternativeSeed();
110                    // this never reduces randomness
111                    synchronized (cachedSecureRandom) {
112                        cachedSecureRandom.setSeed(seed);
113                    }
114                }
115            } catch (SecurityException e) {
116                // workaround for the Google App Engine: don't use a thread
117                runnable.run();
118                generateAlternativeSeed();
119            }
120 
121        } catch (Exception e) {
122            // NoSuchAlgorithmException
123            warn("SecureRandom", e);
124            cachedSecureRandom = new SecureRandom();
125        }
126        return cachedSecureRandom;
127    }
128 
129    /**
130     * Generate a seed value, using as much unpredictable data as possible.
131     *
132     * @return the seed
133     */
134    public static byte[] generateAlternativeSeed() {
135        try {
136            ByteArrayOutputStream bout = new ByteArrayOutputStream();
137            DataOutputStream out = new DataOutputStream(bout);
138 
139            // milliseconds and nanoseconds
140            out.writeLong(System.currentTimeMillis());
141            out.writeLong(System.nanoTime());
142 
143            // memory
144            out.writeInt(new Object().hashCode());
145            Runtime runtime = Runtime.getRuntime();
146            out.writeLong(runtime.freeMemory());
147            out.writeLong(runtime.maxMemory());
148            out.writeLong(runtime.totalMemory());
149 
150            // environment
151            try {
152                String s = System.getProperties().toString();
153                // can't use writeUTF, as the string
154                // might be larger than 64 KB
155                out.writeInt(s.length());
156                out.write(s.getBytes("UTF-8"));
157            } catch (Exception e) {
158                warn("generateAlternativeSeed", e);
159            }
160 
161            // host name and ip addresses (if any)
162            try {
163                // workaround for the Google App Engine: don't use InetAddress
164                Class<?> inetAddressClass = Class.forName(
165                        "java.net.InetAddress");
166                Object localHost = inetAddressClass.getMethod(
167                        "getLocalHost").invoke(null);
168                String hostName = inetAddressClass.getMethod(
169                        "getHostName").invoke(localHost).toString();
170                out.writeUTF(hostName);
171                Object[] list = (Object[]) inetAddressClass.getMethod(
172                        "getAllByName", String.class).invoke(null, hostName);
173                Method getAddress = inetAddressClass.getMethod(
174                        "getAddress");
175                for (Object o : list) {
176                    out.write((byte[]) getAddress.invoke(o));
177                }
178            } catch (Throwable e) {
179                // on some system, InetAddress is not supported
180                // on some system, InetAddress.getLocalHost() doesn't work
181                // for some reason (incorrect configuration)
182            }
183 
184            // timing (a second thread is already running usually)
185            for (int j = 0; j < 16; j++) {
186                int i = 0;
187                long end = System.currentTimeMillis();
188                while (end == System.currentTimeMillis()) {
189                    i++;
190                }
191                out.writeInt(i);
192            }
193 
194            out.close();
195            return bout.toByteArray();
196        } catch (IOException e) {
197            warn("generateAlternativeSeed", e);
198            return new byte[1];
199        }
200    }
201 
202    /**
203     * Print a message to system output if there was a problem initializing the
204     * random number generator.
205     *
206     * @param s the message to print
207     * @param t the stack trace
208     */
209    static void warn(String s, Throwable t) {
210        // not a fatal problem, but maybe reduced security
211        System.out.println("Warning: " + s);
212        if (t != null) {
213            t.printStackTrace();
214        }
215    }
216 
217    /**
218     * Get the value that is equal or higher than this value, and that is a
219     * power of two.
220     *
221     * @param x the original value
222     * @return the next power of two value
223     */
224    public static int nextPowerOf2(int x) {
225        long i = 1;
226        while (i < x && i < (Integer.MAX_VALUE / 2)) {
227            i += i;
228        }
229        return (int) i;
230    }
231 
232    /**
233     * Convert a long value to an int value. Values larger than the biggest int
234     * value is converted to the biggest int value, and values smaller than the
235     * smallest int value are converted to the smallest int value.
236     *
237     * @param l the value to convert
238     * @return the converted int value
239     */
240    public static int convertLongToInt(long l) {
241        if (l <= Integer.MIN_VALUE) {
242            return Integer.MIN_VALUE;
243        } else if (l >= Integer.MAX_VALUE) {
244            return Integer.MAX_VALUE;
245        } else {
246            return (int) l;
247        }
248    }
249 
250    /**
251     * Compare two values. Returns -1 if the first value is smaller, 1 if
252     * bigger, and 0 if equal.
253     *
254     * @param a the first value
255     * @param b the second value
256     * @return the result
257     */
258    public static int compareInt(int a, int b) {
259        return a == b ? 0 : a < b ? -1 : 1;
260    }
261 
262    /**
263     * Compare two values. Returns -1 if the first value is smaller, 1 if
264     * bigger, and 0 if equal.
265     *
266     * @param a the first value
267     * @param b the second value
268     * @return the result
269     */
270    public static int compareLong(long a, long b) {
271        return a == b ? 0 : a < b ? -1 : 1;
272    }
273 
274    /**
275     * Get a cryptographically secure pseudo random long value.
276     *
277     * @return the random long value
278     */
279    public static long secureRandomLong() {
280        SecureRandom sr = getSecureRandom();
281        synchronized (sr) {
282            return sr.nextLong();
283        }
284    }
285 
286    /**
287     * Get a number of pseudo random bytes.
288     *
289     * @param bytes the target array
290     */
291    public static void randomBytes(byte[] bytes) {
292        RANDOM.nextBytes(bytes);
293    }
294 
295    /**
296     * Get a number of cryptographically secure pseudo random bytes.
297     *
298     * @param len the number of bytes
299     * @return the random bytes
300     */
301    public static byte[] secureRandomBytes(int len) {
302        if (len <= 0) {
303            len = 1;
304        }
305        byte[] buff = new byte[len];
306        SecureRandom sr = getSecureRandom();
307        synchronized (sr) {
308            sr.nextBytes(buff);
309        }
310        return buff;
311    }
312 
313    /**
314     * Get a pseudo random int value between 0 (including and the given value
315     * (excluding). The value is not cryptographically secure.
316     *
317     * @param lowerThan the value returned will be lower than this value
318     * @return the random long value
319     */
320    public static int randomInt(int lowerThan) {
321        return RANDOM.nextInt(lowerThan);
322    }
323 
324    /**
325     * Get a cryptographically secure pseudo random int value between 0
326     * (including and the given value (excluding).
327     *
328     * @param lowerThan the value returned will be lower than this value
329     * @return the random long value
330     */
331    public static int secureRandomInt(int lowerThan) {
332        SecureRandom sr = getSecureRandom();
333        synchronized (sr) {
334            return sr.nextInt(lowerThan);
335        }
336    }
337 
338}

[all classes][org.h2.util]
EMMA 2.0.5312 (C) Vladimir Roubtsov