feature config exporter + non-functional importer
authordadubrow
Wed, 11 Aug 2010 15:25:32 -0500
changeset 1810 2ccd3660a736
parent 1809 7c3b884eb33b
child 1814 837f2f0d0b21
feature config exporter + non-functional importer
core/com.nokia.carbide.discovery.ui/icons/icon-discovery_exp.png
core/com.nokia.carbide.discovery.ui/icons/install_wiz.gif
core/com.nokia.carbide.discovery.ui/icons/iu_obj.gif
core/com.nokia.carbide.discovery.ui/plugin.properties
core/com.nokia.carbide.discovery.ui/plugin.xml
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/discovery/ui/messages.properties
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/editor/RoundedCornerComposite.java
core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/extension/AbstractDiscoveryPortalPageLayer.java
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/FeatureInfo.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/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/Streamer.java
Binary file core/com.nokia.carbide.discovery.ui/icons/icon-discovery_exp.png has changed
Binary file core/com.nokia.carbide.discovery.ui/icons/install_wiz.gif has changed
Binary file core/com.nokia.carbide.discovery.ui/icons/iu_obj.gif has changed
--- a/core/com.nokia.carbide.discovery.ui/plugin.properties	Wed Aug 11 14:53:40 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/plugin.properties	Wed Aug 11 15:25:32 2010 -0500
@@ -1,9 +1,11 @@
-view.name=Install Extensions
-menu.title=Carbide Portal
-portal.desc=Install extensions, get support, install SDKs, find latest news
+view.name = Install Extensions
+menu.title = Carbide.c++ Portal
+portal.desc = Install extensions, get support, install SDKs, find latest news
 customize.title = Customize
 home.title = Home
 support.title = Support
 install.layer.title = Install Extensions
 wrenchscience.title = Wrench Science
-creatingcarbide.title = Creating Carbide
\ No newline at end of file
+creatingcarbide.title = Creating Carbide
+Export.desc = Export a set of installed features to a file that can be imported from a different installation
+Import.desc = Import a set of installed features from an exported file and perform installation of the features
\ No newline at end of file
--- a/core/com.nokia.carbide.discovery.ui/plugin.xml	Wed Aug 11 14:53:40 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/plugin.xml	Wed Aug 11 15:25:32 2010 -0500
@@ -138,5 +138,31 @@
             version="1.0.0">
       </action>
    </extension>
+   <extension
+         point="org.eclipse.ui.exportWizards">
+      <wizard
+            category="org.eclipse.ui.Basic"
+            class="com.nokia.carbide.internal.discovery.ui.wizard.ExportWizard"
+            icon="icons/icon-discovery_exp.png"
+            id="com.nokia.carbide.discovery.ui.features.exportWizard"
+            name="Installed Feature Configuration">
+         <description>
+            %Export.desc
+         </description>
+      </wizard>
+   </extension>
+   <extension
+         point="org.eclipse.ui.importWizards">
+      <wizard
+            category="org.eclipse.ui.Basic"
+            class="com.nokia.carbide.internal.discovery.ui.wizard.ImportWizard"
+            icon="icons/icon-discovery.png"
+            id="com.nokia.carbide.discovery.ui.features.importWizard"
+            name="Installed Feature Configuration">
+         <description>
+            %Import.desc
+         </description>
+      </wizard>
+   </extension>
 
 </plugin>
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/discovery/ui/messages.properties	Wed Aug 11 14:53:40 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/discovery/ui/messages.properties	Wed Aug 11 15:25:32 2010 -0500
@@ -11,21 +11,21 @@
 AbstractBrowserPortalPageLayer_ShowInBrowserLabel=Show in browser
 AbstractBrowserPortalPageLayer_URLLabel=URL:
 AbstractDiscoveryPortalPageLayer_AdvancedInstallActionLabel=Advanced install...
-AbstractDiscoveryPortalPageLayer_CheckAllActionLabel=Check all
-AbstractDiscoveryPortalPageLayer_CheckedItemsStatusMessage={0} item(s) checked
+AbstractDiscoveryPortalPageLayer_CheckAllActionLabel=Select all
+AbstractDiscoveryPortalPageLayer_CheckedItemsStatusMessage={0} item(s) selected
 AbstractDiscoveryPortalPageLayer_GatheringExtensionsDesc=Gathering Extensions
 AbstractDiscoveryPortalPageLayer_GatheringInstallInfoDesc=Gathering Install Information
 AbstractDiscoveryPortalPageLayer_InstallActionLabel=Install...
-AbstractDiscoveryPortalPageLayer_InstallActionTooltip=Install checked items
+AbstractDiscoveryPortalPageLayer_InstallActionTooltip=Install selected items
 AbstractDiscoveryPortalPageLayer_RefreshActionLabel=Refresh
 AbstractDiscoveryPortalPageLayer_Title=Install Extensions
-AbstractDiscoveryPortalPageLayer_UncheckAllActionLabel=Check none
+AbstractDiscoveryPortalPageLayer_UncheckAllActionLabel=Deselect all
 AbstractRSSPortalPageLayer_ReturnToFeedLabel=Return to RSS
 AbstractRSSPortalPageLayer_RSSReadError=Could not read RSS from: {0}
 Activator_GetProxyInfoJobTitle=Getting proxy info
 Activator_MissingConfigURLError=Could not find URL in configuration/server.properties file for key={0}
 PortalEditor_BadCommandBarFactoryError=Command bar factory class could not be created for id: {0
-PortalEditor_Name=Carbide Portal
+PortalEditor_Name=Carbide.c++ Portal
 PortalEditor_NoLayersError=Could not load portal page because no layers were found for id: {0}
 PortalEditor_PageLoadError=Could not load portal page
 PortalEditor_PageOpenError=Could not open portal
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/editor/RoundedCornerComposite.java	Wed Aug 11 14:53:40 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/editor/RoundedCornerComposite.java	Wed Aug 11 15:25:32 2010 -0500
@@ -40,7 +40,7 @@
 		}
 		if (outline != null) {
 			gc.setForeground(outline);
-			gc.drawRoundRectangle(2, 2, width - 4, height - 4, 6, 6);
+			gc.drawRoundRectangle(0, 0, width - 1, height - 1, 6, 6);
 		}
 	}
 }
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/extension/AbstractDiscoveryPortalPageLayer.java	Wed Aug 11 14:53:40 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/extension/AbstractDiscoveryPortalPageLayer.java	Wed Aug 11 15:25:32 2010 -0500
@@ -34,7 +34,6 @@
 import org.eclipse.equinox.internal.p2.ui.discovery.wizards.CatalogConfiguration;
 import org.eclipse.equinox.internal.p2.ui.discovery.wizards.CatalogViewer;
 import org.eclipse.equinox.p2.core.IProvisioningAgent;
-import org.eclipse.equinox.p2.operations.ProvisioningSession;
 import org.eclipse.equinox.p2.repository.artifact.IArtifactRepositoryManager;
 import org.eclipse.equinox.p2.repository.metadata.IMetadataRepositoryManager;
 import org.eclipse.equinox.p2.ui.ProvisioningUI;
@@ -54,7 +53,9 @@
 import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.IActionBars;
 import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.PlatformUI;
 import org.eclipse.ui.actions.BaseSelectionListenerAction;
+import org.eclipse.ui.handlers.IHandlerService;
 
 import com.nokia.carbide.discovery.ui.Activator;
 import com.nokia.carbide.discovery.ui.Messages;
@@ -113,7 +114,7 @@
 	protected static final String REFRESH_ACTION_ID = 
 		AbstractDiscoveryPortalPageLayer.class.getName() + ".refresh"; //$NON-NLS-1$
 
-	private IEditorPart part;
+	protected IEditorPart part;
 	private CatalogViewer viewer;
 	private List<ISelectionChangedListener> selectionListeners;
 	private IActionUIUpdater updater;
@@ -294,16 +295,20 @@
 	}
 
 	protected void showInstallWizard() {
-		ProvisioningUI defaultUI = ProvisioningUI.getDefaultUI();
-		ProvisioningSession session = defaultUI.getSession();
-		IProvisioningAgent agent = session.getProvisioningAgent();
+		IProvisioningAgent agent = ProvisioningUI.getDefaultUI().getSession().getProvisioningAgent();
 		IMetadataRepositoryManager metadataManager = (IMetadataRepositoryManager) agent.getService(IMetadataRepositoryManager.SERVICE_NAME);
 		IArtifactRepositoryManager artifactManager = (IArtifactRepositoryManager) agent.getService(IArtifactRepositoryManager.SERVICE_NAME);
 		for (URI uri : getSiteURIs(viewer.getCatalog().getItems())) {
 			metadataManager.addRepository(uri);
 			artifactManager.addRepository(uri);
 		}
-		defaultUI.openInstallWizard(null, null, null);
+		IHandlerService handlerService = 
+			(IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
+        try {
+			handlerService.executeCommand("org.eclipse.equinox.p2.ui.sdk.install", null);
+		} catch (Exception e) {
+			Activator.logError("Could not open install wizard", e);
+		}
 	}
 
 	protected static Collection<URI> getSiteURIs(List<CatalogItem> catalogItems) {
--- a/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/view/InstallExtensionsPortalExtension.java	Wed Aug 11 14:53:40 2010 -0500
+++ b/core/com.nokia.carbide.discovery.ui/src/com/nokia/carbide/internal/discovery/ui/view/InstallExtensionsPortalExtension.java	Wed Aug 11 15:25:32 2010 -0500
@@ -17,15 +17,58 @@
 package com.nokia.carbide.internal.discovery.ui.view;
 
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.wizard.WizardDialog;
 import org.eclipse.swt.widgets.Composite;
 import org.eclipse.swt.widgets.Control;
 import org.eclipse.ui.IEditorPart;
+import org.eclipse.ui.IWorkbenchWizard;
 import org.eclipse.ui.PlatformUI;
 
 import com.nokia.carbide.internal.discovery.ui.extension.AbstractDiscoveryPortalPageLayer;
+import com.nokia.carbide.internal.discovery.ui.extension.IActionBar;
+import com.nokia.carbide.internal.discovery.ui.extension.IActionUIUpdater;
+import com.nokia.carbide.internal.discovery.ui.wizard.ExportWizard;
+import com.nokia.carbide.internal.discovery.ui.wizard.ImportWizard;
 
 public class InstallExtensionsPortalExtension extends AbstractDiscoveryPortalPageLayer {
 
+	private final class MigrateBar implements IActionBar {
+		@Override
+		public String getTitle() {
+			return "Migrate";
+		}
+
+		@Override
+		public String[] getHighlightedActionIds() {
+			return null;
+		}
+
+		@Override
+		public IAction[] getActions() {
+			List<IAction> actions = new ArrayList<IAction>();
+			actions.add(new Action("Export...") {
+				@Override
+				public void run() {
+					showWizard(new ExportWizard());
+				}
+			});
+			actions.add(new Action("Import...") {
+				@Override
+				public void run() {
+					showWizard(new ImportWizard());
+				}
+			});
+			return (IAction[]) actions.toArray(new IAction[actions.size()]);
+		}
+	}
+
 	@Override
 	public Control createControl(Composite parent, IEditorPart part) {
 		Control control = super.createControl(parent, part);
@@ -36,4 +79,20 @@
 
 		return control;
 	}
+	
+	@Override
+	public IActionBar[] createCommandBars(IEditorPart part, IActionUIUpdater updater) {
+		List<IActionBar> commandBars = new ArrayList<IActionBar>(
+				Arrays.asList(super.createCommandBars(part, updater)));
+		commandBars.add(new MigrateBar());
+		
+		return (IActionBar[]) commandBars.toArray(new IActionBar[commandBars.size()]);
+	}
+
+	private void showWizard(IWorkbenchWizard wizard) {
+		wizard.init(PlatformUI.getWorkbench(), StructuredSelection.EMPTY);
+        WizardDialog dialog = new WizardDialog(part.getEditorSite().getShell(), wizard);
+        dialog.create();
+        dialog.open();
+	}
 }
--- /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/AbstractImportExportPage.java	Wed Aug 11 15:25:32 2010 -0500
@@ -0,0 +1,186 @@
+/*
+* 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.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.CheckboxTableViewer;
+import org.eclipse.jface.viewers.ColumnLabelProvider;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.wizard.WizardPage;
+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.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+
+import com.nokia.carbide.discovery.ui.Activator;
+
+/**
+ * Abstract superclass of import and export page
+ */
+abstract class AbstractImportExportPage extends WizardPage {
+
+	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 Image featureImg;
+
+	public AbstractImportExportPage(String pageName) {
+		super(pageName);
+	}
+	
+	public void createControl(Composite parent) {
+        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));
+
+        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() {
+			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);
+	}
+
+	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);
+		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)
+					return ((FeatureInfo) element).getId();
+				return null;
+			}
+		});
+		TableViewerColumn versionColumn = new TableViewerColumn(viewer, SWT.CENTER);
+		versionColumn.getColumn().setText("Version");
+		versionColumn.setLabelProvider(new ColumnLabelProvider() {
+			@Override
+			public String getText(Object element) {
+				if (element instanceof FeatureInfo) {
+					return ((FeatureInfo) element).getVersion().toString();
+				}
+				return null;
+			}
+		});
+		
+		viewer.getControl().setLayoutData(
+				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);
+		buttonComposite.setLayout(new GridLayout());
+		Button checkAllButton = new Button(buttonComposite, SWT.PUSH);
+		checkAllButton.setText("Select All");
+		setButtonLayoutData(checkAllButton);
+		checkAllButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				viewer.setAllChecked(true);
+			}
+		});
+		Button checkNoneButton = new Button(buttonComposite, SWT.PUSH);
+		checkNoneButton.setText("Deselect All");
+		setButtonLayoutData(checkNoneButton);
+		checkNoneButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				viewer.setAllChecked(false);
+			}
+		});
+	}
+	
+	protected abstract boolean validatePage();
+
+	public Collection<FeatureInfo> getSelectedFeatures() {
+		Object[] checkedElements = viewer.getCheckedElements();
+		List<FeatureInfo> infos = new ArrayList<FeatureInfo>();
+		for (Object o : checkedElements) {
+			infos.add((FeatureInfo) o);
+		}
+		return infos;
+	}
+	
+	protected void packColumns() {
+		TableColumn[] columns = viewer.getTable().getColumns();
+		for (TableColumn column : columns) {
+			column.pack();
+		}
+	}
+
+	protected void updateViewer() {
+		packColumns();
+		viewer.setAllChecked(true);
+		setPageComplete(validatePage());
+	}
+	
+	@Override
+	public void dispose() {
+		super.dispose();
+		featureImg.dispose();
+	}
+}
\ 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/wizard/ExportPage.java	Wed Aug 11 15:25:32 2010 -0500
@@ -0,0 +1,153 @@
+/*
+* 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.util.ArrayList;
+import java.util.Collection;
+
+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.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;
+
+import com.nokia.cpp.internal.api.utils.ui.BrowseDialogUtils;
+
+/**
+ * Page in export wizard
+ */
+class ExportPage extends AbstractImportExportPage {
+
+	private File file;
+	private Collection<FeatureInfo> featureInfos;
+	private static String saveAsParent;
+
+	protected ExportPage() {
+		super("ExportPage"); //$NON-NLS-1$
+		setTitle("Export Installed Feature Configuration");
+		setDescription("Create an export file with the selected feature configuration");
+	}
+
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		Composite composite = (Composite) getControl();
+		
+        createViewerGroup(composite, "Export features:");
+		createBrowseGroup(composite, "Export to file:");
+		
+        featureInfos = new ArrayList<FeatureInfo>();
+        
+        setPageComplete(validatePage());
+	}
+	
+	@Override
+	protected void createViewerGroup(Composite parent, String labelText) {
+		super.createViewerGroup(parent, labelText);
+
+		viewer.addCheckStateListener(new ICheckStateListener() {
+			public void checkStateChanged(CheckStateChangedEvent event) {
+				setPageComplete(validatePage());
+			}
+		});
+		startGetInputJob();
+		updateViewer();
+	}
+	
+	@Override
+	protected void createBrowseGroup(Composite parent, String labelText) {
+		super.createBrowseGroup(parent, labelText);
+		
+		if (saveAsParent == null)
+			saveAsParent = System.getProperty("user.home"); //$NON-NLS-1$
+		pathText.setText(new Path(saveAsParent).append("exportedFeatures.xml").toOSString()); //$NON-NLS-1$
+        browseButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				FileDialog dialog =  new FileDialog(getShell(), SWT.SAVE);
+				dialog.setText("Save As");
+				BrowseDialogUtils.initializeFrom(dialog, pathText.getText());
+				dialog.setOverwrite(true); // prompt for overwrite
+				String path = dialog.open();
+				if (path != null) {
+					IPath saveAsPath = new Path(path);
+					saveAsParent = saveAsPath.removeLastSegments(1).toString();
+					pathText.setText(saveAsPath.toOSString());
+				}
+			}
+        });
+	}
+
+	private void startGetInputJob() {
+		UIJob j = new UIJob("Getting Installed Features") {
+			@Override
+			public IStatus runInUIThread(IProgressMonitor monitor) {
+				viewer.setInput(FeatureUtils.getInstalledFeatures(monitor));
+				updateViewer();
+				return Status.OK_STATUS;
+			} 
+		};
+		j.schedule();
+	}
+	
+	protected boolean validatePage() {
+		setErrorMessage(null);
+		if (viewer.getCheckedElements().length == 0) {
+			setErrorMessage("At least one feature must be selected for export");
+			return false;
+		}
+		
+		IPath path = new Path(pathText.getText());
+		file = path.toFile();
+		if (!file.isAbsolute()) {
+			setErrorMessage("A file must be selected in order to export features");
+			return false;
+		}
+		if (file.exists()) {
+			setMessage("File exists at selected location and will be overwritten", DialogPage.WARNING);
+		}
+		
+		return true;
+	}
+
+	public File getFile() {
+		return file;
+	}
+
+	public Collection<FeatureInfo> getFeatureInfos() {
+		featureInfos.clear();
+		for (Object o : viewer.getCheckedElements()) {
+			featureInfos.add((FeatureInfo) o);
+		}
+		return featureInfos;
+	}
+
+}
--- /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/ExportWizard.java	Wed Aug 11 15:25:32 2010 -0500
@@ -0,0 +1,66 @@
+/*
+* 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.io.OutputStream;
+import java.text.MessageFormat;
+import java.util.Collection;
+
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IExportWizard;
+import org.eclipse.ui.IWorkbench;
+
+import com.nokia.carbide.discovery.ui.Activator;
+
+/**
+ * Wizard for exporting installed features to a file
+ */
+public class ExportWizard extends Wizard implements IExportWizard {
+
+	private ExportPage exportPage;
+
+	public ExportWizard() {
+	}
+
+	public boolean performFinish() {
+		Collection<FeatureInfo> featureInfos = exportPage.getFeatureInfos();
+		File file = exportPage.getFile();
+		OutputStream os;
+		try {
+			os = new FileOutputStream(file);
+			Streamer.writeToXML(os, FeatureUtils.getKnownRepositories(), featureInfos);
+		} catch (Exception e) {
+			MessageDialog.openError(getShell(), "Error", 
+					MessageFormat.format("Could not write export file 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$
+		setWindowTitle("Export");
+		exportPage = new ExportPage();
+		addPage(exportPage);
+	}
+
+}
--- /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/FeatureInfo.java	Wed Aug 11 15:25:32 2010 -0500
@@ -0,0 +1,73 @@
+/*
+* 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;
+	}
+}
\ 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/wizard/FeatureUtils.java	Wed Aug 11 15:25:32 2010 -0500
@@ -0,0 +1,70 @@
+/*
+* 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/ImportPage.java	Wed Aug 11 15:25:32 2010 -0500
@@ -0,0 +1,136 @@
+/*
+* 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 org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+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 com.nokia.cpp.internal.api.utils.ui.BrowseDialogUtils;
+
+/**
+ * Page in import wizard
+ */
+class ImportPage extends AbstractImportExportPage {
+
+	private boolean importOriginalVersion;
+
+	// the following two arrays need to correspond
+	static final String[] FILTER_EXTS  = { 
+		"*.xml", //$NON-NLS-1$
+		"*.*" //$NON-NLS-1$
+	};
+	static final String[] FILTER_EXT_NAMES  = { 
+		"XML Files",
+		"All Files"
+	};
+	
+
+	protected ImportPage() {
+		super("ImportPage"); //$NON-NLS-1$
+		setTitle("Import Feature Configuration and Install");
+		setDescription("Import a feature configurations from a file and install the features");
+	}
+
+	public void createControl(Composite parent) {
+		super.createControl(parent);
+		Composite composite = (Composite) getControl();
+
+        createBrowseGroup(composite, "Feature configuration file:");
+	    browseButton.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				FileDialog fileDialog = new FileDialog(getShell(), SWT.OPEN);
+				fileDialog.setText("Select an Exported Feature Configuration File");
+				fileDialog.setFilterExtensions(FILTER_EXTS);
+				fileDialog.setFilterNames(FILTER_EXT_NAMES);
+				BrowseDialogUtils.initializeFrom(fileDialog, pathText);
+				String pathstr = fileDialog.open();
+				if (pathstr != null) {
+					pathText.setText(pathstr);
+				}
+			}
+	    });
+        createViewerGroup(composite, "Import Features:");
+		viewer.addCheckStateListener(new ICheckStateListener() {
+			public void checkStateChanged(CheckStateChangedEvent event) {
+				setPageComplete(validatePage());
+			}
+		});
+
+        setPageComplete(validatePage());
+	}
+
+	protected void createVersionRadioGroup(Composite parent) {
+	    Composite composite = new Composite(parent, SWT.NONE);
+        GridLayoutFactory.fillDefaults().applyTo(composite);
+	    GridDataFactory.fillDefaults().align(SWT.FILL, SWT.BEGINNING).grab(true, false).applyTo(composite);
+	    
+	    final Button originalVersionCheck = new Button(composite, SWT.CHECK);  
+	    originalVersionCheck.setText("Attempt import original feature versions");
+	    originalVersionCheck.addSelectionListener(new SelectionAdapter() {
+			@Override
+	    	public void widgetSelected(SelectionEvent e) {
+	    		importOriginalVersion = 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");
+				return false;
+			}
+			viewer.setInput(featureInfos);
+			updateViewer();
+		}
+		else {
+			setErrorMessage("A valid exported feature configuration file must be selected");
+			return false;
+		}
+		
+		if (viewer.getCheckedElements().length == 0) {
+			setErrorMessage("At least one feature must be selected for import");
+			return false;
+		}
+		
+		return true;
+	}
+
+	private FeatureInfo[] getFeaturesFromFile(File file) {
+		// TODO
+		return new FeatureInfo[0];
+	}
+
+}
--- /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/ImportWizard.java	Wed Aug 11 15:25:32 2010 -0500
@@ -0,0 +1,49 @@
+/*
+* 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.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.ui.IImportWizard;
+import org.eclipse.ui.IWorkbench;
+
+import com.nokia.carbide.discovery.ui.Activator;
+
+/**
+ * Wizard for importing installed features from a file and install them
+ */
+public class ImportWizard extends Wizard implements IImportWizard {
+
+	private ImportPage importPage;
+
+	public ImportWizard() {
+	}
+
+	@Override
+	public boolean performFinish() {
+		// TODO read from file and install
+		return true;
+	}
+
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+		setDefaultPageImageDescriptor(Activator.getImageDescriptor("icons\\install_wiz.gif")); //$NON-NLS-1$
+		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/Streamer.java	Wed Aug 11 15:25:32 2010 -0500
@@ -0,0 +1,79 @@
+/*
+* 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.text.MessageFormat;
+import java.util.Collection;
+
+import com.nokia.cpp.internal.api.utils.core.Pair;
+
+/**
+ * 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 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$
+
+	public static void writeToXML(OutputStream os, Collection<URI> repositories, Collection<FeatureInfo> featureInfos) throws IOException {
+		os.write(XML_HEADER.getBytes());
+		os.write(FEATURES_CONFIG_START.getBytes());
+		
+		// write auto-import original versions
+		String originalVersionElement = MessageFormat.format(AUTO_IMPORT_ORIGINAL_VERSION_FMT, false);
+		os.write(originalVersionElement.getBytes());
+
+		// write the repositories
+		for (URI uri : repositories) {
+			String repositoryElement = MessageFormat.format(REPOSITORY_FMT, uri);
+			os.write(repositoryElement.getBytes());
+		}
+		
+		// write the featureInfos
+		for (FeatureInfo info : featureInfos) {
+			String featureElement = MessageFormat.format(FEATURE_FMT, info.getId(), info.getVersion());
+			os.write(featureElement.getBytes());
+		}
+		
+		os.write(FEATURES_CONFIG_END.getBytes());
+		os.close();
+	}
+	
+	public static Pair<Collection<URI>, Collection<FeatureInfo>> readFromXML(InputStream is) {
+		
+		return null; // TODO
+	}
+}