Bug 570425 - Avoid using SecureRandom for framework UUID

Change-Id: Ia549b309b3470b2167e25c89a0af59e3ce4f9228
Signed-off-by: Thomas Watson <tjwatson@us.ibm.com>
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
index 10a06ad..0d3facb 100644
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/AbstractBundleTests.java
@@ -354,7 +354,7 @@
 			equinox.stop();
 		} catch (BundleException e) {
 			if (!quietly) {
-				fail("Unexpected erorr stopping framework", e); //$NON-NLS-1$
+				fail("Unexpected error stopping framework", e); //$NON-NLS-1$
 			}
 		}
 		return waitForStop(equinox, uuid, quietly, timeout);
diff --git a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
index 73955d2..e0f6be2 100755
--- a/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
+++ b/bundles/org.eclipse.osgi.tests/src/org/eclipse/osgi/tests/bundles/SystemBundleTests.java
@@ -1181,7 +1181,7 @@
 				default :
 					break;
 			}
-			assertTrue("UUISection is too big: " + uuidSections[i], uuidSections[i].length() <= limit);
+			assertTrue("UUIDSection is too big: " + uuidSections[i], uuidSections[i].length() <= limit);
 			try {
 				Long.decode(uuidSections[i]);
 			} catch (NumberFormatException e) {
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java
index d563aa1..3e6626c 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/container/InternalUtils.java
@@ -14,11 +14,29 @@
 package org.eclipse.osgi.internal.container;
 
 import java.security.Permission;
-import java.util.*;
-import org.osgi.framework.*;
-import org.osgi.framework.namespace.*;
-import org.osgi.framework.wiring.*;
-import org.osgi.resource.*;
+import java.security.SecureRandom;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Random;
+import java.util.UUID;
+import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundlePermission;
+import org.osgi.framework.CapabilityPermission;
+import org.osgi.framework.PackagePermission;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
 
 public class InternalUtils {
 
@@ -175,4 +193,33 @@
 		return "unknown"; //$NON-NLS-1$
 	}
 
+	public static String newUUID(EquinoxConfiguration config) {
+		// Note that we use simple Random to improve
+		// performance and the Framework UUID generation does not require
+		// a full SecureRandom seed.
+		boolean useSecureRandom = "true".equals(config.getConfiguration(EquinoxConfiguration.PROP_SECURE_UUID)); //$NON-NLS-1$
+		byte[] uuidBytes = new byte[16];
+		if (useSecureRandom) {
+			new SecureRandom().nextBytes(uuidBytes);
+		} else {
+			new Random().nextBytes(uuidBytes);
+		}
+		// clear the version bits - set to use version 4
+		uuidBytes[6] &= 0x0f;
+		uuidBytes[6] |= 0x40;
+		// clear the variant bits - set to use IETF variant
+		uuidBytes[8] &= 0x3f;
+		uuidBytes[8] |= 0x80;
+		// split into the most and least significant bits
+		long mostSignificantBits = 0;
+		long leastSignificantBits = 0;
+		for (int i = 0; i < 8; i++) {
+			mostSignificantBits = (mostSignificantBits << 8) | (uuidBytes[i] & 0xff);
+		}
+		for (int i = 8; i < 16; i++) {
+			leastSignificantBits = (leastSignificantBits << 8) | (uuidBytes[i] & 0xff);
+		}
+		return new UUID(mostSignificantBits, leastSignificantBits).toString();
+	}
+
 }
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java
index 56c5eee..924f20a 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxBundle.java
@@ -36,7 +36,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import java.util.UUID;
 import org.eclipse.osgi.container.Module;
 import org.eclipse.osgi.container.Module.Settings;
 import org.eclipse.osgi.container.Module.StartOptions;
@@ -51,6 +50,7 @@
 import org.eclipse.osgi.container.ModuleWiring;
 import org.eclipse.osgi.container.SystemModule;
 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.internal.container.InternalUtils;
 import org.eclipse.osgi.internal.debug.Debug;
 import org.eclipse.osgi.internal.loader.BundleLoader;
 import org.eclipse.osgi.internal.loader.ModuleClassLoader;
@@ -187,10 +187,11 @@
 
 			@Override
 			protected void initWorker() throws BundleException {
-				String initUUID = getEquinoxContainer().getConfiguration().setConfiguration(EquinoxConfiguration.PROP_INIT_UUID, Boolean.TRUE.toString());
+				EquinoxConfiguration config = getEquinoxContainer().getConfiguration();
+				String initUUID = config.setConfiguration(EquinoxConfiguration.PROP_INIT_UUID, Boolean.TRUE.toString());
 				if (initUUID != null) {
 					// this is not the first framework init, need to generate a new UUID
-					getEquinoxContainer().getConfiguration().setConfiguration(Constants.FRAMEWORK_UUID, UUID.randomUUID().toString());
+					config.setConfiguration(Constants.FRAMEWORK_UUID, InternalUtils.newUUID(config));
 				}
 				getEquinoxContainer().init();
 				addInitFrameworkListeners();
diff --git a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
index 1b0bdbf..f3ddd62 100644
--- a/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
+++ b/bundles/org.eclipse.osgi/container/src/org/eclipse/osgi/internal/framework/EquinoxConfiguration.java
@@ -50,10 +50,10 @@
 import java.util.NoSuchElementException;
 import java.util.Properties;
 import java.util.StringTokenizer;
-import java.util.UUID;
 import java.util.concurrent.atomic.AtomicBoolean;
 import org.eclipse.core.runtime.internal.adaptor.ConsoleManager;
 import org.eclipse.osgi.framework.log.FrameworkLogEntry;
+import org.eclipse.osgi.internal.container.InternalUtils;
 import org.eclipse.osgi.internal.debug.Debug;
 import org.eclipse.osgi.internal.debug.FrameworkDebugOptions;
 import org.eclipse.osgi.internal.hookregistry.HookRegistry;
@@ -247,6 +247,8 @@
 
 	public static final String PROP_GOSH_ARGS = "gosh.args"; //$NON-NLS-1$
 
+	public static final String PROP_SECURE_UUID = "equinox.uuid.secure"; //$NON-NLS-1$
+
 	public static final class ConfigValues {
 		/**
 		 * Value of {@link #localConfig} properties that should be considered
@@ -1091,9 +1093,8 @@
 				archValue = name;
 			setConfiguration(PROP_OSGI_ARCH, archValue);
 		}
-
 		// set the initial UUID so that it is set as soon as possible
-		String uuid = UUID.randomUUID().toString();
+		String uuid = InternalUtils.newUUID(this);
 		setConfiguration(FRAMEWORK_UUID, uuid);
 	}