initial commit of feature config import
authordadubrow
Thu, 12 Aug 2010 15:22:11 -0500
changeset 1818 bb528d06abcd
parent 1817 4eae2726ff31
child 1822 8fdfd1446ad7
initial commit of feature config import
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/view/InstallExtensionsPortalExtension.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/FeatureUtils.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.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/view/InstallExtensionsPortalExtension.java	Thu Aug 12 13:56:20 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/view/InstallExtensionsPortalExtension.java	Thu Aug 12 15:22:11 2010 -0500
@@ -92,6 +92,7 @@
 	private void showWizard(IWorkbenchWizard wizard) {
 		wizard.init(PlatformUI.getWorkbench(), StructuredSelection.EMPTY);
         WizardDialog dialog = new WizardDialog(part.getEditorSite().getShell(), wizard);
+		dialog.setMinimumPageSize(550, 250);
         dialog.create();
         dialog.open();
 	}
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/AbstractImportExportPage.java	Thu Aug 12 13:56:20 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/AbstractImportExportPage.java	Thu Aug 12 15:22:11 2010 -0500
@@ -1,25 +1,26 @@
 /*
-* 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: 
-*
-*/
+ * 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.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 
+import org.eclipse.jface.dialogs.Dialog;
 import org.eclipse.jface.layout.GridDataFactory;
 import org.eclipse.jface.layout.GridLayoutFactory;
 import org.eclipse.jface.resource.ImageDescriptor;
@@ -52,61 +53,68 @@
 	protected Text pathText;
 	protected Button browseButton;
 	protected CheckboxTableViewer viewer;
-	protected static final ImageDescriptor FEATURE_IMGDESC = 
-		Activator.getImageDescriptor("icons/iu_obj.gif"); //$NON-NLS-1$
+	protected static final ImageDescriptor FEATURE_IMGDESC = Activator
+			.getImageDescriptor("icons/iu_obj.gif"); //$NON-NLS-1$
 	protected Image featureImg;
 
 	public AbstractImportExportPage(String pageName) {
 		super(pageName);
 	}
-	
+
 	public void createControl(Composite parent) {
-        initializeDialogUnits(parent);
-        featureImg = FEATURE_IMGDESC.createImage();
+		initializeDialogUnits(parent);
+		featureImg = FEATURE_IMGDESC.createImage();
 
-        Composite composite = new Composite(parent, SWT.NONE);
-        GridLayoutFactory.swtDefaults().numColumns(2).applyTo(composite);
-        GridDataFactory.fillDefaults().applyTo(composite);
-        composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayoutFactory.swtDefaults().numColumns(2).applyTo(composite);
+		GridDataFactory.fillDefaults().applyTo(composite);
+		composite.setSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
 
-        setControl(composite);
+		Dialog.applyDialogFont(composite);
+		setControl(composite);
 	}
 
 	protected void createBrowseGroup(Composite parent, String labelText) {
-	    Composite composite = new Composite(parent, SWT.NONE);
-        GridLayoutFactory.fillDefaults().numColumns(3).applyTo(composite);
-	    GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).span(2, 1).applyTo(composite);
-	
-	    Label label = new Label(composite, SWT.NONE);
-	    label.setText(labelText);
-	
-	    pathText = new Text(composite, SWT.BORDER);
-	    GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).hint(250, SWT.DEFAULT).applyTo(pathText);
-	    pathText.addModifyListener(new ModifyListener() {
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayoutFactory.fillDefaults().numColumns(3).applyTo(composite);
+		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING)
+				.grab(true, false).applyTo(composite);
+
+		Label label = new Label(composite, SWT.NONE);
+		label.setText(labelText);
+
+		pathText = new Text(composite, SWT.BORDER);
+		GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER)
+				.grab(true, false).hint(250, SWT.DEFAULT).applyTo(pathText);
+		pathText.addModifyListener(new ModifyListener() {
 			public void modifyText(ModifyEvent e) {
 				setPageComplete(validatePage());
 			}
-	    });
-	    browseButton = new Button(composite, SWT.PUSH);
-	    browseButton.setText("Browse...");
-	    browseButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
-	    setButtonLayoutData(browseButton);
+		});
+		browseButton = new Button(composite, SWT.PUSH);
+		browseButton.setText("Browse...");
+		browseButton
+				.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
+		setButtonLayoutData(browseButton);
+		
+		new Label(parent, SWT.NONE); // spacer
 	}
 
 	protected void createViewerGroup(Composite parent, String labelText) {
 		Label label = new Label(parent, SWT.NONE);
 		label.setText(labelText);
 		GridDataFactory.defaultsFor(label).span(2, 1).applyTo(label);
-	
+
 		viewer = CheckboxTableViewer.newCheckList(parent, SWT.BORDER);
-		TableViewerColumn featureColumn = new TableViewerColumn(viewer, SWT.CENTER);
+		TableViewerColumn featureColumn = new TableViewerColumn(viewer,
+				SWT.CENTER);
 		featureColumn.getColumn().setText("Feature");
 		featureColumn.setLabelProvider(new ColumnLabelProvider() {
 			@Override
 			public Image getImage(Object element) {
 				return featureImg;
 			}
-	
+
 			@Override
 			public String getText(Object element) {
 				if (element instanceof FeatureInfo)
@@ -114,7 +122,8 @@
 				return null;
 			}
 		});
-		TableViewerColumn versionColumn = new TableViewerColumn(viewer, SWT.CENTER);
+		TableViewerColumn versionColumn = new TableViewerColumn(viewer,
+				SWT.CENTER);
 		versionColumn.getColumn().setText("Version");
 		versionColumn.setLabelProvider(new ColumnLabelProvider() {
 			@Override
@@ -125,14 +134,16 @@
 				return null;
 			}
 		});
-		
+
 		viewer.getControl().setLayoutData(
-				new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL | GridData.GRAB_VERTICAL));
+				new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL
+						| GridData.GRAB_VERTICAL));
 		viewer.setContentProvider(new ArrayContentProvider());
 		viewer.getTable().setHeaderVisible(true);
-		
+
 		Composite buttonComposite = new Composite(parent, SWT.NONE);
-		GridDataFactory.swtDefaults().align(SWT.END, SWT.BEGINNING).applyTo(buttonComposite);
+		GridDataFactory.swtDefaults().align(SWT.END, SWT.BEGINNING)
+				.applyTo(buttonComposite);
 		buttonComposite.setLayout(new GridLayout());
 		Button checkAllButton = new Button(buttonComposite, SWT.PUSH);
 		checkAllButton.setText("Select All");
@@ -153,7 +164,7 @@
 			}
 		});
 	}
-	
+
 	protected abstract boolean validatePage();
 
 	public Collection<FeatureInfo> getSelectedFeatures() {
@@ -164,7 +175,7 @@
 		}
 		return infos;
 	}
-	
+
 	protected void packColumns() {
 		TableColumn[] columns = viewer.getTable().getColumns();
 		for (TableColumn column : columns) {
@@ -177,7 +188,7 @@
 		viewer.setAllChecked(true);
 		setPageComplete(validatePage());
 	}
-	
+
 	@Override
 	public void dispose() {
 		super.dispose();
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportPage.java	Thu Aug 12 13:56:20 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportPage.java	Thu Aug 12 15:22:11 2010 -0500
@@ -28,14 +28,11 @@
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Status;
 import org.eclipse.jface.dialogs.DialogPage;
-import org.eclipse.jface.layout.GridDataFactory;
-import org.eclipse.jface.layout.GridLayoutFactory;
 import org.eclipse.jface.viewers.CheckStateChangedEvent;
 import org.eclipse.jface.viewers.ICheckStateListener;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.FileDialog;
 import org.eclipse.ui.progress.UIJob;
@@ -62,7 +59,7 @@
 		Composite composite = (Composite) getControl();
 		
         createViewerGroup(composite, "Export features:");
-		createBrowseGroup(composite, "Export to file:");
+		createBrowseGroup(composite, "Export file:");
 		
         featureInfos = new ArrayList<FeatureInfo>();
         
@@ -110,7 +107,7 @@
 		UIJob j = new UIJob("Getting Installed Features") {
 			@Override
 			public IStatus runInUIThread(IProgressMonitor monitor) {
-				viewer.setInput(FeatureUtils.getInstalledFeatures(monitor));
+				viewer.setInput(P2Utils.getInstalledFeatures(monitor));
 				updateViewer();
 				return Status.OK_STATUS;
 			} 
@@ -120,6 +117,10 @@
 	
 	protected boolean validatePage() {
 		setErrorMessage(null);
+		if (viewer.getTable().getItemCount() == 0) {
+			setErrorMessage("There are no features to export");
+			return false;
+		}
 		if (viewer.getCheckedElements().length == 0) {
 			setErrorMessage("At least one feature must be selected for export");
 			return false;
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportWizard.java	Thu Aug 12 13:56:20 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ExportWizard.java	Thu Aug 12 15:22:11 2010 -0500
@@ -48,7 +48,8 @@
 		OutputStream os;
 		try {
 			os = new FileOutputStream(file);
-			Streamer.writeToXML(os, FeatureUtils.getKnownRepositories(), featureInfos);
+			ImportExportData data = new ImportExportData(false, P2Utils.getKnownRepositories(), featureInfos);
+			Streamer.writeToXML(os, data);
 		} catch (Exception e) {
 			MessageDialog.openError(getShell(), "Error", 
 					MessageFormat.format("Could not write export file due to error: {0}", e.getLocalizedMessage()));
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/FeatureUtils.java	Thu Aug 12 13:56:20 2010 -0500
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,70 +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.OutputStream;
-import java.net.URI;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Set;
-
-import org.eclipse.core.runtime.IProgressMonitor;
-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;
-
-class FeatureUtils {
-	
-	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 writeInfosToStream(Collection<FeatureInfo> featureInfos, OutputStream os) {
-		// TODO Auto-generated method stub
-		
-	}
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportExportData.java	Thu Aug 12 15:22:11 2010 -0500
@@ -0,0 +1,46 @@
+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	Thu Aug 12 13:56:20 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportPage.java	Thu Aug 12 15:22:11 2010 -0500
@@ -18,20 +18,30 @@
 
 
 import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.text.MessageFormat;
 
 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.jface.layout.GridDataFactory;
 import org.eclipse.jface.layout.GridLayoutFactory;
 import org.eclipse.jface.viewers.CheckStateChangedEvent;
 import org.eclipse.jface.viewers.ICheckStateListener;
 import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
 import org.eclipse.swt.events.SelectionAdapter;
 import org.eclipse.swt.events.SelectionEvent;
 import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.FileDialog;
+import org.eclipse.ui.progress.UIJob;
 
+import com.nokia.carbide.discovery.ui.Activator;
 import com.nokia.cpp.internal.api.utils.ui.BrowseDialogUtils;
 
 /**
@@ -39,8 +49,6 @@
  */
 class ImportPage extends AbstractImportExportPage {
 
-	private boolean importOriginalVersion;
-
 	// the following two arrays need to correspond
 	static final String[] FILTER_EXTS  = { 
 		"*.xml", //$NON-NLS-1$
@@ -50,8 +58,11 @@
 		"XML Files",
 		"All Files"
 	};
+
+	private String currentPath;
+	private ImportExportData readData;
+	protected boolean wantsOriginalVersions;
 	
-
 	protected ImportPage() {
 		super("ImportPage"); //$NON-NLS-1$
 		setTitle("Import Feature Configuration and Install");
@@ -62,8 +73,23 @@
 		super.createControl(parent);
 		Composite composite = (Composite) getControl();
 
-        createBrowseGroup(composite, "Feature configuration file:");
-	    browseButton.addSelectionListener(new SelectionAdapter() {
+        createBrowseGroup(composite, "Import file:");
+        createViewerGroup(composite, "Import Features:");
+
+        setPageComplete(validatePage());
+	}
+	
+	@Override
+	protected void createBrowseGroup(Composite parent, String labelText) {
+		super.createBrowseGroup(parent, labelText);
+		pathText.addModifyListener(new ModifyListener() {
+			@Override
+			public void modifyText(ModifyEvent e) {
+				handlePathChanged();
+			}
+		});
+		
+		browseButton.addSelectionListener(new SelectionAdapter() {
 			@Override
 			public void widgetSelected(SelectionEvent e) {
 				FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN);
@@ -74,19 +100,45 @@
 				String pathstr = fileDialog.open();
 				if (pathstr != null) {
 					pathText.setText(pathstr);
+//					handlePathChanged();
 				}
 			}
-	    });
-        createViewerGroup(composite, "Import Features:");
+		});
+	}
+	
+	@Override
+	protected void createViewerGroup(Composite parent, String labelText) {
+		super.createViewerGroup(parent, labelText);
+
 		viewer.addCheckStateListener(new ICheckStateListener() {
 			public void checkStateChanged(CheckStateChangedEvent event) {
 				setPageComplete(validatePage());
 			}
 		});
-
-        setPageComplete(validatePage());
+		updateViewer();
 	}
 
+	private void startGetInputJob(final String path) {
+		UIJob j = new UIJob("Reading Feature Configuration File") {
+			@Override
+			public IStatus runInUIThread(IProgressMonitor monitor) {
+				try {
+					FileInputStream is = new FileInputStream(path);
+					readData = Streamer.readFromXML(is);
+					viewer.setInput(readData.getFeatureInfos());
+					updateViewer();
+					monitor.done();
+				} catch (IOException e) {
+					// may have bad/incomplete path, so don't log this
+				} catch (Exception e) {
+					Activator.logError(MessageFormat.format("Could not read data from file: {0}", path), e);
+				}
+				return Status.OK_STATUS;
+			} 
+		};
+		j.schedule();
+	}
+	
 	protected void createVersionRadioGroup(Composite parent) {
 	    Composite composite = new Composite(parent, SWT.NONE);
         GridLayoutFactory.fillDefaults().applyTo(composite);
@@ -97,23 +149,23 @@
 	    originalVersionCheck.addSelectionListener(new SelectionAdapter() {
 			@Override
 	    	public void widgetSelected(SelectionEvent e) {
-	    		importOriginalVersion = originalVersionCheck.getSelection();
+	    		wantsOriginalVersions = originalVersionCheck.getSelection();
 	    	}
 		});
 	}
-	
+
 	protected boolean validatePage() {
 		setErrorMessage(null);
 		IPath path = new Path(pathText.getText());
-		File file = path.toFile();
-		if (file.exists()) {
-			FeatureInfo[] featureInfos = getFeaturesFromFile(file);
-			if (featureInfos.length == 0) {
-				setErrorMessage("The file has no valid features");
+		if (isFilePath(path.toOSString())) {
+			if (readData == null || readData.getFeatureInfos().isEmpty()) {
+				setErrorMessage("No valid features found in configurations file");
 				return false;
 			}
-			viewer.setInput(featureInfos);
-			updateViewer();
+			if (readData == null || readData.getURIs().isEmpty()) {
+				setErrorMessage("No valid repositories found in configurations file");
+				return false;
+			}
 		}
 		else {
 			setErrorMessage("A valid exported feature configuration file must be selected");
@@ -128,9 +180,19 @@
 		return true;
 	}
 
-	private FeatureInfo[] getFeaturesFromFile(File file) {
-		// TODO
-		return new FeatureInfo[0];
+	private boolean isFilePath(String path) {
+		File file = new File(path);
+		return file.exists() && !file.isDirectory();
 	}
 
+	private void handlePathChanged() {
+		String path = pathText.getText();
+		if (!path.equals(currentPath) && isFilePath(path)) {
+			startGetInputJob(currentPath = path);
+		}
+	}
+
+	public ImportExportData getData() {
+		return readData;
+	}
 }
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportWizard.java	Thu Aug 12 13:56:20 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/ImportWizard.java	Thu Aug 12 15:22:11 2010 -0500
@@ -16,6 +16,12 @@
 */
 package com.nokia.carbide.internal.discovery.ui.wizard;
 
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.operation.IRunnableWithProgress;
 import org.eclipse.jface.viewers.IStructuredSelection;
 import org.eclipse.jface.wizard.Wizard;
 import org.eclipse.ui.IImportWizard;
@@ -35,12 +41,30 @@
 
 	@Override
 	public boolean performFinish() {
-		// TODO read from file and install
+		final ImportExportData data = importPage.getData();
+		IRunnableWithProgress runnable = new IRunnableWithProgress() {
+			@Override
+			public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+				try {
+					P2Utils.doInstall(data.getURIs(), data.getFeatureInfos(), data.getWantsVersions(), monitor);
+				} catch (Exception e) {
+					throw new InvocationTargetException(e);
+				}
+			}
+		};
+		
+		try {
+			getContainer().run(true, true, runnable);
+		} catch (Exception e) {
+			MessageDialog.openError(getShell(), "Error", 
+					MessageFormat.format("Could not install due to error: {0}", e.getLocalizedMessage()));
+		}
 		return true;
 	}
 
 	public void init(IWorkbench workbench, IStructuredSelection selection) {
 		setDefaultPageImageDescriptor(Activator.getImageDescriptor("icons\\install_wiz.gif")); //$NON-NLS-1$
+		setNeedsProgressMonitor(true);
 		setWindowTitle("Import Installed Feature Configuration");
 		importPage = new ImportPage();
 		addPage(importPage);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/P2Utils.java	Thu Aug 12 15:22:11 2010 -0500
@@ -0,0 +1,174 @@
+/*
+* 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.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+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.OperationCanceledException;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.equinox.p2.core.IProvisioningAgent;
+import org.eclipse.equinox.p2.core.ProvisionException;
+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.metadata.Version;
+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.IQueryResult;
+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.swt.widgets.Display;
+
+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 doInstall(Collection<URI> uris, Collection<FeatureInfo> featureInfos, 
+			boolean wantVersions, IProgressMonitor monitor) throws OperationCanceledException, CoreException {
+		SubMonitor subMonitor = SubMonitor.convert(monitor, "Configuring install operation", 100);
+		Collection<IMetadataRepository> repositories = 
+			getRepositories(uris, wantVersions, subMonitor.newChild(30));
+		final Collection<IInstallableUnit> ius = 
+			findInstallableUnits(repositories, featureInfos, wantVersions, subMonitor.newChild(40));
+		final InstallOperation operation = resolve(ius, (URI[]) uris.toArray(new URI[uris.size()]), subMonitor.newChild(30));
+		Display.getDefault().asyncExec(new Runnable() {
+			@Override
+			public void run() {
+				ProvisioningUI.getDefaultUI().openInstallWizard(ius, operation, null);
+			}
+		});
+	}
+
+	private static Collection<IMetadataRepository> getRepositories(Collection<URI> uris, 
+			boolean wantVersions, SubMonitor monitor) throws ProvisionException, OperationCanceledException {
+		monitor.setWorkRemaining(uris.size());
+		List<IMetadataRepository> repositories = new ArrayList<IMetadataRepository>();
+		ProvisioningUI provisioningUI = ProvisioningUI.getDefaultUI();
+		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)));
+		}
+
+		return repositories;
+	}
+
+	private static Collection<IInstallableUnit> findInstallableUnits(Collection<IMetadataRepository> repositories, 
+			Collection<FeatureInfo> featureInfos, boolean wantVersions, SubMonitor monitor) throws ProvisionException {
+		monitor.setWorkRemaining(repositories.size());
+		List<IInstallableUnit> ius = new ArrayList<IInstallableUnit>();
+		Set<FeatureInfo> remainingInfos = new HashSet<FeatureInfo>(featureInfos);
+		for (IMetadataRepository repository : repositories) {
+			checkIfCanceled(monitor);
+			IQueryResult<IInstallableUnit> result = repository.query(QueryUtil.createIUGroupQuery(), monitor.newChild(1));
+			for (Iterator<IInstallableUnit> iter = result.iterator(); iter.hasNext();) {
+				IInstallableUnit iu = iter.next();
+				String id = iu.getId();
+				Version version = iu.getVersion();
+				FeatureInfo featureInfo = findInfo(remainingInfos, id, wantVersions ? version : null);
+				if (featureInfo != null) {
+					ius.add(iu);
+					remainingInfos.remove(featureInfo);
+				}
+			}
+		}
+		if (!remainingInfos.isEmpty()) {
+			StringBuilder sb = new StringBuilder();
+			sb.append("Install failed. Could not find some features: \n");
+			for (FeatureInfo featureInfo : remainingInfos) {
+				sb.append("id=");
+				sb.append(featureInfo.getId());
+				if (wantVersions) {
+					sb.append("version=");
+					sb.append(featureInfo.getVersion().toString());
+				}
+				sb.append("\n");
+			}
+			throw new ProvisionException(sb.toString());
+		}
+		return ius;
+	}
+	
+	private static FeatureInfo findInfo(Collection<FeatureInfo> featureInfos, String id, Version version) {
+		for (FeatureInfo featureInfo : featureInfos) {
+			if (featureInfo.getId().equals(id) && 
+					(version == null || version.toString().equals(featureInfo.getVersion().toString())))
+				return featureInfo;
+		}
+		return null;
+	}
+	
+	private static InstallOperation resolve(Collection<IInstallableUnit> ius, URI[] repositories, 
+			SubMonitor monitor) throws CoreException {
+		checkIfCanceled(monitor);
+		ProvisioningUI provisioningUI = ProvisioningUI.getDefaultUI();
+		InstallOperation installOperation = provisioningUI.getInstallOperation(ius, repositories);
+		IStatus operationStatus = installOperation.resolveModal(monitor);
+		if (operationStatus.getSeverity() > IStatus.WARNING) {
+			throw new CoreException(operationStatus);
+		}
+		return installOperation;
+	}
+
+	private static 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/Streamer.java	Thu Aug 12 13:56:20 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/wizard/Streamer.java	Thu Aug 12 15:22:11 2010 -0500
@@ -20,10 +20,19 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.text.MessageFormat;
-import java.util.Collection;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
 
-import com.nokia.cpp.internal.api.utils.core.Pair;
+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;
 
 /**
  * Serializes feature infos and repository URIs into output stream as XML
@@ -41,39 +50,95 @@
 
 	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 FEATURES_CONFIG_START = "<featuresConfiguration version=\"" + CURRENT_VERSION + "\">\n"; //$NON-NLS-1$ //$NON-NLS-2$
-	private static final String FEATURES_CONFIG_END = "</featuresConfiguration>\n"; //$NON-NLS-1$
-	private static final String AUTO_IMPORT_ORIGINAL_VERSION_FMT = "\t<autoImportOriginalVersions value=\"{0}\"/>\n"; //$NON-NLS-1$
-	private static final String REPOSITORY_FMT = "\t<repository uri=\"{0}\"/>\n"; //$NON-NLS-1$
-	private static final String FEATURE_FMT = "\t<feature id=\"{0}\" version=\"{1}\"/>\n"; //$NON-NLS-1$
+	
+	private static final String ROOT_START = "<" + ROOT_ELEMENT + " " + VERSION_ATTR + "=\"" + CURRENT_VERSION + "\">\n"; //$NON-NLS-1$ //$NON-NLS-2$
+	private static final String ROOT_END = "</" + ROOT_ELEMENT + ">\n"; //$NON-NLS-1$
+	
+	private static final String ORIGINAL_VERSION_FMT = "\t<" + WANTS_VERSIONS_ELEMENT + " " + VALUE_ATTR + "=\"{0}\"/>\n"; //$NON-NLS-1$
+	private static final String REPOSITORY_FMT = "\t<" + REPOSITORY_ELEMENT + " " + URI_ATTR + "=\"{0}\"/>\n"; //$NON-NLS-1$
+	private static final String FEATURE_FMT = "\t<" + FEATURE_ELEMENT + " " + ID_ATTR + "=\"{0}\" " + VERSION_ATTR + "=\"{1}\"/>\n"; //$NON-NLS-1$
 
-	public static void writeToXML(OutputStream os, Collection<URI> repositories, Collection<FeatureInfo> featureInfos) throws IOException {
+	public static void writeToXML(OutputStream os, ImportExportData data) throws IOException {
 		os.write(XML_HEADER.getBytes());
-		os.write(FEATURES_CONFIG_START.getBytes());
+		os.write(ROOT_START.getBytes());
 		
 		// write auto-import original versions
-		String originalVersionElement = MessageFormat.format(AUTO_IMPORT_ORIGINAL_VERSION_FMT, false);
+		String originalVersionElement = MessageFormat.format(ORIGINAL_VERSION_FMT, data.getWantsVersions());
 		os.write(originalVersionElement.getBytes());
 
 		// write the repositories
-		for (URI uri : repositories) {
+		for (URI uri : data.getURIs()) {
 			String repositoryElement = MessageFormat.format(REPOSITORY_FMT, uri);
 			os.write(repositoryElement.getBytes());
 		}
 		
 		// write the featureInfos
-		for (FeatureInfo info : featureInfos) {
+		for (FeatureInfo info : data.getFeatureInfos()) {
 			String featureElement = MessageFormat.format(FEATURE_FMT, info.getId(), info.getVersion());
 			os.write(featureElement.getBytes());
 		}
 		
-		os.write(FEATURES_CONFIG_END.getBytes());
+		os.write(ROOT_END.getBytes());
 		os.close();
 	}
 	
-	public static Pair<Collection<URI>, Collection<FeatureInfo>> readFromXML(InputStream is) {
-		
-		return null; // TODO
+	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("Can only read version {0} of <{1}>", 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("Could not parse URI: {0}", 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("Could not parse version: {0}", 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;
+	}
+	
 }