/*
* Written by Dawid Kurzyniec, based on code written by Doug Lea with assistance
* from members of JCP JSR-166 Expert Group. Released to the public domain,
* as explained at http://creativecommons.org/licenses/publicdomain.
*
* Thanks to Craig Mattocks for suggesting to use <code>sun.misc.Perf</code>.
*/
package net.jxta.impl.util.backport.java.util;
import java.lang.reflect.Array;
import java.util.Collection;
import java.util.Iterator;
/**
* <p>
* This class groups together the functionality of java.util.concurrent that
* cannot be fully and reliably implemented in backport, but for which some
* form of emulation is possible.
* <p>
* Currently, this class contains methods related to nanosecond-precision
* timing, particularly via the {@link #nanoTime} method. To measure time
* accurately, this method by default uses <code>java.sun.Perf</code> on
* JDK1.4.2 and it falls back to <code>System.currentTimeMillis</code>
* on earlier JDKs.
*
* @author Dawid Kurzyniec
* @version 1.0
*/
@SuppressWarnings("unchecked")
public final class Utils {
private Utils() {}
public static Object[] collectionToArray(Collection c) {
// guess the array size; expect to possibly be different
int len = c.size();
Object[] arr = new Object[len];
Iterator itr = c.iterator();
int idx = 0;
while (true) {
while (idx < len && itr.hasNext()) {
arr[idx++] = itr.next();
}
if (!itr.hasNext()) {
if (idx == len) return arr;
// otherwise have to trim
return copyOf(arr, idx, Object[].class);
}
// otherwise, have to grow
int newcap = ((arr.length/2)+1)*3;
if (newcap < arr.length) {
// overflow
if (arr.length < Integer.MAX_VALUE) {
newcap = Integer.MAX_VALUE;
}
else {
throw new OutOfMemoryError("required array size too large");
}
}
arr = copyOf(arr, newcap, Object[].class);
len = newcap;
}
}
public static Object[] collectionToArray(Collection c, Object[] a) {
Class aType = a.getClass();
// guess the array size; expect to possibly be different
int len = c.size();
Object[] arr = (a.length >= len ? a :
(Object[])Array.newInstance(aType.getComponentType(), len));
Iterator itr = c.iterator();
int idx = 0;
while (true) {
while (idx < len && itr.hasNext()) {
arr[idx++] = itr.next();
}
if (!itr.hasNext()) {
if (idx == len) return arr;
if (arr == a) {
// orig array -> null terminate
a[idx] = null;
return a;
}
else {
// have to trim
return copyOf(arr, idx, aType);
}
}
// otherwise, have to grow
int newcap = ((arr.length/2)+1)*3;
if (newcap < arr.length) {
// overflow
if (arr.length < Integer.MAX_VALUE) {
newcap = Integer.MAX_VALUE;
}
else {
throw new OutOfMemoryError("required array size too large");
}
}
arr = copyOf(arr, newcap, aType);
len = newcap;
}
}
/**
* Taken from Arrays in backport-jsr166 3.1.
*/
public static Object[] copyOf(Object[] original, int newLength, Class newType) {
Object[] arr = (newType == Object[].class) ? new Object[newLength] :
(Object[])Array.newInstance(newType.getComponentType(), newLength);
int len = (original.length < newLength ? original.length : newLength);
System.arraycopy(original, 0, arr, 0, len);
return arr;
}
}