Bug 127793 - Improve Headless startup performance (osgi and core runtime side)
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java
index 55e9a02..34d6184 100644
--- a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/AdapterManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2005 IBM Corporation and others.
+ * Copyright (c) 2000, 2006 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -56,6 +56,8 @@
 	 */
 	protected final HashMap factories;
 
+	private ArrayList lazyFactoryProviders;
+
 	private static final AdapterManager singleton = new AdapterManager();
 
 	public static AdapterManager getDefault() {
@@ -67,6 +69,7 @@
 	 */
 	private AdapterManager() {
 		factories = new HashMap(5);
+		lazyFactoryProviders = new ArrayList(1);
 		adapterLookup = null;
 	}
 
@@ -76,7 +79,7 @@
 	 * IAdapterFactory.getAdapterList).
 	 */
 	private void addFactoriesFor(String typeName, Map table) {
-		List factoryList = (List) factories.get(typeName);
+		List factoryList = (List) getFactories().get(typeName);
 		if (factoryList == null)
 			return;
 		for (int i = 0, imax = factoryList.size(); i < imax; i++) {
@@ -347,7 +350,29 @@
 		flushLookup();
 	}
 
+	public void registerLazyFactoryProvider(IAdapterManagerProvider factoryProvider) {
+		synchronized (lazyFactoryProviders) {
+			lazyFactoryProviders.add(factoryProvider);
+		}
+	}
+
+	public boolean unregisterLazyFactoryProvider(IAdapterManagerProvider factoryProvider) {
+		synchronized (lazyFactoryProviders) {
+			return lazyFactoryProviders.remove(factoryProvider);
+		}
+	}
+
 	public HashMap getFactories() {
+		// avoid the synchronize if we don't have to call it
+		if (lazyFactoryProviders.size() == 0)
+			return factories;
+		synchronized (lazyFactoryProviders) {
+			while (lazyFactoryProviders.size() > 0) {
+				IAdapterManagerProvider provider = (IAdapterManagerProvider) lazyFactoryProviders.remove(0);
+				if (provider.addFactories(this))
+					flushLookup();
+			}
+		}
 		return factories;
 	}
 }
diff --git a/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/IAdapterManagerProvider.java b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/IAdapterManagerProvider.java
new file mode 100644
index 0000000..d7077a2
--- /dev/null
+++ b/bundles/org.eclipse.equinox.common/src/org/eclipse/core/internal/runtime/IAdapterManagerProvider.java
@@ -0,0 +1,30 @@
+/*******************************************************************************
+ * Copyright (c) 2006 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.core.internal.runtime;
+
+/**
+ * The callback interface for the elements desiring to lazily supply
+ * information to the adapter manager.
+ * 
+ * @since org.eclipse.core.runtime 3.2
+ */
+public interface IAdapterManagerProvider {
+
+	/**
+	 * Add factories. The method called before the AdapterManager starts
+	 * using factories.
+	 *  
+	 * @param adapterManager the adapter manager that is about to be used
+	 * @return <code>true</code> if factories were added; <code>false</code> 
+	 * if no factories were added in this method call.
+	 */
+	public boolean addFactories(AdapterManager adapterManager);
+}
diff --git a/bundles/org.eclipse.equinox.preferences/META-INF/MANIFEST.MF b/bundles/org.eclipse.equinox.preferences/META-INF/MANIFEST.MF
index 86e8daa..8d1066f 100644
--- a/bundles/org.eclipse.equinox.preferences/META-INF/MANIFEST.MF
+++ b/bundles/org.eclipse.equinox.preferences/META-INF/MANIFEST.MF
@@ -8,10 +8,11 @@
 Bundle-Localization: plugin
 Require-Bundle: org.eclipse.equinox.common,
  org.eclipse.equinox.registry;resolution:=optional
-Export-Package: org.eclipse.core.internal.preferences;x-friends:="org.eclipse.core.resources,org.eclipse.core.runtime"; preferences="split"; mandatory:="preferences",
+Export-Package: org.eclipse.core.internal.preferences;x-friends:="org.eclipse.core.resources,org.eclipse.core.runtime",
+ org.eclipse.core.internal.preferences.exchange;x-friends:="org.eclipse.core.runtime",
  org.eclipse.core.runtime.preferences,
  org.osgi.service.prefs;version="1.1"
-Eclipse-LazyStart: true
+Eclipse-LazyStart: true; exceptions="org.eclipse.core.internal.preferences.exchange"
 Import-Package: org.eclipse.osgi.framework.log,
  org.eclipse.osgi.service.datalocation,
  org.eclipse.osgi.service.debug,
diff --git a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/Activator.java b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/Activator.java
index 4e9c541..88df616 100644
--- a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/Activator.java
+++ b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/Activator.java
@@ -28,6 +28,12 @@
 	public static final String PI_PREFERENCES = "org.eclipse.equinox.preferences"; //$NON-NLS-1$
 
 	/**
+	 * Eclipse property. Set to <code>false</code> to avoid registering JobManager
+	 * as an OSGi service.
+	 */
+	private static final String PROP_REGISTER_PERF_SERVICE = "eclipse.service.pref"; //$NON-NLS-1$
+	
+	/**
 	 * Track the registry service - only register preference service if the registry is 
 	 * available
 	 */
@@ -46,7 +52,7 @@
 	/**
 	 * This plugin provides the OSGi Preferences service.
 	 */
-	private ServiceRegistration osgiPreferencesService;
+	private ServiceRegistration osgiPreferencesService = null;
 
 	/* (non-Javadoc)
 	 * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
@@ -55,8 +61,12 @@
 		bundleContext = context;
 		processCommandLine();
 		PreferencesOSGiUtils.getDefault().openServices();
-		preferencesService = bundleContext.registerService(IPreferencesService.class.getName(), PreferencesService.getDefault(), new Hashtable());
-		osgiPreferencesService = bundleContext.registerService(org.osgi.service.prefs.PreferencesService.class.getName(), new OSGiPreferencesServiceManager(bundleContext), null);
+		
+		boolean shouldRegister = !"false".equalsIgnoreCase(context.getProperty(PROP_REGISTER_PERF_SERVICE)); //$NON-NLS-1$
+		if (shouldRegister) {
+			preferencesService = bundleContext.registerService(IPreferencesService.class.getName(), PreferencesService.getDefault(), new Hashtable());
+			osgiPreferencesService = bundleContext.registerService(org.osgi.service.prefs.PreferencesService.class.getName(), new OSGiPreferencesServiceManager(bundleContext), null);
+		}
 		// use the string for the class name here in case the registry isn't around
 		registryServiceTracker = new ServiceTracker(bundleContext, "org.eclipse.core.runtime.IExtensionRegistry", this); //$NON-NLS-1$
 		registryServiceTracker.open();
diff --git a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/DefaultPreferences.java b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/DefaultPreferences.java
index ec30fc6..1ec791d 100644
--- a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/DefaultPreferences.java
+++ b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/DefaultPreferences.java
@@ -14,6 +14,7 @@
 import java.lang.ref.WeakReference;
 import java.net.URL;
 import java.util.*;
+import org.eclipse.core.internal.preferences.exchange.IProductPreferencesService;
 import org.eclipse.core.internal.runtime.RuntimeLog;
 import org.eclipse.core.runtime.*;
 import org.eclipse.core.runtime.preferences.*;
diff --git a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/PreferenceServiceRegistryHelper.java b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/PreferenceServiceRegistryHelper.java
index abf532f..b3a4ac5 100644
--- a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/PreferenceServiceRegistryHelper.java
+++ b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/PreferenceServiceRegistryHelper.java
@@ -12,6 +12,7 @@
 
 import java.lang.ref.WeakReference;
 import java.util.*;
+import org.eclipse.core.internal.preferences.exchange.ILegacyPreferences;
 import org.eclipse.core.internal.runtime.RuntimeLog;
 import org.eclipse.core.runtime.*;
 import org.eclipse.core.runtime.preferences.*;
diff --git a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/PreferencesOSGiUtils.java b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/PreferencesOSGiUtils.java
index bab1d84..93bc1f1 100644
--- a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/PreferencesOSGiUtils.java
+++ b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/PreferencesOSGiUtils.java
@@ -10,6 +10,7 @@
  *******************************************************************************/
 package org.eclipse.core.internal.preferences;
 
+import org.eclipse.core.internal.preferences.exchange.ILegacyPreferences;
 import org.eclipse.osgi.framework.log.FrameworkLog;
 import org.eclipse.osgi.service.datalocation.Location;
 import org.eclipse.osgi.service.debug.DebugOptions;
diff --git a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/ILegacyPreferences.java b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/exchange/ILegacyPreferences.java
similarity index 92%
rename from bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/ILegacyPreferences.java
rename to bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/exchange/ILegacyPreferences.java
index 149bae8..34f93ae 100644
--- a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/ILegacyPreferences.java
+++ b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/exchange/ILegacyPreferences.java
@@ -8,13 +8,13 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
-package org.eclipse.core.internal.preferences;
+package org.eclipse.core.internal.preferences.exchange;
 
 /**
  * Provides initialization of the legacy preferences as described in
  * the Plugin class.
  * 
- * @deprecated
+ * @depreceated
  */
 public interface ILegacyPreferences {
 	/**
diff --git a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/IProductPreferencesService.java b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/exchange/IProductPreferencesService.java
similarity index 69%
rename from bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/IProductPreferencesService.java
rename to bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/exchange/IProductPreferencesService.java
index 4396b4f..e4b20d9 100644
--- a/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/IProductPreferencesService.java
+++ b/bundles/org.eclipse.equinox.preferences/src/org/eclipse/core/internal/preferences/exchange/IProductPreferencesService.java
@@ -8,22 +8,30 @@
  * Contributors:
  *     IBM Corporation - initial API and implementation
  *******************************************************************************/
-package org.eclipse.core.internal.preferences;
+package org.eclipse.core.internal.preferences.exchange;
 
 import java.util.Properties;
 
 /**
  * A product can customize preferences by implementing this service.
  * 
- * @since org.eclipse.equinox.preferences 3.2
+ * This interface is likely going to change as the application model is introduced
+ * in which point it might be kept for backward compatibility or removed entirely.
+ * 
+ * @since org.eclipse.equinox.common 3.2
  */
 public interface IProductPreferencesService {
+
 	/**
+	 * Returns properties specified in the product customization file.
+	 * 
 	 * @return default preferences specified by the product. 
 	 */
 	public Properties getProductCustomization();
 
 	/**
+	 * Returns translations for the customized properties.
+	 *  
 	 * @return translation table for default preferences
 	 */
 	public Properties getProductTranslation();