Bug 10645 - add p2 install operation for docs plugins
authordadubrow
Mon, 13 Sep 2010 15:22:01 -0500
changeset 1994 e9be28ae423a
parent 1993 2288674e8199
child 1995 b4d36ee06879
Bug 10645 - add p2 install operation for docs plugins
core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/NewPluginChecker.java
core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/SDKPreferencePage.java
core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/sdk/ui/SDKUIPlugin.java
core/com.nokia.carbide.discovery.ui/META-INF/MANIFEST.MF
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/discovery/ui/Activator.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/DynamicP2Installer.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/FeatureInfo.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/FeatureInstallOperation.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/ImportExportData.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/P2Utils.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/Streamer.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/AbstractImportExportPage.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportPage.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportWizard.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/FeatureInfo.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/FeatureInstallOperation.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportExportData.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportPage.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportWizard.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/P2Utils.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/Streamer.java
--- a/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/NewPluginChecker.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/NewPluginChecker.java	Mon Sep 13 15:22:01 2010 -0500
@@ -22,21 +22,21 @@
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.core.runtime.jobs.Job;
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.IWorkbench;
 import org.eclipse.ui.IWorkbenchWindow;
 
-import com.nokia.carbide.cpp.internal.api.sdk.ISBSv1BuildInfo;
-import com.nokia.carbide.cpp.internal.sdk.core.model.DynamicFeatureInstaller;
+import com.nokia.carbide.cpp.internal.api.sdk.ISBSv2BuildInfo;
 import com.nokia.carbide.cpp.sdk.core.ISymbianBuilderID;
 import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
 import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
 import com.nokia.carbide.cpp.sdk.ui.SDKUIPlugin;
+import com.nokia.carbide.internal.discovery.ui.p2.DynamicP2Installer;
 import com.nokia.cpp.internal.api.utils.ui.WorkbenchUtils;
 
-@SuppressWarnings("restriction")
 public class NewPluginChecker {
 
 	private static final String SDK_FEATURE_SUBDIR = "epoc32/kit";  //$NON-NLS-1$
@@ -54,16 +54,21 @@
 				boolean installed = false;
 				boolean oneSDKWasScanned = false;
 				for (ISymbianSDK sdk : sdkList) {
-					ISBSv1BuildInfo sbsv1BuildInfo = (ISBSv1BuildInfo)sdk.getBuildInfo(ISymbianBuilderID.SBSV1_BUILDER);
-					if (sbsv1BuildInfo != null) {
-						if (sbsv1BuildInfo.isPreviouslyScanned() == false) {
+					ISBSv2BuildInfo sbsv2BuildInfo = (ISBSv2BuildInfo)sdk.getBuildInfo(ISymbianBuilderID.SBSV2_BUILDER);
+					if (sbsv2BuildInfo != null) {
+						if (sbsv2BuildInfo.isPreviouslyScanned() == false) {
 							oneSDKWasScanned = true;
 							// XML was parsed, now try to run the feature installer
-							sbsv1BuildInfo.setPreviouslyScanned(true);
+							sbsv2BuildInfo.setPreviouslyScanned(true);
 							File featureDir = new File(sdk.getEPOCROOT() + SDK_FEATURE_SUBDIR);
 							try {
-								DynamicFeatureInstaller installer = new DynamicFeatureInstaller(featureDir, null);
-								if (installer.install()) {
+								IStatus status = DynamicP2Installer.install(featureDir, new NullProgressMonitor());
+								if (status.isOK()) {
+									// TODO advise user??
+									installed = true;
+								}
+								else if (status.getSeverity() == IStatus.CANCEL) {
+									// TODO was installed 
 									installed = true;
 								}
 							} catch (Exception e) {
@@ -81,7 +86,7 @@
 				}
 				if (installed) {
 					// plugins from some SDK were installed
-					doEclipseRestartDialog(workbench);
+					//doEclipseRestartDialog(workbench);
 				}
 				
 				return Status.OK_STATUS;
--- a/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/SDKPreferencePage.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/SDKPreferencePage.java	Mon Sep 13 15:22:01 2010 -0500
@@ -71,6 +71,7 @@
 import com.nokia.carbide.cpp.sdk.core.ISDKManager;
 import com.nokia.carbide.cpp.sdk.core.ISymbianSDK;
 import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
+import com.nokia.carbide.cpp.sdk.ui.SDKUIPlugin;
 import com.nokia.carbide.cpp.sdk.ui.shared.AddSDKDialog;
 import com.nokia.carbide.cpp.ui.TextAndDialogCellEditor;
 import com.nokia.cpp.internal.api.utils.ui.BrowseDialogUtils;
@@ -536,6 +537,7 @@
 		addSDKComponentTableItems();
 		sdkListTableViewer.refresh();
 		selectSDKEntry(0);
+		NewPluginChecker.checkForNewlyInstalledPlugins(SDKUIPlugin.getDefault().getWorkbench());
 		rescanButton.setText(Messages.getString("SDKPreferencePage.Rescan_Button_Label")); //$NON-NLS-1$
 		rescanButton.setEnabled(true);
 	}
--- a/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/sdk/ui/SDKUIPlugin.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/sdk/ui/SDKUIPlugin.java	Mon Sep 13 15:22:01 2010 -0500
@@ -28,6 +28,7 @@
 import com.nokia.carbide.cpp.internal.api.sdk.ISDKManagerInternal;
 import com.nokia.carbide.cpp.internal.api.sdk.ui.SBSv1PlatformFilterComposite;
 import com.nokia.carbide.cpp.internal.sdk.core.model.SDKManager;
+import com.nokia.carbide.cpp.internal.sdk.ui.NewPluginChecker;
 import com.nokia.carbide.cpp.internal.sdk.ui.SDKUIPreferenceConstants;
 import com.nokia.carbide.cpp.sdk.core.ISDKManager;
 import com.nokia.carbide.cpp.sdk.core.SDKCorePlugin;
@@ -60,6 +61,7 @@
 	 */
 	public void start(BundleContext context) throws Exception {
 		super.start(context);
+		NewPluginChecker.checkForNewlyInstalledPlugins(getWorkbench());
 		
 		ISDKManager sdkMgr = SDKCorePlugin.getSDKManager();
 		if (HostOS.IS_WIN32){
--- a/core/com.nokia.carbide.discovery.ui/META-INF/MANIFEST.MF	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/META-INF/MANIFEST.MF	Mon Sep 13 15:22:01 2010 -0500
@@ -8,6 +8,7 @@
 Require-Bundle: org.eclipse.ui,
  org.eclipse.core.runtime,
  org.eclipse.core.net;bundle-version="1.2.100",
+ org.eclipse.core.filesystem;bundle-version="1.3.0",
  org.eclipse.equinox.p2.discovery;bundle-version="1.0.0",
  org.eclipse.equinox.p2.discovery.compatibility;bundle-version="1.0.0",
  org.eclipse.equinox.p2.ui.discovery;bundle-version="1.0.0",
@@ -17,6 +18,7 @@
  org.eclipse.equinox.p2.metadata;bundle-version="2.0.0",
  org.eclipse.equinox.p2.repository;bundle-version="2.0.0",
  org.eclipse.equinox.p2.engine;bundle-version="2.0.0",
+ org.eclipse.equinox.p2.director;bundle-version="2.0.0",
  org.eclipse.jface.text,
  org.eclipse.ui.editors,
  org.eclipse.ui.forms;bundle-version="3.5.0",
@@ -30,5 +32,6 @@
  com.nokia.carbide.internal.discovery.ui.command;x-internal:=true,
  com.nokia.carbide.internal.discovery.ui.editor;x-internal:=true,
  com.nokia.carbide.internal.discovery.ui.extension;x-internal:=true,
+ com.nokia.carbide.internal.discovery.ui.p2;x-friends:="com.nokia.carbide.cpp.sdk.ui",
  com.nokia.carbide.internal.discovery.ui.view;x-internal:=true,
  com.nokia.carbide.internal.discovery.ui.wizard;x-friends:="com.nokia.carbide.cpp"
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/discovery/ui/Activator.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/discovery/ui/Activator.java	Mon Sep 13 15:22:01 2010 -0500
@@ -197,7 +197,10 @@
 	}
 
     public static IStatus makeErrorStatus(String message, Throwable t) {
-        return new Status(IStatus.ERROR, PLUGIN_ID, message, t);
+    	return makeStatus(IStatus.ERROR, message, t);
     }
 
+    public static IStatus makeStatus(int severity, String message, Throwable t) {
+    	return new Status(severity, PLUGIN_ID, message, t);
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/DynamicP2Installer.java	Mon Sep 13 15:22:01 2010 -0500
@@ -0,0 +1,163 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+*/
+
+package com.nokia.carbide.internal.discovery.ui.p2;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.net.URI;
+
+import org.eclipse.core.filesystem.URIUtil;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.equinox.internal.provisional.p2.director.IDirector;
+import org.eclipse.equinox.internal.provisional.p2.director.ProfileChangeRequest;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.engine.IProfile;
+import org.eclipse.equinox.p2.engine.IProfileRegistry;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.query.IQueryResult;
+import org.eclipse.equinox.p2.query.QueryUtil;
+import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
+import org.eclipse.equinox.p2.ui.ProvisioningUI;
+
+import com.nokia.carbide.discovery.ui.Activator;
+
+/**
+ * Installer to install features from a p2 repository at a supplied URL or directory.
+ * 
+ * The supplied directory should have as sub-directories features and plugins. These 
+ * sub-directories in turn can contain any number of features and their corresponding 
+ * plug-ins.
+ * 
+ * <p/>
+ * e.g.
+ * <p/>
+ * <pre>
+ * &lt;Feature Directory&gt;
+ *               |
+ *               | --- artifacts.jar
+ *               | --- content.jar
+ *               |
+ *               ----&lt;features&gt;
+ *                   |
+ *                   |----&lt;feature folder name&gt;
+ *                        |
+ *                        |---features.xml file (contains list of feature jars)
+ *               ----&lt;plugins&gt;
+ *                        |
+ *                        ---jar files;
+ * </pre>
+ */
+
+@SuppressWarnings("restriction")
+public class DynamicP2Installer {
+	
+	private IPath repositoryLocation;
+	private ProvisioningUI provisioningUI;
+	private IProvisioningAgent agent;
+	private IProfile profile;
+	
+	/**
+	 * Performs the install.
+	 * @param monitor An implementation of IProgressMonitor, usually showing the 
+	 * installation progress as a Progress Bar to the user.
+	 */
+	public static IStatus install(File repositoryDirectory, IProgressMonitor monitor) {
+		try {
+			DynamicP2Installer installer = new DynamicP2Installer(repositoryDirectory);
+			installer.doInstall(monitor);
+			return Status.OK_STATUS;
+		} catch (CoreException e) {
+			return e.getStatus();
+		} catch (FileNotFoundException e) {
+			return Activator.makeErrorStatus(null, e);
+		}
+	}
+
+	private DynamicP2Installer(File repositoryDirectory) throws FileNotFoundException {
+		checkRepository(repositoryDirectory);
+		repositoryLocation = new Path(repositoryDirectory.getAbsolutePath());
+		provisioningUI = ProvisioningUI.getDefaultUI();
+		agent = provisioningUI.getSession().getProvisioningAgent();
+		profile = getProfile();
+	}
+	
+	private void checkRepository(File repositoryDirectory) throws FileNotFoundException {
+		if (!repositoryDirectory.isDirectory()) {
+			throw new FileNotFoundException(repositoryDirectory + " is not a directory.");
+		}
+		if (!(new File(repositoryDirectory, "features").isDirectory())) {
+			throw new FileNotFoundException(repositoryDirectory + " missing \"features\" directory.");
+		}
+		if (!(new File(repositoryDirectory, "plugins").isDirectory())) {
+			throw new FileNotFoundException(repositoryDirectory + " missing \"plugins\" directory.");
+		}
+		if (!(new File(repositoryDirectory, "artifacts.jar").exists()) && !(new File(repositoryDirectory, "artifacts.xml").exists())) {
+			throw new FileNotFoundException(repositoryDirectory + " missing artifacts.jar.");
+		}
+		if (!(new File(repositoryDirectory, "content.jar").exists()) && !(new File(repositoryDirectory, "content.xml").exists())) {
+			throw new FileNotFoundException(repositoryDirectory + " missing content.jar.");
+		}
+	}
+
+	private void doInstall(IProgressMonitor monitor) throws CoreException {
+		URI uri = URIUtil.toURI(repositoryLocation);
+		IMetadataRepositoryManager metadataRepoManager = 
+			(IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
+		IArtifactRepositoryManager artifactRepoManager = 
+			(IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
+		try {
+			// add and load repository
+			metadataRepoManager.addRepository(uri);
+			IMetadataRepository metadataRepository = metadataRepoManager.loadRepository(uri, null);
+			artifactRepoManager.addRepository(uri);
+			artifactRepoManager.loadRepository(uri, null);
+			
+			// get IU from repository
+			IQueryResult<IInstallableUnit> units = metadataRepository.query(QueryUtil.createIUGroupQuery(), monitor);
+			if (units.isEmpty())
+				throw new CoreException(Activator.makeErrorStatus("Could not find installable unit", null));
+			
+			// check if installed
+			IQueryResult<IInstallableUnit> result = profile.query(QueryUtil.createIUQuery(units.iterator().next()), monitor);
+			if (!result.isEmpty())
+				throw new CoreException(Activator.makeStatus(IStatus.CANCEL, null, null)); // already installed
+			
+			// do provisioning operation
+			ProfileChangeRequest request = new ProfileChangeRequest(profile);
+			request.addAll(units.toUnmodifiableSet());
+			IDirector director = (IDirector) agent.getService(IDirector.SERVICE_NAME);
+			IStatus status = director.provision(request, null, monitor);
+	
+			if (!status.isOK())
+				throw new CoreException(status);
+		}
+		finally {
+			metadataRepoManager.removeRepository(uri);
+			artifactRepoManager.removeRepository(uri);
+		}
+	}
+
+	private IProfile getProfile() {
+		IProfileRegistry profileRegistry = (IProfileRegistry) agent.getService(IProfileRegistry.SERVICE_NAME);
+		return profileRegistry.getProfile(provisioningUI.getProfileId());
+	}
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/FeatureInfo.java	Mon Sep 13 15:22:01 2010 -0500
@@ -0,0 +1,78 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+package com.nokia.carbide.internal.discovery.ui.p2;
+
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.metadata.Version;
+
+public class FeatureInfo {
+	private String id;
+	private Version version;
+	
+	public FeatureInfo(IInstallableUnit iu) {
+		this(iu.getId(), iu.getVersion());
+	}
+	
+	public FeatureInfo(String id, Version version) {
+		this.id = id;
+		this.version = version;
+	}
+	
+	public String getId() {
+		return id;
+	}
+	
+	public Version getVersion() {
+		return version;
+	}
+	
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + ((id == null) ? 0 : id.hashCode());
+		result = prime * result + ((version == null) ? 0 : version.toString().hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		FeatureInfo other = (FeatureInfo) obj;
+		if (id == null) {
+			if (other.id != null)
+				return false;
+		} else if (!id.equals(other.id))
+			return false;
+		if (version == null) {
+			if (other.version != null)
+				return false;
+		} else if (!version.toString().equals(other.version.toString()))
+			return false;
+		return true;
+	}
+	
+	@Override
+	public String toString() {
+		return getId() + " " + getVersion().toString(); //$NON-NLS-1$
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/FeatureInstallOperation.java	Mon Sep 13 15:22:01 2010 -0500
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * All rights reserved.
+ * This component and the accompanying materials are made available
+ * under the terms of the License "Eclipse Public License v1.0"
+ * which accompanies this distribution, and is available
+ * at the URL "http://www.eclipse.org/legal/epl-v10.html".
+ *
+ * Initial Contributors:
+ * Nokia Corporation - initial contribution.
+ *
+ * Contributors:
+ *
+ * Description: 
+ *
+ */
+package com.nokia.carbide.internal.discovery.ui.p2;
+
+import java.lang.reflect.InvocationTargetException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.OperationCanceledException;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.equinox.p2.core.ProvisionException;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.operations.InstallOperation;
+import org.eclipse.equinox.p2.operations.ProvisioningSession;
+import org.eclipse.equinox.p2.operations.RepositoryTracker;
+import org.eclipse.equinox.p2.query.IQuery;
+import org.eclipse.equinox.p2.query.IQueryResult;
+import org.eclipse.equinox.p2.query.IQueryable;
+import org.eclipse.equinox.p2.query.QueryUtil;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
+import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
+import org.eclipse.equinox.p2.ui.ProvisioningUI;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.widgets.Display;
+
+import com.nokia.carbide.discovery.ui.Messages;
+
+public class FeatureInstallOperation implements IRunnableWithProgress {
+	
+	private Collection<URI> uris;
+	private Collection<FeatureInfo> featureInfos;
+	private boolean wantVersions;
+	private ProvisioningUI provisioningUI;
+	private Collection<IMetadataRepository> repositories;
+	private Collection<IInstallableUnit> ius;
+	private Collection<URI> urisUsed;
+
+	public FeatureInstallOperation(Collection<URI> uris, Collection<FeatureInfo> featureInfos, boolean wantVersions) {
+		this.uris = uris;
+		this.featureInfos = featureInfos;
+		this.wantVersions = wantVersions;
+		provisioningUI = ProvisioningUI.getDefaultUI();
+	}
+
+	@Override
+	public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+		try {
+			doInstall(monitor);
+		} catch (OperationCanceledException e) {
+			throw new InterruptedException();
+		} catch (CoreException e) {
+			throw new InvocationTargetException(e);
+		}
+	}
+
+	public void doInstall(IProgressMonitor monitor) throws OperationCanceledException, CoreException {
+		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.FeatureInstallOperation_ConfiguringTaskName, 100);
+		getRepositories(subMonitor.newChild(30));
+		findInstallableUnits(subMonitor.newChild(40));
+		final InstallOperation operation = resolve(subMonitor.newChild(30));
+		Display.getDefault().asyncExec(new Runnable() {
+			@Override
+			public void run() {
+				IQueryable<IInstallableUnit> additions = operation.getProvisioningPlan().getAdditions();
+				IQueryResult<IInstallableUnit> result = additions.query(QueryUtil.createIUGroupQuery(), new NullProgressMonitor());
+				provisioningUI.openInstallWizard(result.toSet(), operation, null);
+			}
+		});
+	}
+
+	private void getRepositories(SubMonitor monitor) throws ProvisionException, OperationCanceledException {
+		monitor.setWorkRemaining(uris.size());
+		repositories = new ArrayList<IMetadataRepository>();
+		ProvisioningSession session = provisioningUI.getSession();
+		RepositoryTracker repositoryTracker = provisioningUI.getRepositoryTracker();
+		IMetadataRepositoryManager manager = 
+			(IMetadataRepositoryManager) session.getProvisioningAgent().getService(IMetadataRepositoryManager.SERVICE_NAME);
+		for (URI uri : uris) {
+			checkIfCanceled(monitor);
+			repositoryTracker.addRepository(uri, null, session);
+			repositories.add(manager.loadRepository(uri, monitor.newChild(1)));
+		}
+	}
+
+	private void findInstallableUnits(SubMonitor monitor) throws ProvisionException {
+		monitor.setWorkRemaining(repositories.size() * featureInfos.size());
+		ius = new ArrayList<IInstallableUnit>();
+		urisUsed = new HashSet<URI>();
+		Set<FeatureInfo> remainingInfos = new HashSet<FeatureInfo>(featureInfos);
+		for (IMetadataRepository repository : repositories) {
+			checkIfCanceled(monitor);
+			IQueryResult<IInstallableUnit> iusInRepository = repository.query(QueryUtil.createIUGroupQuery(), monitor.newChild(1));
+			for (FeatureInfo featureInfo : new HashSet<FeatureInfo>(remainingInfos)) {
+				String id = featureInfo.getId();
+				IQuery<IInstallableUnit> iuQuery = wantVersions ?
+					QueryUtil.createIUQuery(id, featureInfo.getVersion()) :
+					QueryUtil.createLatestQuery(QueryUtil.createIUQuery(id));
+				IQueryResult<IInstallableUnit> result = iusInRepository.query(iuQuery, monitor.newChild(1));
+				if (!result.isEmpty()) {
+					ius.add(result.iterator().next());
+					urisUsed.add(repository.getLocation());
+					remainingInfos.remove(featureInfo);
+					if (remainingInfos.isEmpty())
+						break;
+				}
+			}
+		}
+
+		if (!remainingInfos.isEmpty()) {
+			StringBuilder sb = new StringBuilder();
+			sb.append(Messages.FeatureInstallOperation_MissingFeaturesError);
+			for (FeatureInfo featureInfo : remainingInfos) {
+				sb.append(Messages.FeatureInstallOperation_IdLabel);
+				sb.append(featureInfo.getId());
+				if (wantVersions) {
+					sb.append(Messages.FeatureInstallOperation_VersionLabel);
+					sb.append(featureInfo.getVersion().toString());
+				}
+				sb.append("\n"); //$NON-NLS-1$
+			}
+			throw new ProvisionException(sb.toString());
+		}
+		monitor.done();
+	}
+	
+	private InstallOperation resolve(SubMonitor monitor) throws CoreException {
+		checkIfCanceled(monitor);
+		URI[] uris = (URI[]) urisUsed.toArray(new URI[urisUsed.size()]);
+		InstallOperation installOperation = provisioningUI.getInstallOperation(ius, uris);
+		IStatus operationStatus = installOperation.resolveModal(monitor);
+		if (operationStatus.getSeverity() > IStatus.WARNING) {
+			throw new CoreException(operationStatus);
+		}
+		return installOperation;
+	}
+
+	private void checkIfCanceled(IProgressMonitor monitor) {
+		if (monitor.isCanceled()) {
+			throw new OperationCanceledException();
+		}
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/ImportExportData.java	Mon Sep 13 15:22:01 2010 -0500
@@ -0,0 +1,47 @@
+package com.nokia.carbide.internal.discovery.ui.p2;
+
+import java.net.URI;
+import java.util.Collection;
+import java.util.HashSet;
+
+
+public class ImportExportData {
+	private boolean wantsVersions;
+	private Collection<URI> uris;
+	private Collection<FeatureInfo> featureInfos;
+	
+	public ImportExportData() {
+		uris = new HashSet<URI>();
+		featureInfos = new HashSet<FeatureInfo>();
+	}
+	
+	public ImportExportData(boolean wantsVersions, Collection<URI> uris, Collection<FeatureInfo> featureInfos) {
+		this.wantsVersions = wantsVersions;
+		this.uris = uris;
+		this.featureInfos = featureInfos;
+	}
+
+	public void addURI(URI uri) {
+		uris.add(uri);
+	}
+	
+	public Collection<URI> getURIs() {
+		return uris;
+	}
+	
+	public void addFeatureInfo(FeatureInfo info) {
+		featureInfos.add(info);
+	}
+	
+	public Collection<FeatureInfo> getFeatureInfos() {
+		return featureInfos;
+	}
+	
+	public void setWantsVersions(boolean wantsVersions) {
+		this.wantsVersions = wantsVersions;
+	}
+	
+	public boolean getWantsVersions() {
+		return wantsVersions;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/P2Utils.java	Mon Sep 13 15:22:01 2010 -0500
@@ -0,0 +1,99 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+package com.nokia.carbide.internal.discovery.ui.p2;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.net.URI;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.NullProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.engine.IProfile;
+import org.eclipse.equinox.p2.engine.IProfileRegistry;
+import org.eclipse.equinox.p2.metadata.IInstallableUnit;
+import org.eclipse.equinox.p2.operations.ProvisioningSession;
+import org.eclipse.equinox.p2.query.IQueryResult;
+import org.eclipse.equinox.p2.query.QueryUtil;
+import org.eclipse.equinox.p2.ui.ProvisioningUI;
+import org.eclipse.osgi.service.datalocation.Location;
+
+import com.nokia.carbide.discovery.ui.Activator;
+import com.nokia.carbide.discovery.ui.Messages;
+
+public class P2Utils {
+	
+	public static Collection<URI> getKnownRepositories() {
+		ProvisioningUI provisioningUI = ProvisioningUI.getDefaultUI();
+		ProvisioningSession session = provisioningUI.getSession();
+		URI[] uris = provisioningUI.getRepositoryTracker().getKnownRepositories(session);
+		return Arrays.asList(uris);
+	}
+
+	public static Collection<FeatureInfo> getInstalledFeatures(IProgressMonitor monitor) {
+		Set<FeatureInfo> infos = new HashSet<FeatureInfo>();
+		ProvisioningUI provisioningUI = ProvisioningUI.getDefaultUI();
+		ProvisioningSession session = provisioningUI.getSession();
+		IProvisioningAgent agent = session.getProvisioningAgent();
+		IProfileRegistry profileRegistry = (IProfileRegistry) agent.getService(IProfileRegistry.SERVICE_NAME);
+		IProfile profile = null;
+		if (profileRegistry != null) {
+			profile = profileRegistry.getProfile(provisioningUI.getProfileId());
+			if (profile != null) {
+				IQueryResult<IInstallableUnit> result = 
+					profile.query(QueryUtil.createIUGroupQuery(), monitor);
+				for (Iterator<IInstallableUnit> iterator = result.iterator(); iterator.hasNext();) {
+					infos.add(new FeatureInfo((IInstallableUnit) iterator.next()));
+				}
+			}
+		}
+		return infos;
+	}
+	
+	public static void writeFeaturesToFile(File file) {
+		if (!file.exists()) {
+			Collection<FeatureInfo> initialFeatures = P2Utils.getInstalledFeatures(new NullProgressMonitor());
+			ImportExportData data = new ImportExportData(false, Collections.<URI>emptyList(), initialFeatures);
+			try {
+				Streamer.writeToXML(new FileOutputStream(file), data);
+			} catch (Exception e) {
+				Activator.logError(MessageFormat.format(
+						Messages.P2Utils_WriteInitialFeaturesFileError, file), e);
+			}
+		}
+	}
+
+	public static File getInitialFeaturesFile() {
+		Location installLocation = Platform.getInstallLocation();
+		URL url = installLocation.getURL();
+		IPath path = new Path(url.getPath());
+		path = path.append("configuration/initialFeatures.xml"); //$NON-NLS-1$
+		File file = path.toFile();
+		return file;
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/p2/Streamer.java	Mon Sep 13 15:22:01 2010 -0500
@@ -0,0 +1,145 @@
+/*
+* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*
+*/
+package com.nokia.carbide.internal.discovery.ui.p2;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.text.MessageFormat;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.equinox.p2.metadata.Version;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import com.nokia.carbide.discovery.ui.Activator;
+import com.nokia.carbide.discovery.ui.Messages;
+
+/**
+ * Serializes feature infos and repository URIs into output stream as XML
+ * Example serialized single test connection:
+ * 
+ * <blockquote><pre>
+ *&lt;featuresConfiguration version="1"&gt;
+ *	&lt;autoImportOriginalVersions value="false"/&gt;
+ *	&lt;repository uri="http://cdn.symbian.org/carbide/updates/3.0/discovery"/&gt;
+ *	&lt;feature id="com.nokia.example.feature.group" version="1.0.0"/&gt;
+ *&lt;/featuresConfiguration&gt;
+ * </pre></blockquote>
+ */
+public class Streamer {
+
+	private static final String CURRENT_VERSION = "1"; //$NON-NLS-1$
+	
+	private static final String ROOT_ELEMENT = "featuresConfiguration"; //$NON-NLS-1$
+	private static final String WANTS_VERSIONS_ELEMENT = "wantsOriginalVersions"; //$NON-NLS-1$
+	private static final String REPOSITORY_ELEMENT = "repository"; //$NON-NLS-1$
+	private static final String FEATURE_ELEMENT = "feature"; //$NON-NLS-1$
+
+	private static final String VERSION_ATTR = "version"; //$NON-NLS-1$
+	private static final String VALUE_ATTR = "value"; //$NON-NLS-1$
+	private static final String URI_ATTR = "uri"; //$NON-NLS-1$
+	private static final String ID_ATTR = "id"; //$NON-NLS-1$
+	
+	private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n"; //$NON-NLS-1$
+	
+	private static final String ROOT_START = "<" + ROOT_ELEMENT + " " + VERSION_ATTR + "=\"" + CURRENT_VERSION + "\">\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+	private static final String ROOT_END = "</" + ROOT_ELEMENT + ">\n"; //$NON-NLS-1$ //$NON-NLS-2$
+	
+	private static final String ORIGINAL_VERSION_FMT = "\t<" + WANTS_VERSIONS_ELEMENT + " " + VALUE_ATTR + "=\"{0}\"/>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final String REPOSITORY_FMT = "\t<" + REPOSITORY_ELEMENT + " " + URI_ATTR + "=\"{0}\"/>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+	private static final String FEATURE_FMT = "\t<" + FEATURE_ELEMENT + " " + ID_ATTR + "=\"{0}\" " + VERSION_ATTR + "=\"{1}\"/>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+
+	public static void writeToXML(OutputStream os, ImportExportData data) throws IOException {
+		os.write(XML_HEADER.getBytes());
+		os.write(ROOT_START.getBytes());
+		
+		// write auto-import original versions
+		String originalVersionElement = MessageFormat.format(ORIGINAL_VERSION_FMT, data.getWantsVersions());
+		os.write(originalVersionElement.getBytes());
+
+		// write the repositories
+		for (URI uri : data.getURIs()) {
+			String repositoryElement = MessageFormat.format(REPOSITORY_FMT, uri);
+			os.write(repositoryElement.getBytes());
+		}
+		
+		// write the featureInfos
+		for (FeatureInfo info : data.getFeatureInfos()) {
+			String featureElement = MessageFormat.format(FEATURE_FMT, info.getId(), info.getVersion());
+			os.write(featureElement.getBytes());
+		}
+		
+		os.write(ROOT_END.getBytes());
+		os.close();
+	}
+	
+	private static class ReadHandler extends DefaultHandler {
+
+		private final ImportExportData data;
+
+		public ReadHandler(ImportExportData data) {
+			this.data = data;
+		}
+
+		@Override
+		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+			if (ROOT_ELEMENT.equals(qName)) {
+				String versionStr = attributes.getValue(VERSION_ATTR);
+				if (!CURRENT_VERSION.equals(versionStr))
+					throw new IllegalArgumentException(
+							MessageFormat.format(Messages.Streamer_BadVersionError, CURRENT_VERSION, ROOT_ELEMENT));
+			}
+			else if (WANTS_VERSIONS_ELEMENT.equals(qName)) {
+				String wantsVersions = attributes.getValue(VALUE_ATTR);
+				data.setWantsVersions(Boolean.parseBoolean(wantsVersions));
+			}
+			else if (REPOSITORY_ELEMENT.equals(qName)) {
+				String uriStr = attributes.getValue(URI_ATTR);
+				try {
+					data.addURI(new URI(uriStr));
+				} catch (URISyntaxException e) {
+					Activator.logError(MessageFormat.format(Messages.Streamer_BadURIError, uriStr), e);
+				}
+			}
+			else if (FEATURE_ELEMENT.equals(qName)) {
+				String id = attributes.getValue(ID_ATTR);
+				String versionStr = attributes.getValue(VERSION_ATTR);
+				try {
+					Version version = Version.create(versionStr);
+					data.addFeatureInfo(new FeatureInfo(id, version));
+				} catch (IllegalArgumentException e) {
+					Activator.logError(MessageFormat.format(Messages.Streamer_VersionParseError, versionStr), e);
+				}
+			}
+		}
+	}
+	
+	public static ImportExportData readFromXML(InputStream is) throws SAXException, IOException, ParserConfigurationException {
+		SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
+		ImportExportData data = new ImportExportData();
+		parser.parse(is, new ReadHandler(data));
+		return data;
+	}
+	
+}
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/AbstractImportExportPage.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/AbstractImportExportPage.java	Mon Sep 13 15:22:01 2010 -0500
@@ -48,6 +48,7 @@
 
 import com.nokia.carbide.discovery.ui.Activator;
 import com.nokia.carbide.discovery.ui.Messages;
+import com.nokia.carbide.internal.discovery.ui.p2.FeatureInfo;
 
 /**
  * Abstract superclass of import and export page
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportPage.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportPage.java	Mon Sep 13 15:22:01 2010 -0500
@@ -38,6 +38,8 @@
 import org.eclipse.ui.progress.UIJob;
 
 import com.nokia.carbide.discovery.ui.Messages;
+import com.nokia.carbide.internal.discovery.ui.p2.FeatureInfo;
+import com.nokia.carbide.internal.discovery.ui.p2.P2Utils;
 import com.nokia.cpp.internal.api.utils.ui.BrowseDialogUtils;
 
 /**
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportWizard.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportWizard.java	Mon Sep 13 15:22:01 2010 -0500
@@ -34,6 +34,10 @@
 
 import com.nokia.carbide.discovery.ui.Activator;
 import com.nokia.carbide.discovery.ui.Messages;
+import com.nokia.carbide.internal.discovery.ui.p2.FeatureInfo;
+import com.nokia.carbide.internal.discovery.ui.p2.ImportExportData;
+import com.nokia.carbide.internal.discovery.ui.p2.P2Utils;
+import com.nokia.carbide.internal.discovery.ui.p2.Streamer;
 
 /**
  * Wizard for exporting installed features to a file
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/FeatureInfo.java	Mon Sep 13 15:01:12 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,78 +0,0 @@
-/*
-* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: 
-*
-*/
-package com.nokia.carbide.internal.discovery.ui.wizard;
-
-import org.eclipse.equinox.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.p2.metadata.Version;
-
-class FeatureInfo {
-	private String id;
-	private Version version;
-	
-	public FeatureInfo(IInstallableUnit iu) {
-		this(iu.getId(), iu.getVersion());
-	}
-	
-	public FeatureInfo(String id, Version version) {
-		this.id = id;
-		this.version = version;
-	}
-	
-	public String getId() {
-		return id;
-	}
-	
-	public Version getVersion() {
-		return version;
-	}
-	
-	@Override
-	public int hashCode() {
-		final int prime = 31;
-		int result = 1;
-		result = prime * result + ((id == null) ? 0 : id.hashCode());
-		result = prime * result + ((version == null) ? 0 : version.toString().hashCode());
-		return result;
-	}
-
-	@Override
-	public boolean equals(Object obj) {
-		if (this == obj)
-			return true;
-		if (obj == null)
-			return false;
-		if (getClass() != obj.getClass())
-			return false;
-		FeatureInfo other = (FeatureInfo) obj;
-		if (id == null) {
-			if (other.id != null)
-				return false;
-		} else if (!id.equals(other.id))
-			return false;
-		if (version == null) {
-			if (other.version != null)
-				return false;
-		} else if (!version.toString().equals(other.version.toString()))
-			return false;
-		return true;
-	}
-	
-	@Override
-	public String toString() {
-		return getId() + " " + getVersion().toString(); //$NON-NLS-1$
-	}
-}
\ No newline at end of file
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/FeatureInstallOperation.java	Mon Sep 13 15:01:12 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,163 +0,0 @@
-/*
- * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
- * All rights reserved.
- * This component and the accompanying materials are made available
- * under the terms of the License "Eclipse Public License v1.0"
- * which accompanies this distribution, and is available
- * at the URL "http://www.eclipse.org/legal/epl-v10.html".
- *
- * Initial Contributors:
- * Nokia Corporation - initial contribution.
- *
- * Contributors:
- *
- * Description: 
- *
- */
-package com.nokia.carbide.internal.discovery.ui.wizard;
-
-import java.lang.reflect.InvocationTargetException;
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.OperationCanceledException;
-import org.eclipse.core.runtime.SubMonitor;
-import org.eclipse.equinox.p2.core.ProvisionException;
-import org.eclipse.equinox.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.p2.operations.InstallOperation;
-import org.eclipse.equinox.p2.operations.ProvisioningSession;
-import org.eclipse.equinox.p2.operations.RepositoryTracker;
-import org.eclipse.equinox.p2.query.IQuery;
-import org.eclipse.equinox.p2.query.IQueryResult;
-import org.eclipse.equinox.p2.query.IQueryable;
-import org.eclipse.equinox.p2.query.QueryUtil;
-import org.eclipse.equinox.p2.repository.metadata.IMetadataRepository;
-import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
-import org.eclipse.equinox.p2.ui.ProvisioningUI;
-import org.eclipse.jface.operation.IRunnableWithProgress;
-import org.eclipse.swt.widgets.Display;
-
-import com.nokia.carbide.discovery.ui.Messages;
-
-class FeatureInstallOperation implements IRunnableWithProgress {
-	
-	private Collection<URI> uris;
-	private Collection<FeatureInfo> featureInfos;
-	private boolean wantVersions;
-	private ProvisioningUI provisioningUI;
-	private Collection<IMetadataRepository> repositories;
-	private Collection<IInstallableUnit> ius;
-	private Collection<URI> urisUsed;
-
-	public FeatureInstallOperation(Collection<URI> uris, Collection<FeatureInfo> featureInfos, boolean wantVersions) {
-		this.uris = uris;
-		this.featureInfos = featureInfos;
-		this.wantVersions = wantVersions;
-		provisioningUI = ProvisioningUI.getDefaultUI();
-	}
-
-	@Override
-	public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
-		try {
-			doInstall(monitor);
-		} catch (OperationCanceledException e) {
-			throw new InterruptedException();
-		} catch (CoreException e) {
-			throw new InvocationTargetException(e);
-		}
-	}
-
-	public void doInstall(IProgressMonitor monitor) throws OperationCanceledException, CoreException {
-		SubMonitor subMonitor = SubMonitor.convert(monitor, Messages.FeatureInstallOperation_ConfiguringTaskName, 100);
-		getRepositories(subMonitor.newChild(30));
-		findInstallableUnits(subMonitor.newChild(40));
-		final InstallOperation operation = resolve(subMonitor.newChild(30));
-		Display.getDefault().asyncExec(new Runnable() {
-			@Override
-			public void run() {
-				IQueryable<IInstallableUnit> additions = operation.getProvisioningPlan().getAdditions();
-				IQueryResult<IInstallableUnit> result = additions.query(QueryUtil.createIUGroupQuery(), new NullProgressMonitor());
-				provisioningUI.openInstallWizard(result.toSet(), operation, null);
-			}
-		});
-	}
-
-	private void getRepositories(SubMonitor monitor) throws ProvisionException, OperationCanceledException {
-		monitor.setWorkRemaining(uris.size());
-		repositories = new ArrayList<IMetadataRepository>();
-		ProvisioningSession session = provisioningUI.getSession();
-		RepositoryTracker repositoryTracker = provisioningUI.getRepositoryTracker();
-		IMetadataRepositoryManager manager = 
-			(IMetadataRepositoryManager) session.getProvisioningAgent().getService(IMetadataRepositoryManager.SERVICE_NAME);
-		for (URI uri : uris) {
-			checkIfCanceled(monitor);
-			repositoryTracker.addRepository(uri, null, session);
-			repositories.add(manager.loadRepository(uri, monitor.newChild(1)));
-		}
-	}
-
-	private void findInstallableUnits(SubMonitor monitor) throws ProvisionException {
-		monitor.setWorkRemaining(repositories.size() * featureInfos.size());
-		ius = new ArrayList<IInstallableUnit>();
-		urisUsed = new HashSet<URI>();
-		Set<FeatureInfo> remainingInfos = new HashSet<FeatureInfo>(featureInfos);
-		for (IMetadataRepository repository : repositories) {
-			checkIfCanceled(monitor);
-			IQueryResult<IInstallableUnit> iusInRepository = repository.query(QueryUtil.createIUGroupQuery(), monitor.newChild(1));
-			for (FeatureInfo featureInfo : new HashSet<FeatureInfo>(remainingInfos)) {
-				String id = featureInfo.getId();
-				IQuery<IInstallableUnit> iuQuery = wantVersions ?
-					QueryUtil.createIUQuery(id, featureInfo.getVersion()) :
-					QueryUtil.createLatestQuery(QueryUtil.createIUQuery(id));
-				IQueryResult<IInstallableUnit> result = iusInRepository.query(iuQuery, monitor.newChild(1));
-				if (!result.isEmpty()) {
-					ius.add(result.iterator().next());
-					urisUsed.add(repository.getLocation());
-					remainingInfos.remove(featureInfo);
-					if (remainingInfos.isEmpty())
-						break;
-				}
-			}
-		}
-
-		if (!remainingInfos.isEmpty()) {
-			StringBuilder sb = new StringBuilder();
-			sb.append(Messages.FeatureInstallOperation_MissingFeaturesError);
-			for (FeatureInfo featureInfo : remainingInfos) {
-				sb.append(Messages.FeatureInstallOperation_IdLabel);
-				sb.append(featureInfo.getId());
-				if (wantVersions) {
-					sb.append(Messages.FeatureInstallOperation_VersionLabel);
-					sb.append(featureInfo.getVersion().toString());
-				}
-				sb.append("\n"); //$NON-NLS-1$
-			}
-			throw new ProvisionException(sb.toString());
-		}
-		monitor.done();
-	}
-	
-	private InstallOperation resolve(SubMonitor monitor) throws CoreException {
-		checkIfCanceled(monitor);
-		URI[] uris = (URI[]) urisUsed.toArray(new URI[urisUsed.size()]);
-		InstallOperation installOperation = provisioningUI.getInstallOperation(ius, uris);
-		IStatus operationStatus = installOperation.resolveModal(monitor);
-		if (operationStatus.getSeverity() > IStatus.WARNING) {
-			throw new CoreException(operationStatus);
-		}
-		return installOperation;
-	}
-
-	private void checkIfCanceled(IProgressMonitor monitor) {
-		if (monitor.isCanceled()) {
-			throw new OperationCanceledException();
-		}
-	}
-}
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportExportData.java	Mon Sep 13 15:01:12 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,46 +0,0 @@
-package com.nokia.carbide.internal.discovery.ui.wizard;
-
-import java.net.URI;
-import java.util.Collection;
-import java.util.HashSet;
-
-class ImportExportData {
-	private boolean wantsVersions;
-	private Collection<URI> uris;
-	private Collection<FeatureInfo> featureInfos;
-	
-	public ImportExportData() {
-		uris = new HashSet<URI>();
-		featureInfos = new HashSet<FeatureInfo>();
-	}
-	
-	public ImportExportData(boolean wantsVersions, Collection<URI> uris, Collection<FeatureInfo> featureInfos) {
-		this.wantsVersions = wantsVersions;
-		this.uris = uris;
-		this.featureInfos = featureInfos;
-	}
-
-	public void addURI(URI uri) {
-		uris.add(uri);
-	}
-	
-	public Collection<URI> getURIs() {
-		return uris;
-	}
-	
-	public void addFeatureInfo(FeatureInfo info) {
-		featureInfos.add(info);
-	}
-	
-	public Collection<FeatureInfo> getFeatureInfos() {
-		return featureInfos;
-	}
-	
-	public void setWantsVersions(boolean wantsVersions) {
-		this.wantsVersions = wantsVersions;
-	}
-	
-	public boolean getWantsVersions() {
-		return wantsVersions;
-	}
-}
\ No newline at end of file
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportPage.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportPage.java	Mon Sep 13 15:22:01 2010 -0500
@@ -44,6 +44,9 @@
 
 import com.nokia.carbide.discovery.ui.Activator;
 import com.nokia.carbide.discovery.ui.Messages;
+import com.nokia.carbide.internal.discovery.ui.p2.FeatureInfo;
+import com.nokia.carbide.internal.discovery.ui.p2.ImportExportData;
+import com.nokia.carbide.internal.discovery.ui.p2.Streamer;
 import com.nokia.cpp.internal.api.utils.ui.BrowseDialogUtils;
 
 /**
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportWizard.java	Mon Sep 13 15:01:12 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportWizard.java	Mon Sep 13 15:22:01 2010 -0500
@@ -30,6 +30,7 @@
 
 import com.nokia.carbide.discovery.ui.Activator;
 import com.nokia.carbide.discovery.ui.Messages;
+import com.nokia.carbide.internal.discovery.ui.p2.FeatureInstallOperation;
 
 /**
  * Wizard for importing installed features from a file and install them
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/P2Utils.java	Mon Sep 13 15:01:12 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,99 +0,0 @@
-/*
-* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: 
-*
-*/
-package com.nokia.carbide.internal.discovery.ui.wizard;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.net.URI;
-import java.net.URL;
-import java.text.MessageFormat;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.NullProgressMonitor;
-import org.eclipse.core.runtime.Path;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.equinox.p2.core.IProvisioningAgent;
-import org.eclipse.equinox.p2.engine.IProfile;
-import org.eclipse.equinox.p2.engine.IProfileRegistry;
-import org.eclipse.equinox.p2.metadata.IInstallableUnit;
-import org.eclipse.equinox.p2.operations.ProvisioningSession;
-import org.eclipse.equinox.p2.query.IQueryResult;
-import org.eclipse.equinox.p2.query.QueryUtil;
-import org.eclipse.equinox.p2.ui.ProvisioningUI;
-import org.eclipse.osgi.service.datalocation.Location;
-
-import com.nokia.carbide.discovery.ui.Activator;
-import com.nokia.carbide.discovery.ui.Messages;
-
-public class P2Utils {
-	
-	public static Collection<URI> getKnownRepositories() {
-		ProvisioningUI provisioningUI = ProvisioningUI.getDefaultUI();
-		ProvisioningSession session = provisioningUI.getSession();
-		URI[] uris = provisioningUI.getRepositoryTracker().getKnownRepositories(session);
-		return Arrays.asList(uris);
-	}
-
-	public static Collection<FeatureInfo> getInstalledFeatures(IProgressMonitor monitor) {
-		Set<FeatureInfo> infos = new HashSet<FeatureInfo>();
-		ProvisioningUI provisioningUI = ProvisioningUI.getDefaultUI();
-		ProvisioningSession session = provisioningUI.getSession();
-		IProvisioningAgent agent = session.getProvisioningAgent();
-		IProfileRegistry profileRegistry = (IProfileRegistry) agent.getService(IProfileRegistry.SERVICE_NAME);
-		IProfile profile = null;
-		if (profileRegistry != null) {
-			profile = profileRegistry.getProfile(provisioningUI.getProfileId());
-			if (profile != null) {
-				IQueryResult<IInstallableUnit> result = 
-					profile.query(QueryUtil.createIUGroupQuery(), monitor);
-				for (Iterator<IInstallableUnit> iterator = result.iterator(); iterator.hasNext();) {
-					infos.add(new FeatureInfo((IInstallableUnit) iterator.next()));
-				}
-			}
-		}
-		return infos;
-	}
-	
-	public static void writeFeaturesToFile(File file) {
-		if (!file.exists()) {
-			Collection<FeatureInfo> initialFeatures = P2Utils.getInstalledFeatures(new NullProgressMonitor());
-			ImportExportData data = new ImportExportData(false, Collections.<URI>emptyList(), initialFeatures);
-			try {
-				Streamer.writeToXML(new FileOutputStream(file), data);
-			} catch (Exception e) {
-				Activator.logError(MessageFormat.format(
-						Messages.P2Utils_WriteInitialFeaturesFileError, file), e);
-			}
-		}
-	}
-
-	public static File getInitialFeaturesFile() {
-		Location installLocation = Platform.getInstallLocation();
-		URL url = installLocation.getURL();
-		IPath path = new Path(url.getPath());
-		path = path.append("configuration/initialFeatures.xml"); //$NON-NLS-1$
-		File file = path.toFile();
-		return file;
-	}
-}
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/Streamer.java	Mon Sep 13 15:01:12 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,145 +0,0 @@
-/*
-* Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
-* All rights reserved.
-* This component and the accompanying materials are made available
-* under the terms of the License "Eclipse Public License v1.0"
-* which accompanies this distribution, and is available
-* at the URL "http://www.eclipse.org/legal/epl-v10.html".
-*
-* Initial Contributors:
-* Nokia Corporation - initial contribution.
-*
-* Contributors:
-*
-* Description: 
-*
-*/
-package com.nokia.carbide.internal.discovery.ui.wizard;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.text.MessageFormat;
-
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.parsers.SAXParser;
-import javax.xml.parsers.SAXParserFactory;
-
-import org.eclipse.equinox.p2.metadata.Version;
-import org.xml.sax.Attributes;
-import org.xml.sax.SAXException;
-import org.xml.sax.helpers.DefaultHandler;
-
-import com.nokia.carbide.discovery.ui.Activator;
-import com.nokia.carbide.discovery.ui.Messages;
-
-/**
- * Serializes feature infos and repository URIs into output stream as XML
- * Example serialized single test connection:
- * 
- * <blockquote><pre>
- *&lt;featuresConfiguration version="1"&gt;
- *	&lt;autoImportOriginalVersions value="false"/&gt;
- *	&lt;repository uri="http://cdn.symbian.org/carbide/updates/3.0/discovery"/&gt;
- *	&lt;feature id="com.nokia.example.feature.group" version="1.0.0"/&gt;
- *&lt;/featuresConfiguration&gt;
- * </pre></blockquote>
- */
-class Streamer {
-
-	private static final String CURRENT_VERSION = "1"; //$NON-NLS-1$
-	
-	private static final String ROOT_ELEMENT = "featuresConfiguration"; //$NON-NLS-1$
-	private static final String WANTS_VERSIONS_ELEMENT = "wantsOriginalVersions"; //$NON-NLS-1$
-	private static final String REPOSITORY_ELEMENT = "repository"; //$NON-NLS-1$
-	private static final String FEATURE_ELEMENT = "feature"; //$NON-NLS-1$
-
-	private static final String VERSION_ATTR = "version"; //$NON-NLS-1$
-	private static final String VALUE_ATTR = "value"; //$NON-NLS-1$
-	private static final String URI_ATTR = "uri"; //$NON-NLS-1$
-	private static final String ID_ATTR = "id"; //$NON-NLS-1$
-	
-	private static final String XML_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n"; //$NON-NLS-1$
-	
-	private static final String ROOT_START = "<" + ROOT_ELEMENT + " " + VERSION_ATTR + "=\"" + CURRENT_VERSION + "\">\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-	private static final String ROOT_END = "</" + ROOT_ELEMENT + ">\n"; //$NON-NLS-1$ //$NON-NLS-2$
-	
-	private static final String ORIGINAL_VERSION_FMT = "\t<" + WANTS_VERSIONS_ELEMENT + " " + VALUE_ATTR + "=\"{0}\"/>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-	private static final String REPOSITORY_FMT = "\t<" + REPOSITORY_ELEMENT + " " + URI_ATTR + "=\"{0}\"/>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-	private static final String FEATURE_FMT = "\t<" + FEATURE_ELEMENT + " " + ID_ATTR + "=\"{0}\" " + VERSION_ATTR + "=\"{1}\"/>\n"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
-
-	public static void writeToXML(OutputStream os, ImportExportData data) throws IOException {
-		os.write(XML_HEADER.getBytes());
-		os.write(ROOT_START.getBytes());
-		
-		// write auto-import original versions
-		String originalVersionElement = MessageFormat.format(ORIGINAL_VERSION_FMT, data.getWantsVersions());
-		os.write(originalVersionElement.getBytes());
-
-		// write the repositories
-		for (URI uri : data.getURIs()) {
-			String repositoryElement = MessageFormat.format(REPOSITORY_FMT, uri);
-			os.write(repositoryElement.getBytes());
-		}
-		
-		// write the featureInfos
-		for (FeatureInfo info : data.getFeatureInfos()) {
-			String featureElement = MessageFormat.format(FEATURE_FMT, info.getId(), info.getVersion());
-			os.write(featureElement.getBytes());
-		}
-		
-		os.write(ROOT_END.getBytes());
-		os.close();
-	}
-	
-	private static class ReadHandler extends DefaultHandler {
-
-		private final ImportExportData data;
-
-		public ReadHandler(ImportExportData data) {
-			this.data = data;
-		}
-
-		@Override
-		public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
-			if (ROOT_ELEMENT.equals(qName)) {
-				String versionStr = attributes.getValue(VERSION_ATTR);
-				if (!CURRENT_VERSION.equals(versionStr))
-					throw new IllegalArgumentException(
-							MessageFormat.format(Messages.Streamer_BadVersionError, CURRENT_VERSION, ROOT_ELEMENT));
-			}
-			else if (WANTS_VERSIONS_ELEMENT.equals(qName)) {
-				String wantsVersions = attributes.getValue(VALUE_ATTR);
-				data.setWantsVersions(Boolean.parseBoolean(wantsVersions));
-			}
-			else if (REPOSITORY_ELEMENT.equals(qName)) {
-				String uriStr = attributes.getValue(URI_ATTR);
-				try {
-					data.addURI(new URI(uriStr));
-				} catch (URISyntaxException e) {
-					Activator.logError(MessageFormat.format(Messages.Streamer_BadURIError, uriStr), e);
-				}
-			}
-			else if (FEATURE_ELEMENT.equals(qName)) {
-				String id = attributes.getValue(ID_ATTR);
-				String versionStr = attributes.getValue(VERSION_ATTR);
-				try {
-					Version version = Version.create(versionStr);
-					data.addFeatureInfo(new FeatureInfo(id, version));
-				} catch (IllegalArgumentException e) {
-					Activator.logError(MessageFormat.format(Messages.Streamer_VersionParseError, versionStr), e);
-				}
-			}
-		}
-	}
-	
-	public static ImportExportData readFromXML(InputStream is) throws SAXException, IOException, ParserConfigurationException {
-		SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
-		ImportExportData data = new ImportExportData();
-		parser.parse(is, new ReadHandler(data));
-		return data;
-	}
-	
-}