[Esbox-commits] r1249 - in branches/work_Ed: org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/command org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk org.maemo.esbox.scratchbox.sb1 org.maemo.esbox.scratchbox.sb1/conf org.maemo.esbox.scratchbox.sb1/icons/full org.maemo.esbox.scratchbox.sb1/icons/full/obj16 org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/provider org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/preferences org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/scratchbox/sb1/sdk org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/command org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/launcher org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/provider org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/wizard

eswartz at garage.maemo.org eswartz at garage.maemo.org
Sat Feb 28 00:27:07 EET 2009


Author: eswartz
Date: 2009-02-28 00:27:06 +0200 (Sat, 28 Feb 2009)
New Revision: 1249

Added:
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/icons/full/obj16/
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/icons/full/obj16/build_target_container.png
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/icons/full/obj16/build_target_icon.gif
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/SB1PreferenceMigrator.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/BaseScratchbox1SDKInstallerEngine.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/MaemoScriptInstallerMonitor.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/NewScratchbox1SDKWizard.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1InstallerWorkPage.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerData.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerDataContentLabelProvider.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerEngine.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerSelectionWizardPage.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerData.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerDataContentLabelProvider.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerEngine.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerSelectionWizardPage.java
Removed:
   branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/ScratchboxSDK.java
Modified:
   branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/AllTests.java
   branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestProcessLauncher.java
   branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestSB1ProcessLauncher.java
   branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestSB1SDKProvider.java
   branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/BaseTest.java
   branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestCreateTargetSb2Command.java
   branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestScratchboxFacade.java
   branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestShowPathMappingSb2Command.java
   branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/OldStyleProjectProperties.java
   branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/AbstractScratchboxSDK.java
   branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/AbstractScratchboxSDKTarget.java
   branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/command/ScratchboxCommand.java
   branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk/IScratchboxSDK.java
   branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk/ScratchboxSDKFacade.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/conf/sb1_prefs.xml
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/plugin.xml
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/AbstractSB1Command.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/CreateTargetCommand.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/GetCurrentTargetCommand.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/GetVersionScratchboxCommand.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/RemoveTargetCommand.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/SB1PreferenceConstants.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1FileSystemMapping.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1SDK.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1SDKTarget.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher/Scratchbox1PrepareTargetProcessLaunchAdapter.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher/Scratchbox1ProcessLauncher.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/provider/Scratchbox1SDKProvider.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters/MaemoScratchbox1SDKManageTargetAdapter.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters/MaemoScratchbox1SDKManageTargetAdapterFactory.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/preferences/Scratchbox1PreferencesPage.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/NewScratchbox1TargetWizard.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/scratchbox/sb1/sdk/IScratchbox1SDK.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/command/CreateTargetSb2Command.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core/Scratchbox2SDK.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core/Scratchbox2SDKTarget.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/launcher/Scratchbox2ProcessLauncherFactory.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/provider/Scratchbox2SDKProvider.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters/MaemoScratchbox2SDKManageTargetAdapter.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters/MaemoScratchbox2SDKManageTargetAdapterFactory.java
   branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/wizard/NewScratchbox2TargetWizard.java
Log:
-- add "Install Scratchbox 1" and "Add Scratchbox 1 Targets" wizards
-- support multiple Scratchbox 1 installations
-- rework prefs to provide a path of Scratchbox 1 roots
-- fix issues related to not having Scratchbox 1 at /scratchbox

-- remove unnecessary ScratchboxException from ScratchboxSDKFacade calls
-- minor cleanups to make SB1 and SB2 use fewer static methods to reduce duplication


Modified: branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/AllTests.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/AllTests.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/AllTests.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -22,15 +22,15 @@
 	public static Test suite() {
 		TestSuite suite = new TestSuite(
 				"Test for org.maemo.esbox.scratchbox.tests");
-		suite.addTest(new JUnit4TestAdapter(TestOProfileValgrindSupport.class));
 		//$JUnit-BEGIN$
 		suite.addTestSuite(TestSB1SDKProvider.class);
+		suite.addTestSuite(TestSB1ProcessLauncher.class);
+		suite.addTestSuite(TestSb1SDKTarget.class);
 		suite.addTestSuite(TestSB2SDKProvider.class);
 		suite.addTestSuite(TestSB2ProcessLauncher.class);
-		suite.addTestSuite(TestSB1ProcessLauncher.class);
 		suite.addTestSuite(TestProcessLauncher.class);
-		suite.addTestSuite(TestSb1SDKTarget.class);
 		//$JUnit-END$
+		suite.addTest(new JUnit4TestAdapter(TestOProfileValgrindSupport.class));
 		return suite;
 	}
 

Modified: branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestProcessLauncher.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestProcessLauncher.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestProcessLauncher.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -250,9 +250,9 @@
 		IPath scriptPath = target.getMachine().getUserHome().append(".tmp").append("foo.sh");
 		IPath targetPath = target.getMachineToSDKTargetFileSystemMapping().convertTargetToHostPath(scriptPath);
 		assertNotNull(target + ": could not create a file in " + scriptPath, targetPath);
-		target.getTargetFileSystemAccess().getFileStore(targetPath.removeLastSegments(1)).mkdir(0, null);
 		
-		IFileStore fileStore = target.getTargetFileSystemAccess().getFileStore(targetPath);
+		IFileStore fileStore = target.getMachineFileSystemAccess().getFileStore(targetPath);
+		fileStore.getParent().mkdir(0, null);
 		OutputStream fos = fileStore.openOutputStream(
 				EFS.NONE, new NullProgressMonitor());
 		fos.write(("#!/bin/sh\n" + cmdText).getBytes());

Modified: branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestSB1ProcessLauncher.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestSB1ProcessLauncher.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestSB1ProcessLauncher.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -12,6 +12,7 @@
 
 import org.eclipse.core.runtime.*;
 import org.junit.Test;
+import org.maemo.esbox.internal.scratchbox.sb1.core.Scratchbox1SDK;
 import org.maemo.esbox.internal.scratchbox.sb1.provider.Scratchbox1SDKProvider;
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.env.EnvironmentManager;
@@ -94,10 +95,11 @@
 				assertNotNull(args);
 
 				// be sure no variables are left unexpanded
-				assertFalse(CommandLineArguments.toCommandLine(args).contains("${"));
+				assertFalse(CommandLineArguments.toCommandLine(args),
+						CommandLineArguments.toCommandLine(args).contains("${"));
 
 				// assume the pattern is still /scratchbox/login ... 
-				assertEquals("/scratchbox/login", args.get(0));
+				assertEquals(((Scratchbox1SDK) target.getSDK()).getInstallRoot().append("login").toPortableString(), args.get(0));
 			}
 		});
 	}
@@ -133,12 +135,13 @@
 				assertNotNull(args);
 
 				// be sure no variables are left unexpanded
-				assertFalse(CommandLineArguments.toCommandLine(args).contains("${"));
+				assertFalse(CommandLineArguments.toCommandLine(args),
+						CommandLineArguments.toCommandLine(args).contains("${"));
 
 				// assume the pattern is still /scratchbox/login -d ...
 				// ".../run.sh ... \".... <command>\""
 				// (basically verifying the command is wrapped)
-				assertEquals("/scratchbox/login", args.get(0));
+				assertEquals(((Scratchbox1SDK) target.getSDK()).getInstallRoot().append("login").toPortableString(), args.get(0));
 				String last = args.get(args.size() - 1);
 				// System.out.println(last);
 				assertEquals(

Modified: branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestSB1SDKProvider.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestSB1SDKProvider.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/TestSB1SDKProvider.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -14,29 +14,33 @@
 
 import org.eclipse.core.filesystem.IFileStore;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IStatus;
 import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
 import org.junit.Test;
+import org.maemo.esbox.internal.scratchbox.sb1.core.Scratchbox1SDK;
 import org.maemo.esbox.internal.scratchbox.sb1.provider.Scratchbox1SDKProvider;
 import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDKTarget;
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.machine.ILocalMachine;
+import org.maemo.mica.common.core.machine.IMountPoint;
 import org.maemo.mica.common.core.sdk.ISDK;
 import org.maemo.mica.common.core.sdk.ISDKPlatform;
 import org.maemo.mica.common.core.sdk.ISDKProvider;
 import org.maemo.mica.common.core.sdk.ISDKTarget;
 import org.maemo.mica.common.core.sdk.SDKFactory;
+import org.maemo.mica.common.core.tests.StdoutProgressReporter;
 import org.maemo.mica.common.core.tests.TestUtils;
 import org.maemo.mica.common.core.tests.core.BaseTest;
 import org.maemo.mica.maemosdk.core.MaemoSDKPlatform;
 import org.maemo.mica.maemosdk.core.MaemoSDKPlatformEngine;
 
 /**
- * If SB1 is installed, make sure its SDKs and targets
- * are properly detected, and that it launches processes
- * in the expected way
+ * If SB1 is installed, make sure its SDKs and targets are properly detected,
+ * and that it launches processes in the expected way
+ * 
  * @author eswartz
- *
+ * 
  */
 public class TestSB1SDKProvider extends BaseTest {
 	private ISDKProvider sb1Provider;
@@ -49,8 +53,6 @@
 		List<ISDKProvider> providers = factory.getSDKProviders();
 		assertNotNull(providers);
 		
-		// don't worry if we don't find an SB1 installation
-		// on this host (this is mostly a manual test)
 		for (ISDKProvider provider : providers) {
 			if (provider instanceof Scratchbox1SDKProvider) {
 				sb1Provider = provider;
@@ -86,12 +88,43 @@
 			assertEquals("Scratchbox 1", sdk.getName());
 			assertTrue(sdk.getVersion().matches("1\\.0\\.\\d+"));
 			IPath root = sdk.getSDKRoot();
-			assertTrue(sdk.getMachineFileSystemAccess().getFileStore(root).fetchInfo().exists());
-			assertTrue(root.toPortableString().startsWith("/scratchbox/"));
+			assertTrue(sdk+" -> " +root+"", sdk.getMachineFileSystemAccess().getFileStore(root).fetchInfo().exists());
+			assertTrue(root+"", root.toPortableString().contains("/scratchbox/users/"));
+			assertTrue(((Scratchbox1SDK)sdk).getInstallRoot().toPortableString().endsWith("/scratchbox/"));
 		}
 	}
 
 	@Test
+	public void testSB1SDKStartStop() throws Exception {
+		if (sb1Provider == null)
+			return;
+		
+		List<ISDK> sdks = sb1Provider.createSDKs();
+		assertNotNull(sdks);
+		
+		for (ISDK sdk : sdks) {
+			Scratchbox1SDK sb1Sdk = (Scratchbox1SDK) sdk;
+			IStatus status = Scratchbox1SDK.startup(sdk.getMachine(), sb1Sdk.getInstallRoot(), 
+					null, new StdoutProgressReporter());
+			if (status.isOK()) {
+				status = Scratchbox1SDK.shutdown(sdk.getMachine(), sb1Sdk.getInstallRoot(), 
+						null, new StdoutProgressReporter());
+				if (status.isOK()) {
+					// no mounts should be present
+					IMountPoint[] mounts = sdk.getMachine().getFileSystemAccess().getMounts();
+					for (IMountPoint mount : mounts) {
+						if (sb1Sdk.getInstallRoot().isPrefixOf(mount.getPath())) {
+							fail("We shut down " + sb1Sdk + " but " + mount.getPath() + " is still mounted");
+						}
+					}
+					status = Scratchbox1SDK.startup(sdk.getMachine(), sb1Sdk.getInstallRoot(), 
+							null, new StdoutProgressReporter());
+					assertTrue("Failed to restart scratchbox 1 after shutting it down:\n"+status, status.isOK());
+				}
+			}
+		}
+	}
+	@Test
 	public void testSB1SDKTargets() throws Exception {
 		if (sb1Provider == null)
 			return;
@@ -152,35 +185,32 @@
 			sbPath = new Path(test);
 			hostPath = null;
 			
-			// ignore bogus target installed on my system -- no underscore in name
-			if (target.getName().contains("_")) {
-				// make sure the path can be converted to somewhere on the machine
-				// (no guarantee we can see it on the host machine)
-				IFileStore store = target.getTargetFileSystemAccess().getFileStore(sbPath);
-				assertTrue(target + " @" + sbPath.toString(), store.fetchInfo().exists());
-				
-				// if we happen to be running locally, verify sanity
-				if (target.getMachine() instanceof ILocalMachine) {
-					try {
-						hostPath = target.convertTargetToHostPath(sbPath);
-						assertTrue(hostPath.toFile().toString(),
-								target.getTargetFileSystemAccess().getFileStore(hostPath).fetchInfo().exists());
-						// there's no guarantee of being able to convert back, but
-						// at least don't throw
-						//assertEquals(sbPath, target.convertHostToTargetPath(hostPath));
-						target.convertHostToTargetPath(hostPath);
-					} catch (MicaException e) {
-						fail(e.getMessage());
-					}
+			// make sure the path can be converted to somewhere on the machine
+			// (no guarantee we can see it on the host machine)
+			IFileStore store = target.getTargetFileSystemAccess().getFileStore(sbPath);
+			assertTrue(target + " @" + sbPath.toString() + " -> " + store, store.fetchInfo().exists());
+			
+			// if we happen to be running locally, verify sanity
+			if (target.getMachine() instanceof ILocalMachine) {
+				try {
+					hostPath = target.convertTargetToHostPath(sbPath);
+					assertTrue(hostPath.toFile().toString(),
+							target.getTargetFileSystemAccess().getFileStore(hostPath).fetchInfo().exists());
+					// there's no guarantee of being able to convert back, but
+					// at least don't throw
+					//assertEquals(sbPath, target.convertHostToTargetPath(hostPath));
+					target.convertHostToTargetPath(hostPath);
+				} catch (MicaException e) {
+					fail(e.getMessage());
 				}
-			}			
+			}
 		}
 		
 	}
 
 	private void _testSDKTargetFileAccess(ISDKTarget target) {
-		IFileStore sbRoot = target.getTargetFileSystemAccess().getFileStore(target.getSDKRoot());
-		assertTrue(sbRoot.fetchInfo().exists());
+		IFileStore sbRoot = target.getTargetFileSystemAccess().getFileStore(new Path("/"));
+		assertTrue(target+"/"+target.getSDKRoot()+"/"+sbRoot.toString(), sbRoot.fetchInfo().exists());
 		
 		// these tests only make sense if running the scratchbox machine 
 		
@@ -191,6 +221,10 @@
 			sbPath = target.convertHostToTargetPath(target.getSDKRoot());
 			assertEquals(new Path("/"), sbPath);
 			
+			// this mapping is independent of installation
+			hostPath = target.convertTargetToHostPath(new Path("/scratchbox"));
+			assertEquals(((Scratchbox1SDK)target.getSDK()).getInstallRoot(), hostPath);
+			
 			// guaranteed NOT to be an SB1 path
 			hostPath = new Path("/");
 			try {
@@ -200,7 +234,7 @@
 			}
 			
 			IPath rootstrapPath = ((IScratchboxSDKTarget) target).getRootstrapPath();
-			if (target.getName().toLowerCase().contains("chinook40"))
+			if (TestUtils.isSupportedBuildableSDKTarget(target))
 				assertNotNull(rootstrapPath);
 			if (rootstrapPath != null) {
 				System.out.println("  rootstrap path is -> " + rootstrapPath);

Modified: branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/BaseTest.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/BaseTest.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/BaseTest.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -10,23 +10,19 @@
  *******************************************************************************/
 package org.maemo.esbox.scratchbox.tests.commands;
 
+import java.util.List;
+
+import junit.framework.TestCase;
+
 import org.junit.Before;
 import org.maemo.esbox.internal.scratchbox.sb1.core.Scratchbox1SDK;
 import org.maemo.esbox.internal.scratchbox.sb2.core.Scratchbox2SDK;
-import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
-import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDKTarget;
 import org.maemo.esbox.scratchbox.core.sdk.ScratchboxSDKFacade;
 import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
 import org.maemo.esbox.scratchbox.sb2.sdk.IScratchbox2SDK;
-import org.maemo.mica.common.core.machine.IFileSystemAccess;
-import org.maemo.mica.common.core.process.IProcessLauncherFactory;
-import org.maemo.mica.common.core.sdk.ISDKTarget;
 import org.maemo.mica.common.core.sdk.SDKFactory;
 import org.maemo.mica.common.core.sdk.commands.ICommandAbstractor;
-import org.maemo.mica.common.core.tests.TestUtils;
 
-import junit.framework.TestCase;
-
 /**
  * Base test for the ICommand tests
  * @author eswartz
@@ -38,7 +34,8 @@
 	protected ICommandAbstractor sb1Command;
 	protected IScratchbox2SDK sb2Sdk;
 	protected ICommandAbstractor sb2Command;
-	protected ICommandAbstractor sb2ArmelTargetCommand;
+	protected List<IScratchbox1SDK> sb1Sdks;
+	protected List<IScratchbox2SDK> sb2Sdks;
 
 	/**
 	 * @throws java.lang.Exception
@@ -46,48 +43,24 @@
 	@Before
 	public void setUp() throws Exception {
 		SDKFactory.getInstance().waitForRefreshComplete(null);
-		this.sb1Sdk = ScratchboxSDKFacade.getInstance().getScratchboxSDK(IScratchbox1SDK.class).get(0);
-		this.sb1Command = ((Scratchbox1SDK) sb1Sdk).getCommandAbstractor();
-		try {
-			this.sb2Sdk = ScratchboxSDKFacade.getInstance().getScratchboxSDK(IScratchbox2SDK.class).get(0);
+		this.sb1Sdks = ScratchboxSDKFacade.getInstance().getScratchboxSDK(IScratchbox1SDK.class);
+		if (sb1Sdks.size() > 0) {
+			this.sb1Sdk = sb1Sdks.get(0);
+			this.sb1Command = ((Scratchbox1SDK) sb1Sdk).getCommandAbstractor();
+		}
+		else
+			this.sb1Sdk = null;
+		
+		this.sb2Sdks = ScratchboxSDKFacade.getInstance().getScratchboxSDK(IScratchbox2SDK.class);
+		if (sb2Sdks.size() > 0) {
+			this.sb2Sdk = sb2Sdks.get(0);
 			this.sb2Command = ((Scratchbox2SDK) sb2Sdk).getCommandAbstractor();
-		} catch (ScratchboxException e) {
-			// no sb2, fine
+			
 		}
-		if (sb2Sdk != null) {
-			for (ISDKTarget target : sb2Sdk.getSDKTargets()) {
-				if (!TestUtils.isSupportedBuildableSDKTarget(target))
-					continue;
-
-				if (target.getArchitecture().equals(IScratchboxSDKTarget.ARCHITECTURE_ARMEL)) {
-					final ISDKTarget sdkTarget = target;
-					this.sb2ArmelTargetCommand =  new ICommandAbstractor() {
-
-						public String getPreferenceValue(String key) {
-							return sdkTarget.getPreferenceValue(key);
-						}
-
-						public IProcessLauncherFactory getProcessLauncherFactory() {
-							return sdkTarget.getProcessLauncherFactory();
-						}
-
-						public IFileSystemAccess getFileSystemAccess() {
-							return sdkTarget.getTargetFileSystemAccess();
-						}
-					};
-					break;
-				}
-			}
-		}
+		else
+			this.sb2Sdk = null;
+		
 	}
 	
-	/**
-	 * Get a command abstractor that will not actually execute code.
-	 * @param target if non-null, use an SB2 mock process launcher, else use a host mock process launcher
-	 * @return ICommandAbstractor
-	 */
-	protected MockCommandAbstractor getSb2MockCommandAbstractor(final ISDKTarget target) {
-		return new MockCommandAbstractor(sb2Command, target);
-
-	}
+	
 }

Modified: branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestCreateTargetSb2Command.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestCreateTargetSb2Command.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestCreateTargetSb2Command.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -13,6 +13,7 @@
 import org.maemo.esbox.internal.scratchbox.sb2.command.CreateTargetSb2Command;
 import org.maemo.esbox.scratchbox.core.command.ScratchboxCommand;
 import org.maemo.mica.common.core.MicaException;
+import org.maemo.mica.common.core.sdk.ISDKTarget;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -50,6 +51,15 @@
 		assertEquals("sb2-init -c " + CPUTRANSP + " " + TARGET_NAME + " " + COMPILER, command);
 	}
 
+	/**
+	 * Get a command abstractor that will not actually execute code.
+	 * @param target if non-null, use an SB2 mock process launcher, else use a host mock process launcher
+	 * @return ICommandAbstractor
+	 */
+	protected MockCommandAbstractor getSb2MockCommandAbstractor(final ISDKTarget target) {
+		return new MockCommandAbstractor(sb2Command, target);
+
+	}
 	public void testPerformCommandNoCpuTransp() throws MicaException {
 		MockCommandAbstractor mockCommandAbstractor = getSb2MockCommandAbstractor(null);
 		ScratchboxCommand createTargetCommand = new CreateTargetSb2Command(sb2Sdk, 

Modified: branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestScratchboxFacade.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestScratchboxFacade.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestScratchboxFacade.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -11,22 +11,22 @@
  *******************************************************************************/
 package org.maemo.esbox.scratchbox.tests.commands;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import junit.framework.TestCase;
+
 import org.junit.Test;
 import org.maemo.esbox.internal.scratchbox.sb1.core.Scratchbox1SDK;
 import org.maemo.esbox.internal.scratchbox.sb2.core.Scratchbox2SDK;
 import org.maemo.esbox.scratchbox.core.sdk.ScratchboxSDKFacade;
 import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
 import org.maemo.mica.common.core.MicaException;
-import org.maemo.mica.common.core.machine.IMachine;
-import org.maemo.mica.common.core.machine.MachineRegistry;
 import org.maemo.mica.common.core.process.IProcessLauncher;
 import org.maemo.mica.common.core.process.ProcessLauncherCreator;
 import org.maemo.mica.common.core.sdk.ISDKTarget;
 
-import java.util.*;
-
-import junit.framework.TestCase;
-
 /**
  * Please, read file TESTS.txt for more instructions about test.
  */
@@ -44,17 +44,6 @@
 
 	/**
 	 * Test method for
-	 * {@link org.maemo.esbox.common.core.scratchbox.ScratchboxFacade#getInstance()}.
-	 */
-//	@Test
-//	public void testGetInstance() {
-//		ScratchboxFacade facadeA = ScratchboxFacade.getInstance();
-//		ScratchboxFacade facadeB = ScratchboxFacade.getInstance();
-//		assertSame(facadeA, facadeB);
-//	}
-
-	/**
-	 * Test method for
 	 * {@link org.maemo.esbox.common.core.scratchbox.ScratchboxFacade#getCompilers()}.
 	 * 
 	 * @throws MicaException
@@ -407,30 +396,16 @@
 		assertEquals(theTarget, currentTarget);
 	}
 
-	/**
-	 * Test method for
-	 * {@link org.maemo.esbox.common.core.scratchbox.ScratchboxFacade#getCurrentSbox1Version()}.
-	 * 
-	 * @throws MicaException
-	 */
 	@Test
-	public void testGetCurrentSboxVersion() {
-		for (IMachine machine : MachineRegistry.getInstance().getBuildMachines()) {
-			String sbox1Version;
-			try {
-				sbox1Version = Scratchbox1SDK.getCurrentSboxVersion(machine);//ScratchboxFacade.getInstance().getCurrentSbox1Version(machine);
-				assertTrue(sbox1Version.matches("1\\.0\\.\\d+"));
-			} catch (MicaException e) {
-				System.out.println("No Scratchbox 1 on " + machine);
-			}
-			String sbox2Version;
-			try {
-				sbox2Version = Scratchbox2SDK.getCurrentSboxVersion(machine);//ScratchboxFacade.getInstance().getCurrentSbox1Version(machine);
-				assertTrue(sbox2Version.matches("1\\.99\\..*|2\\..*"));
-			} catch (MicaException e) {
-				System.out.println("No Scratchbox 2 on " + machine);
-			}
+	public void testGetCurrentSboxVersion() throws Exception {
+		for (Scratchbox1SDK sdk : ScratchboxSDKFacade.getInstance().getScratchboxSDK(Scratchbox1SDK.class)) {
+			String sbox1Version = sdk.getCurrentSboxVersion();
+			assertTrue(sbox1Version.matches("1\\.0\\.\\d+"));
 		}
+		for (Scratchbox2SDK sdk : ScratchboxSDKFacade.getInstance().getScratchboxSDK(Scratchbox2SDK.class)) {
+			String sbox2Version = sdk.getCurrentSboxVersion();
+			assertTrue(sbox2Version.matches("1\\.99\\..*|2\\..*"));
+		}
 	}
 
 	/**

Modified: branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestShowPathMappingSb2Command.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestShowPathMappingSb2Command.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.maemosdk.tests/src/org/maemo/esbox/scratchbox/tests/commands/TestShowPathMappingSb2Command.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -12,14 +12,49 @@
 
 import org.eclipse.core.runtime.IPath;
 import org.maemo.esbox.internal.scratchbox.sb2.command.ShowPathMappingSb2Command;
+import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDKTarget;
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.machine.IFileSystemAccess;
+import org.maemo.mica.common.core.process.IProcessLauncherFactory;
+import org.maemo.mica.common.core.sdk.ISDKTarget;
+import org.maemo.mica.common.core.sdk.commands.ICommandAbstractor;
+import org.maemo.mica.common.core.tests.TestUtils;
 
 import java.util.*;
 
 public class TestShowPathMappingSb2Command extends BaseTest {
-
-	public void testPerformCommand() throws MicaException {
+
+	
+	public void testPerformCommand() throws MicaException {
+
+		if (sb2Sdk == null)
+			return;
+		
+		ICommandAbstractor sb2ArmelTargetCommand = null;
+		for (ISDKTarget target : sb2Sdk.getSDKTargets()) {
+			if (!TestUtils.isSupportedBuildableSDKTarget(target))
+				continue;
+
+			if (target.getArchitecture().equals(IScratchboxSDKTarget.ARCHITECTURE_ARMEL)) {
+				final ISDKTarget sdkTarget = target;
+				sb2ArmelTargetCommand =  new ICommandAbstractor() {
+
+					public String getPreferenceValue(String key) {
+						return sdkTarget.getPreferenceValue(key);
+					}
+
+					public IProcessLauncherFactory getProcessLauncherFactory() {
+						return sdkTarget.getProcessLauncherFactory();
+					}
+
+					public IFileSystemAccess getFileSystemAccess() {
+						return sdkTarget.getTargetFileSystemAccess();
+					}
+				};
+				break;
+			}
+		}
+		
 		if (sb2ArmelTargetCommand == null)
 			return;
 			

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/OldStyleProjectProperties.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/OldStyleProjectProperties.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/OldStyleProjectProperties.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -18,7 +18,6 @@
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.QualifiedName;
 import org.maemo.esbox.internal.scratchbox.core.Activator;
-import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
 import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK;
 import org.maemo.esbox.scratchbox.core.sdk.ScratchboxSDKFacade;
 import org.maemo.mica.common.core.MicaException;
@@ -175,12 +174,7 @@
 		if (sboxVersion == null)
 			return null;
 		
-		List<IScratchboxSDK> sboxSDKs;
-		try {
-			sboxSDKs = ScratchboxSDKFacade.getInstance().getAllScratchboxSDKs();
-		} catch (ScratchboxException e) {
-			return null;
-		}
+		List<IScratchboxSDK> sboxSDKs = ScratchboxSDKFacade.getInstance().getAllScratchboxSDKs();
 		for (IScratchboxSDK sboxSDK : sboxSDKs) {
 			if (sboxVersion.equals(Integer.toString(sboxSDK.getSboxVersion()))) {
 				return sboxSDK.getName();

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/AbstractScratchboxSDK.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/AbstractScratchboxSDK.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/AbstractScratchboxSDK.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -15,7 +15,7 @@
 import java.util.Properties;
 
 import org.eclipse.core.runtime.IPath;
-import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Path;
 import org.maemo.esbox.internal.api.scratchbox.core.commands.sbrsh.*;
 import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK;
 import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDKTarget;
@@ -25,53 +25,70 @@
 import org.maemo.mica.common.core.process.*;
 import org.maemo.mica.common.core.sdk.IPreferenceProvider;
 import org.maemo.mica.common.core.sdk.commands.ICommandAbstractor;
-import org.maemo.mica.internal.api.common.core.machine.HostUnixMachine;
+import org.maemo.mica.common.ui.SudoLauncherUtils;
 import org.maemo.mica.internal.api.common.core.sdk.BaseSDK;
 
 public abstract class AbstractScratchboxSDK extends BaseSDK implements IScratchboxSDK {
 
 	protected IPreferenceProvider prefProvider = null;
 
-	protected final String NAME; //$NON-NLS-1$
+	protected final String nameKey; //$NON-NLS-1$
 	/** String for URI of machine where we detected scratchbox VERSION */
-	protected final String SB_MACHINE;
+	protected final String sbMachineKey;
 	/** String for scratchbox VERSION version or <code>null</code> */
-	protected final String SB_VERSION;
+	protected final String sbVersionKey;
 	/** String[] scratchbox VERSION target name array */
-	protected final String SB_TARGETS;
-	protected final int VERSION_NUMBER;
+	protected final String sbTargetsKey;
+	protected final int versionNumberKey;
 
 	private String cachedCurrentTarget;
 
 	protected final static List<String> EMPTY_ARGS = new ArrayList<String>();
 
-	public AbstractScratchboxSDK(IMachine machine, String version, String name,
+	protected final IPath installLocation;
+
+	public AbstractScratchboxSDK(IMachine machine, IPath location, String version, String name,
 			String sb_machine, String sb_version, String sb_targets,
 			int versionNumber) {
 		super(machine, version, name);
-		NAME = name;
-		SB_MACHINE = sb_machine;
-		SB_VERSION = sb_version;
-		SB_TARGETS = sb_targets;
-		VERSION_NUMBER = versionNumber;
+		this.installLocation = location;
+		this.nameKey = name;
+		this.sbMachineKey = sb_machine;
+		this.sbVersionKey = sb_version;
+		this.sbTargetsKey = sb_targets;
+		this.versionNumberKey = versionNumber;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.core.sdk.ISDK#init()
+	 */
+	public void init() {
+		cachedCurrentTarget = null;
+	}
+	
 	/*
 	 * (non-Javadoc)
 	 * 
-	 * @see org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK#getSboxVersion()
+	 * @see org.maemo.esbox.common.core.sdk.ISDK#refresh()
 	 */
-	public int getSboxVersion() {
-		return VERSION_NUMBER;
+	public void refresh() {
+		init();
 	}
 
+	/* (non-Javadoc)
+	 * @see org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK#getInstallLocation()
+	 */
+	public IPath getInstallRoot() {
+		return installLocation;
+	}
+	
 	/*
 	 * (non-Javadoc)
 	 * 
-	 * @see org.maemo.esbox.common.core.sdk.ISDK#refresh()
+	 * @see org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK#getSboxVersion()
 	 */
-	public void refresh() {
-		cachedCurrentTarget = null;
+	public int getSboxVersion() {
+		return versionNumberKey;
 	}
 
 	/*
@@ -232,17 +249,69 @@
 	/**
 	 * For launching commands on the SDK's machine in order to control the
 	 * machine, ensure we can access the tools for that SDK.
-	 * 
-	 * SB1 is usually installed to contain softlinks into /usr/bin, but the
-	 * .tar.gz installation method doesn't do this. So be sure to handle sb1
-	 * commands which might not be on /usr/bin.
-	 * 
+	 * <p>
+	 * So always try to access the tools on the installation root of the SDK
+	 * by favoring this entry in the PATH.
 	 * @param toolsPath
 	 * 
 	 */
-	protected static ICommandAbstractor wrapCommandAbstractorForSDK(
-			final ICommandAbstractor commandAbstractor, IMachine machine,
+	protected ICommandAbstractor wrapCommandAbstractorForSDK(
+			final ICommandAbstractor commandAbstractor,
 			final String identifyingTool, final String toolsPath) {
+		
+		return new ICommandAbstractor() {
+
+			public String getPreferenceValue(String key) {
+				return commandAbstractor.getPreferenceValue(key);
+			}
+
+			public IProcessLauncherFactory getProcessLauncherFactory() {
+				final IProcessLauncherFactory launcherFactory = commandAbstractor
+						.getProcessLauncherFactory();
+				IProcessLauncherFactory wrappedLauncherFactory = new IProcessLauncherFactory() {
+
+					public IProcessLauncher createProcessLauncher(
+							IPath workingDirectory, List<String> commandLine,
+							IEnvironmentModifierBlock envBlock) {
+
+						// optimize this somewhat... changing the environment means launching
+						// an extra shell and making an uglier command line
+						IPath executablePath = new Path(toolsPath).append(commandLine.get(0));
+						if (getMachine().getFileSystemAccess().getFileStore(executablePath).fetchInfo().exists()) {
+							commandLine.set(0, executablePath.toPortableString());
+						} else {
+							envBlock = ProcessLauncherUtils.addToPATH(
+									getMachine(),
+									getRawEnvironment(),
+									envBlock != null ? envBlock
+											: defaultEnvironmentModifierBlock(),
+									toolsPath, true);
+						}
+						return launcherFactory.createProcessLauncher(
+								workingDirectory, commandLine, envBlock);
+					}
+
+					public IEnvironmentModifierBlock defaultEnvironmentModifierBlock() {
+						return launcherFactory
+								.defaultEnvironmentModifierBlock();
+					}
+
+					public Properties getRawEnvironment() {
+						return launcherFactory.getRawEnvironment();
+					}
+
+				};
+				return wrappedLauncherFactory;
+			}
+
+			public IFileSystemAccess getFileSystemAccess() {
+				return commandAbstractor.getFileSystemAccess();
+			}
+
+		};
+		
+		/*
+		final IMachine machine = getMachine();
 		if (MachineUtils.areToolsOnPath(machine, identifyingTool)) {
 			return commandAbstractor;
 		}
@@ -265,7 +334,7 @@
 						// .tar.gz with no softlinks into /usr/bin.
 
 						envBlock = ProcessLauncherUtils.addToPATH(
-								new HostUnixMachine(Platform.OS_LINUX, Platform.getOSArch()),
+								machine,
 								getRawEnvironment(),
 								envBlock != null ? envBlock
 										: defaultEnvironmentModifierBlock(),
@@ -288,17 +357,33 @@
 				return wrappedLauncherFactory;
 			}
 
-			/*
-			 * (non-Javadoc)
-			 * 
-			 * @seeorg.maemo.esbox.internal.core.command.ICommandAbstractor#
-			 * getFileSystemAccess()
-			 */
 			public IFileSystemAccess getFileSystemAccess() {
 				return commandAbstractor.getFileSystemAccess();
 			}
 
 		};
+		*/
 	}
 
+	/**
+	 * Get a process launcher for root programs
+	 * @return {@link IProcessLauncherFactory} or <code>null</code>
+	 */
+	protected static IProcessLauncher getRootProcessLauncher(IMachine machine, IPath cwd, List<String> cmdLine, IEnvironmentModifierBlock envBlock) {
+		cmdLine = SudoLauncherUtils.convertToSudoCommandLine(cmdLine, "root");
+		
+		IProcessLauncherFactory factory = machine.getProcessLauncherFactory();
+		IProcessLauncher launcher = factory.createProcessLauncher(
+				cwd, cmdLine, envBlock);
+		return launcher;
+	}
+
+	/**
+	 * Get a stream monitor to check for sudo password prompt
+	 * @return {@link IProcessLauncherFactory} or <code>null</code>
+	 */
+	protected static IStreamMonitor getRootProcessMonitor(IMachine machine, List<String> cmdLine) {
+		return SudoLauncherUtils.createSudoSnifferMonitor(
+				machine.getUserName(), "root", cmdLine);
+	}
 }

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/AbstractScratchboxSDKTarget.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/AbstractScratchboxSDKTarget.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/AbstractScratchboxSDKTarget.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -24,7 +24,6 @@
 
 /**
  * @author baranov
- * 
  */
 public abstract class AbstractScratchboxSDKTarget extends BaseSDKTarget
 		implements IScratchboxSDKTarget {

Deleted: branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/ScratchboxSDK.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/ScratchboxSDK.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/internal/api/scratchbox/core/sdk/ScratchboxSDK.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -1,154 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 Nokia Corporation.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- *    Ed Swartz (Nokia) - initial API and implementation
- *******************************************************************************/
-package org.maemo.esbox.internal.api.scratchbox.core.sdk;
-
-import java.util.List;
-
-import org.eclipse.core.runtime.IPath;
-import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK;
-import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDKTarget;
-import org.maemo.mica.common.core.MicaException;
-import org.maemo.mica.common.core.machine.ILocalMachine;
-import org.maemo.mica.common.core.machine.IMachine;
-import org.maemo.mica.common.core.sdk.IPreferenceProvider;
-import org.maemo.mica.common.core.sdk.commands.ICommandAbstractor;
-import org.maemo.mica.internal.api.common.core.sdk.BaseSDK;
-
-/**
- * SDK for a Scratchbox environment
- * 
- * @author eswartz
- * 
- */
-public abstract class ScratchboxSDK extends BaseSDK implements IScratchboxSDK {
-
-	private String cachedCurrentTarget;
-
-	protected IPreferenceProvider prefProvider;
-	
-	public ScratchboxSDK(IMachine machine, String version, String name, IPreferenceProvider prefProvider) {
-		super(machine, version, name);
-		this.prefProvider = prefProvider;
-	}
-
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.maemo.esbox.common.core.sdk.ISDK#refresh()
-	 */
-	public void refresh() {
-		cachedCurrentTarget = null;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.maemo.esbox.common.core.scratchbox.sdk.IScratchboxSDK#getCachedCurrentTarget
-	 * ()
-	 */
-	public String getCachedCurrentTarget() {
-		// not (too) expensive to re-check, so don't invoke a process
-		if (getMachine() instanceof ILocalMachine)
-			return null;
-		return cachedCurrentTarget;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.maemo.esbox.common.core.scratchbox.sdk.IScratchboxSDK#setCachedCurrentTarget
-	 * (java.lang.String)
-	 */
-	public void setCachedCurrentTarget(String currentTarget) {
-		cachedCurrentTarget = currentTarget;
-	}
-
-	public String getPreferenceValue(String key) {
-		return prefProvider.getPreferenceValue(key);
-	}
-
-	public boolean addSbrshAccessList(String targetDeviceAddr, String username,
-			String ipAddr) throws MicaException {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public boolean configureSbrsh(String targetName, String targetDeviceAddr,
-			String nfsServerAddr) throws MicaException {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public boolean createTarget(String targetName, String compiler,
-			String devkits, String cputransp) throws MicaException {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public ICommandAbstractor getCommandAbstractor() throws MicaException {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public List<String> getCompilers() throws MicaException {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public List<String> getCputransp() throws MicaException {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public String getCurrentSboxVersion(IMachine machine) throws MicaException {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public IScratchboxSDKTarget getCurrentSDKTarget() throws MicaException {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public String getCurrentTarget() throws MicaException {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public List<String> getTargets() throws MicaException {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-	public boolean mountTarget(String targetName) throws MicaException {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public boolean removeTarget(String targetName) throws MicaException {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public boolean unmountTarget(String targetName) throws MicaException {
-		// TODO Auto-generated method stub
-		return false;
-	}
-
-	public IPath getSDKRoot() {
-		// TODO Auto-generated method stub
-		return null;
-	}
-
-}

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/command/ScratchboxCommand.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/command/ScratchboxCommand.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/command/ScratchboxCommand.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -281,8 +281,8 @@
 				try {
 					inputs[0] = getInputFromProcess(process);
 
+					String error = getErrorInputFromProcess(process);
 					if (!allowError) {
-						String error = getErrorInputFromProcess(process);
 						if (error.length() > 0) {
 							excs[0] = new ScratchboxInvalidOperationException(
 									error);

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk/IScratchboxSDK.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk/IScratchboxSDK.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk/IScratchboxSDK.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -13,6 +13,7 @@
 
 import java.util.List;
 
+import org.eclipse.core.runtime.IPath;
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.sdk.ISDK;
 
@@ -20,10 +21,17 @@
  * This interface provides scratchbox-specific functionality to an ISDK
  * 
  * @author baranov
+ * @author eswartz
  * 
  */
 public interface IScratchboxSDK extends ISDK {
 	/**
+	 * Get the installation location where Scratchbox 1 or 2 is installed
+	 * @return IPath on target
+	 */
+	IPath getInstallRoot();
+	
+	/**
 	 * If appropriate, get the cached value of the scratchbox target.
 	 * 
 	 * @return cached name, or <code>null</code>

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk/ScratchboxSDKFacade.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk/ScratchboxSDKFacade.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.core/src/org/maemo/esbox/scratchbox/core/sdk/ScratchboxSDKFacade.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -41,38 +41,28 @@
 	 * Get the (first) scratchbox 1 installation on the system.
 	 * 
 	 * @return list of IScratchbox1SDK, never <code>null</code>
-	 * @throws ScratchboxException
-	 *             if no scratchbox SDKs available
 	 * */
-	public synchronized List<IScratchboxSDK> getAllScratchboxSDKs()
-			throws ScratchboxException {
-		if (scratchboxSDKs == null) {
-			SDKFactory.getInstance().waitForRefreshComplete(null);
-			List<ISDK> sdks = SDKFactory.getInstance().getSDKs();
-			scratchboxSDKs = new ArrayList<IScratchboxSDK>();
-			for (ISDK sdk : sdks) {
-				if (sdk instanceof IScratchboxSDK) {
-					scratchboxSDKs.add((IScratchboxSDK) sdk);
-				}
+	public synchronized List<IScratchboxSDK> getAllScratchboxSDKs() {
+		// always check since this facade doesn't listen to SDKFactory
+		SDKFactory.getInstance().waitForRefreshComplete(null);
+		List<ISDK> sdks = SDKFactory.getInstance().getSDKs();
+		scratchboxSDKs = new ArrayList<IScratchboxSDK>();
+		for (ISDK sdk : sdks) {
+			if (sdk instanceof IScratchboxSDK) {
+				scratchboxSDKs.add((IScratchboxSDK) sdk);
 			}
 		}
-		if (scratchboxSDKs.isEmpty())
-			throw new ScratchboxException("No scratchbox SDKs installed");
 		return scratchboxSDKs;
 	}
 
 	@SuppressWarnings("unchecked")
-	public <SboxSDK extends IScratchboxSDK> List<SboxSDK> getScratchboxSDK(
-			Class<SboxSDK> klass) throws ScratchboxException {
+	public <SboxSDK extends IScratchboxSDK> List<SboxSDK> getScratchboxSDK(Class<SboxSDK> klass) {
 		List<IScratchboxSDK> allSBoxSDKs = getAllScratchboxSDKs();
 		List<SboxSDK> result = new ArrayList<SboxSDK>();
 		for (IScratchboxSDK sdk : allSBoxSDKs) {
 			if (klass.isInstance(sdk))
 				result.add((SboxSDK) sdk);
 		}
-		if (result.isEmpty())
-			throw new ScratchboxException("No " + klass.getName()
-					+ " installed");
 		return result;
 	}
 
@@ -84,11 +74,7 @@
 	public IScratchboxSDKTarget[] getScratchboxSDKTargets() {
 		List<IScratchboxSDK> sboxSDKs = null;
 		List<IScratchboxSDKTarget> sdkTargets = new ArrayList<IScratchboxSDKTarget>();
-		try {
-			sboxSDKs = getAllScratchboxSDKs();
-		} catch (ScratchboxException e) {
-			sboxSDKs = Collections.emptyList();
-		}
+		sboxSDKs = getAllScratchboxSDKs();
 		for (IScratchboxSDK sboxSDK : sboxSDKs) {
 			ISDKTarget[] targets = sboxSDK.getSDKTargets();
 			for (ISDKTarget target : targets)

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/conf/sb1_prefs.xml
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/conf/sb1_prefs.xml	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/conf/sb1_prefs.xml	2009-02-27 22:27:06 UTC (rev 1249)
@@ -5,16 +5,15 @@
 	<comment>This file contains the default settings for Scratchbox 1 preferences; 
 	see the org.maemo.mica.common.core.preference_set_provider extension</comment>
 
-	<!-- WHEN ANY DEFAULTS CHANGED warranting rewriting prefs, 
-		bump pref version in esbox_common.xml and adjust ESboxPreferenceInitializer#RPEFS_VERSION_MAJOR ;
+	<!-- WHEN ANY DEFAULTS CHANGED warranting rewriting prefs, update the
+		Sb1PreferenceConstants#VERSION_MAJOR and handle converting preferences
+		in Sb1PreferenceMigrator. 
 		WHEN ANYTHING ELSE CHANGED which can be merged into existing prefs, 
-		adjust ESboxPreferenceInitializer#RPEFS_VERSION_MINOR -->
+		adjust Sb1PreferenceConstants#VERSION_MINOR -->
 		
-	<entry key="SB1_LOGIN_COMMAND">/scratchbox/login -d ${RUN_SCRIPT_DIRECTORY} "./${RUN_SCRIPT} ${{DIRECTORY}} \\\"${{{EXPORTS}}}\\\" \\\"${{{COMMAND}}} ${{{ARGS}}}\\\""</entry>
+	<entry key="SB1_LOGIN_COMMAND">${SBOX_ROOT}/login -d ${RUN_SCRIPT_DIRECTORY} "./${RUN_SCRIPT} ${{DIRECTORY}} \\\"${{{EXPORTS}}}\\\" \\\"${{{COMMAND}}} ${{{ARGS}}}\\\""</entry>
 	<entry key="SB1_SBOX_COMMAND">sb-conf ${ACTIONS} ${OPTIONS}</entry>	
 
-	<entry key="RUN_SCRIPT_LOC">/scratchbox/users/${USER}/home/${USER}/.esbox/</entry>
-
 	<!-- this uses ${QEMU} because the default qemu-arm is an often misconfigured softlink: see GetGdbQemuCommandPatternCommand -->
 	<entry key="SB1_GDB_REMOTE_QEMU">${QEMU} -g ${PORT}</entry>
 	
@@ -71,7 +70,7 @@
 	<entry key="SB1_LIST_OPT_TARGETS">--targets</entry>
 	<entry key="SB1_LIST_OPT_SESSIONS">--sessions</entry>
 	
-	<!-- setting such as Scratchbox location and user name -->
-	<entry key="SB1_SBOX_SANDBOX">/scratchbox/users/${USER}</entry>
+	<!-- Scratchbox installations to search -->
+	<entry key="SB1_ROOTS">/scratchbox:/opt/scratchbox</entry>
 	
 </properties>

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/icons/full/obj16/build_target_container.png
===================================================================
(Binary files differ)


Property changes on: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/icons/full/obj16/build_target_container.png
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/icons/full/obj16/build_target_icon.gif
===================================================================
(Binary files differ)


Property changes on: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/icons/full/obj16/build_target_icon.gif
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/plugin.xml
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/plugin.xml	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/plugin.xml	2009-02-27 22:27:06 UTC (rev 1249)
@@ -53,10 +53,31 @@
       <preferenceSetProvider
             defaultsXMLFile="conf/sb1_prefs.xml"
             preferenceConstantsClass="org.maemo.esbox.internal.scratchbox.sb1.core.SB1PreferenceConstants"
-            preferenceMigratorClass="org.maemo.mica.internal.api.common.core.OldESboxPreferenceMigrator"
+            preferenceMigratorClass="org.maemo.esbox.internal.scratchbox.sb1.core.SB1PreferenceMigrator"
             preferenceStoreBundle="org.maemo.esbox.scratchbox.sb1"
             version="17">
       </preferenceSetProvider>
    </extension>
+   <extension
+         point="org.eclipse.ui.newWizards">
+      <wizard
+            canFinishEarly="false"
+            category="org.maemo.mica.common.ui.maemo_install_target_wizard"
+            class="org.maemo.esbox.internal.scratchbox.sb1.ui.wizard.NewScratchbox1SDKWizard"
+            hasPages="true"
+            icon="icons/full/obj16/build_target_container.png"
+            id="org.maemo.esbox.scratchbox.sb1.sdk_installer"
+            name="Install Scratchbox 1">
+      </wizard>
+      <wizard
+            canFinishEarly="false"
+            category="org.maemo.mica.common.ui.maemo_install_target_wizard"
+            class="org.maemo.esbox.internal.scratchbox.sb1.ui.wizard.NewScratchbox1TargetWizard"
+            hasPages="true"
+            icon="icons/full/obj16/build_target_icon.gif"
+            id="org.maemo.esbox.scratchbox.sb1.target_installer"
+            name="Add Targets for Scratchbox 1 ">
+      </wizard>
+   </extension>
 
 </plugin>

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/AbstractSB1Command.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/AbstractSB1Command.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/AbstractSB1Command.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -27,7 +27,6 @@
 	 */
 	public AbstractSB1Command(ICommandAbstractor commandAbstractor) {
 		super(commandAbstractor);
-		// TODO Auto-generated constructor stub
 	}
 
 	/*

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/CreateTargetCommand.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/CreateTargetCommand.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/CreateTargetCommand.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -16,6 +16,7 @@
 import org.maemo.esbox.scratchbox.core.command.ScratchboxInvalidParameterException;
 import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
 import org.maemo.mica.common.core.MicaException;
+import org.maemo.mica.common.core.sdk.SDKFactory;
 import org.maemo.mica.common.core.sdk.commands.ICommandAbstractor;
 
 import java.util.List;
@@ -52,6 +53,7 @@
 		Process process = createProcess(setupTargetCommand, null);
 		getInputFromProcessAndWait(process, false, 0);
 		sdk.refresh();
+		SDKFactory.getInstance().fireListeners();
 		return true;
 	}
 	
@@ -64,6 +66,7 @@
 		Process process = createProcess(setupTargetCommand, null);
 		getInputFromProcessAndWait(process, false, 0);
 		sdk.refresh();
+		SDKFactory.getInstance().fireListeners();
 		return true;
 	}
 	

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/GetCurrentTargetCommand.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/GetCurrentTargetCommand.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/GetCurrentTargetCommand.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -12,6 +12,11 @@
  *******************************************************************************/
 package org.maemo.esbox.internal.scratchbox.sb1.command;
 
+import org.eclipse.core.filesystem.EFS;
+import org.eclipse.core.filesystem.IFileInfo;
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
 import org.maemo.esbox.internal.scratchbox.sb1.core.SB1PreferenceConstants;
 import org.maemo.esbox.scratchbox.core.command.ScratchboxInvalidParameterException;
 import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
@@ -51,15 +56,27 @@
 		if (sdk.getCachedCurrentTarget() != null)
 			return sdk.getCachedCurrentTarget();
 
-		String currentTargetAction = commandAbstractor
-				.getPreferenceValue(SB1PreferenceConstants.SB1_CURRENT_ACT);
-		String currentTargetCommand = this
-				.replaceScratchboxConfigCommand(currentTargetAction);
+		String currentTarget;
 
-		Process process = createProcess(currentTargetCommand, null);
-
-		String currentTarget = getInputFromProcessAndWait(process, true, 0);
-
+		// try even more of a shortcut
+		IPath linkPath = sdk.getSDKRoot().append("targets/links/scratchbox.config");
+		IFileStore linkStore = sdk.getMachineFileSystemAccess().getFileStore(linkPath);
+		IFileInfo info = linkStore.fetchInfo();
+		String target = info.getStringAttribute(EFS.ATTRIBUTE_LINK_TARGET);
+		if (target != null) {
+			currentTarget = new Path(target).removeFileExtension().lastSegment();
+		} else {
+			// do it the long way
+			String currentTargetAction = commandAbstractor
+					.getPreferenceValue(SB1PreferenceConstants.SB1_CURRENT_ACT);
+			String currentTargetCommand = this
+					.replaceScratchboxConfigCommand(currentTargetAction);
+	
+			Process process = createProcess(currentTargetCommand, null);
+	
+			currentTarget = getInputFromProcessAndWait(process, true, 0);
+		}
+		
 		sdk.setCachedCurrentTarget(currentTarget);
 		return currentTarget;
 	}

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/GetVersionScratchboxCommand.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/GetVersionScratchboxCommand.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/GetVersionScratchboxCommand.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -38,7 +38,6 @@
 	 * embedded.core.scratchbox.command.ScratchboxCommand#getParametersSize()
 	 */
 	public int getParametersSize() {
-		// TODO Auto-generated method stub
 		return 0;
 	}
 
@@ -63,9 +62,12 @@
 
 		Process process = createProcess(currentSboxVersionCommand, null);
 
-		String currentVersion = getInputFromProcessAndWait(process, true, 0);
-
-		return currentVersion;
+		// note: in a new installation, there will be some lines of text before the version
+		List<String> lines = getLineInputFromProcessAndWait(process, true, 0);
+		if (lines.size() > 0)
+			return lines.get(lines.size() - 1);
+		else
+			return "";
 	}
 
 }

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/RemoveTargetCommand.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/RemoveTargetCommand.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/command/RemoveTargetCommand.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -17,6 +17,7 @@
 import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.sdk.ISDK;
+import org.maemo.mica.common.core.sdk.SDKFactory;
 import org.maemo.mica.common.core.sdk.commands.ICommandAbstractor;
 
 import java.util.ArrayList;
@@ -67,6 +68,7 @@
 		getInputFromProcessAndWait(process, true, 0);
 
 		sdk.refresh();
+		SDKFactory.getInstance().fireListeners();
 
 		return true;
 	}

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/SB1PreferenceConstants.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/SB1PreferenceConstants.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/SB1PreferenceConstants.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -22,7 +22,7 @@
  * 
  */
 public class SB1PreferenceConstants {
-	public static final int VERSION_MAJOR = 17;
+	public static final int VERSION_MAJOR = 18;
 	public static final int VERSION_MINOR = 0;
 
 	/** Get the preference store that contains these preferences */
@@ -31,9 +31,6 @@
 	}
 
 	/* SB1 configuration options */
-
-	public static final String RUN_SCRIPT_LOC = "RUN_SCRIPT_LOC";
-
 	public static final String SB1_GDB_REMOTE_QEMU = "SB1_GDB_REMOTE_QEMU";
 	public static final String SB1_CURRENT_ACT = "SB1_CURRENT_ACT";
 	public static final String SB1_SBOX_COMMAND = "SB1_SBOX_COMMAND";
@@ -58,7 +55,6 @@
 	public static final String SB1_LIST_OPT_SESSIONS = "SB1_LIST_OPT_SESSIONS";
 	public static final String SB1_LIST_OPT_TARGETS = "SB1_LIST_OPT_TARGETS";
 	public static final String SB1_LOGIN_COMMAND = "SB1_LOGIN_COMMAND";
-	public static final String SB1_SBOX_SANDBOX = "SB1_SBOX_SANDBOX";
 	public static final String SB1_SELECT_ACT = "SB1_SELECT_ACT";
 	public static final String SB1_SETUP_ACT = "SB1_SETUP_ACT";
 	public static final String SB1_SETUP_OPT_COMPILER = "SB1_SETUP_OPT_COMPILER";
@@ -73,4 +69,11 @@
 	public static final String SB1_SHOW_OPT_CPU = "SB1_SHOW_OPT_CPU";
 	public static final String SB1_SHOW_OPT_DEVKITS = "SB1_SHOW_OPT_DEVKITS";
 	public static final String SB1_VERSION_ACT = "SB1_VERSION_ACT";
+
+	/** This option is still stored in prefs but is not exposed to the user directly anymore 
+	 * @see #SB1_ROOT */
+	public static final String SB1_SBOX_SANDBOX = "SB1_SBOX_SANDBOX";
+	/** All the installed roots of Scratchbox 1 (e.g. /scratchbox:/opt/scratchbox) */
+	public static final String SB1_ROOTS = "SB1_ROOTS";
+
 }

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/SB1PreferenceMigrator.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/SB1PreferenceMigrator.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/SB1PreferenceMigrator.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.core;
+
+import java.util.Properties;
+
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.maemo.mica.common.core.IPreferenceMigrator;
+import org.maemo.mica.internal.api.common.core.OldESboxPreferenceMigrator;
+
+/**
+ * Convert prefs from older SB1 settings
+ * @author eswartz
+ *
+ */
+public class SB1PreferenceMigrator extends OldESboxPreferenceMigrator implements
+		IPreferenceMigrator {
+
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.internal.api.common.core.OldESboxPreferenceMigrator#adjustDefaultSettings(java.util.Properties)
+	 */
+	@Override
+	public void adjustDefaultSettings(Properties newPropertyDefaults) {
+		super.adjustDefaultSettings(newPropertyDefaults);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.internal.api.common.core.OldESboxPreferenceMigrator#convertExistingPreferences(org.eclipse.jface.preference.IPreferenceStore, int, java.util.Properties, java.util.Properties)
+	 */
+	@Override
+	public void convertExistingPreferences(IPreferenceStore preferences,
+			int oldMajor, Properties existingSettings,
+			Properties newPropertyDefaults) {
+		if (oldMajor < 17) {
+			super.convertExistingPreferences(preferences, oldMajor, existingSettings,
+					newPropertyDefaults);
+		}
+		if (oldMajor < 18) {
+			// moved SB1_SBOX_SANDBOX and RUN_SCRIPT_LOCATION into SB1_ROOT and SB1_USER
+			String sandbox = newPropertyDefaults.getProperty("SB1_SBOX_SANDBOX");
+			String root = null;
+			
+			// remove anything after "scratchbox" (usually "/users/${USER}")
+			if (sandbox != null) {
+				int idx = sandbox.lastIndexOf("scratchbox");
+				if (idx >= 0)
+					root = sandbox.substring(0, idx + "scratchbox".length());
+			} 
+			if (root != null) {
+				newPropertyDefaults.put(SB1PreferenceConstants.SB1_ROOTS, root);
+			}
+			
+			newPropertyDefaults.remove("SB1_SBOX_SANDBOX");
+			newPropertyDefaults.remove("RUN_SCRIPT_LOCATION");
+		}
+	}
+}

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1FileSystemMapping.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1FileSystemMapping.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1FileSystemMapping.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -33,11 +33,11 @@
 	 * Construct with default Linux path canonicalizers and add mappings for
 	 * paths known to be mapped.
 	 * 
-	 * @param targetRoot
-	 * @param target
+	 * @param scratchboxRoot e.g. /scratchbox/
+	 * @param scratchboxBase e.g. /scratchbox/users/maemo/
+	 * @param target name of target, e.g. DIABLO_ARMEL
 	 */
-	public Scratchbox1FileSystemMapping(IPath scratchboxBase, String target,
-			String user) {
+	public Scratchbox1FileSystemMapping(IPath scratchboxRoot, IPath scratchboxBase, String target) {
 
 		super(FileSystemMapping.getMachineCanonicalizer(true),
 				FileSystemMapping.getMachineCanonicalizer(true));
@@ -47,7 +47,7 @@
 
 		// directories that are the same for all targets
 		String[] topLevelDirs = { "dev", "home", "host_usr", "proc",
-				"scratchbox", "sys", "targets" };
+				"sys", "targets" };
 
 		IPath sharedBase = scratchboxBase;
 		map(mappings, sharedBase, new Path("/"));
@@ -55,7 +55,10 @@
 			map(mappings, sharedBase.append(topLevelDir), new Path(topLevelDir)
 					.makeAbsolute());
 		}
-
+
+		// directory that depends on the SDK -- no matter where on the host, the target side is the same
+		map(mappings, scratchboxRoot, new Path("/scratchbox"));
+		
 		// directories that depend on the current target
 		String[] topLevelLinks = { "bin", "boot", "cdrom", "etc", "floppy",
 				"initrd", "lib", "media", "mnt", "opt", "root", "sbin", "srv",

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1SDK.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1SDK.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1SDK.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -10,12 +10,24 @@
  *******************************************************************************/
 package org.maemo.esbox.internal.scratchbox.sb1.core;
 
+import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.NullProgressMonitor;
 import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.maemo.esbox.internal.api.maemosdk.core.tools.IMaemoLauncherAdapter;
+import org.maemo.esbox.internal.api.maemosdk.core.tools.XLauncher;
 import org.maemo.esbox.internal.api.scratchbox.core.sdk.AbstractScratchboxSDK;
 import org.maemo.esbox.internal.api.scratchbox.core.sdk.CacheUtils;
 import org.maemo.esbox.internal.scratchbox.sb1.Activator;
@@ -30,43 +42,53 @@
 import org.maemo.esbox.internal.scratchbox.sb1.command.ListTargetsCommand;
 import org.maemo.esbox.internal.scratchbox.sb1.command.RemoveTargetCommand;
 import org.maemo.esbox.internal.scratchbox.sb1.command.SelectTargetCommand;
+import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
 import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDKTarget;
 import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
+import org.maemo.mica.common.core.IProgressReporter;
 import org.maemo.mica.common.core.MicaException;
+import org.maemo.mica.common.core.ProgressReporterStreamTextMonitor;
 import org.maemo.mica.common.core.machine.IMachine;
+import org.maemo.mica.common.core.machine.IMountPoint;
 import org.maemo.mica.common.core.machine.MachineUtils;
+import org.maemo.mica.common.core.process.CommandLineArguments;
+import org.maemo.mica.common.core.process.IProcessLauncher;
+import org.maemo.mica.common.core.process.IStreamMonitor;
+import org.maemo.mica.common.core.process.ProcessLauncherCreator;
+import org.maemo.mica.common.core.process.ProcessLauncherUtils;
 import org.maemo.mica.common.core.sdk.IPreferenceProvider;
 import org.maemo.mica.common.core.sdk.ISDKPlatform;
 import org.maemo.mica.common.core.sdk.ISDKTarget;
 import org.maemo.mica.common.core.sdk.commands.ICommandAbstractor;
 import org.maemo.mica.internal.api.common.core.sdk.BaseSDKPlatform;
+import org.maemo.mica.maemosdk.core.MaemoSDKPlatform;
 import org.maemo.mica.maemosdk.core.MaemoSDKPlatformEngine;
-import org.maemo.mica.maemosdk.core.MaemoSDKPlatform;
 
 public class Scratchbox1SDK extends AbstractScratchboxSDK implements
 		IScratchbox1SDK {
 
 	private IPath sdkRoot;
-	/** String for URI of machine where we detected scratchbox 1 */
-	static final String SB1_MACHINE = "sb1_machine";
-	/** String for scratchbox 1 version or <code>null</code> */
-	static final String SB1_VERSION = "sb1_version";
+	private List<String> cachedCompilers;
+	private List<String> cachedDevkits;
 
-	public Scratchbox1SDK(IMachine machine, String version,
+	public Scratchbox1SDK(IMachine machine, IPath installLocation, 
+			String version,
 			IPreferenceProvider prefProvider) {
-		super(machine, version, IScratchbox1SDK.NAME, "sb1_machine",
-				"sb1_version", "sb1_targets", 1);
+		super(machine, installLocation, version, 
+				IScratchbox1SDK.NAME + " (" + installLocation.removeTrailingSeparator().toPortableString() + ")", 
+				"sb1_machine:" + installLocation.toPortableString(),
+				"sb1_version:" + installLocation.toPortableString(), 
+				"sb1_targets:" + installLocation.toPortableString(), 
+				1);
 		this.sdkRoot = null;
 		this.prefProvider = prefProvider;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.maemo.mica.maemosdk.core.sdk.AbstractScratchboxSDK#refresh()
+	/* (non-Javadoc)
+	 * @see org.maemo.esbox.internal.api.scratchbox.core.sdk.AbstractScratchboxSDK#init()
 	 */
-	public void refresh() {
-		super.refresh();
+	public void init() {
+		super.init();
 		try {
 			List<String> targetNames = getTargets();
 			List<ISDKTarget> newTargets = new ArrayList<ISDKTarget>();
@@ -84,6 +106,15 @@
 		}
 	}
 
+	/* (non-Javadoc)
+	 * @see org.maemo.esbox.internal.api.scratchbox.core.sdk.AbstractScratchboxSDK#refresh()
+	 */
+	public void refresh() {
+		super.refresh();
+		cachedCompilers = null;
+		cachedDevkits = null;
+	}
+
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -92,8 +123,8 @@
 	 * ()
 	 */
 	public ICommandAbstractor getCommandAbstractor() throws MicaException {
-		return getSb1WrappedAbstractor(super.getCommandAbstractor(), this
-				.getMachine());
+		return wrapCommandAbstractorForSDK(super.getCommandAbstractor(),
+				"sb-conf", getInstallRoot().append("tools/bin").toPortableString());
 	}
 
 	/*
@@ -129,7 +160,7 @@
 		CreateTargetCommand createTargetCommand = new CreateTargetCommand(this,
 				getCommandAbstractor());
 
-		CacheUtils.getInstance().setCachedValue(SB_TARGETS, null);
+		CacheUtils.getInstance().setCachedValue(sbTargetsKey, null);
 		if(force)
 			return (Boolean) createTargetCommand.forceCommand(params);
 		else
@@ -142,9 +173,12 @@
 	 * @see org.maemo.mica.maemosdk.core.sdk.IScratchboxSDK#getCompilers()
 	 */
 	public List<String> getCompilers() throws MicaException {
-		ListCompilersCommand listCompilersCommand = new ListCompilersCommand(
-				getCommandAbstractor());
-		return listCompilersCommand.performCommand(EMPTY_ARGS);
+		if (cachedCompilers == null || cachedCompilers.size() == 0) {
+			ListCompilersCommand listCompilersCommand = new ListCompilersCommand(
+					getCommandAbstractor());
+			cachedCompilers = listCompilersCommand.performCommand(EMPTY_ARGS);
+		}
+		return cachedCompilers;
 	}
 
 	/*
@@ -167,12 +201,12 @@
 	 *             if any problem related to Scratchbox communication occurs,
 	 *             including no scratchbox 1 detected
 	 */
-	public static String getCurrentSboxVersion(IMachine machine)
-			throws MicaException {
+	public String getCurrentSboxVersion() throws MicaException {
 		// find cached value
-		CacheUtils.getInstance().ensureCurrentMachine(SB1_MACHINE, machine);
-		String version = (String) CacheUtils.getInstance().getCachedValue(
-				SB1_VERSION);
+		IMachine machine = getMachine();
+		
+		CacheUtils.getInstance().ensureCurrentMachine(sbMachineKey, machine);
+		String version = (String) CacheUtils.getInstance().getCachedValue(sbVersionKey);
 		// empty string cached if we didn't detect it
 		if ("".equals(version))
 			return null;
@@ -181,11 +215,9 @@
 
 		// do the hard work
 		MachineUtils.acquireMachine(machine);
-		ICommandAbstractor commandAbstractor = MachineUtils
-				.getHostCommandAbstractor(machine);
-		commandAbstractor = getSb1WrappedAbstractor(commandAbstractor, machine);
+		
 		GetVersionScratchboxCommand getVersionCommand = new GetVersionScratchboxCommand(
-				commandAbstractor);
+				getCommandAbstractor());
 
 		String currentVersion;
 		MicaException exception = null;
@@ -198,7 +230,7 @@
 		}
 		
 		// remember cached value
-		CacheUtils.getInstance().setCachedValue(SB1_VERSION, currentVersion);
+		CacheUtils.getInstance().setCachedValue(sbVersionKey, currentVersion);
 
 		if (exception != null)
 			throw exception;
@@ -224,10 +256,10 @@
 	 * @see org.maemo.mica.maemosdk.core.sdk.IScratchboxSDK#getTargets()
 	 */
 	public List<String> getTargets() throws MicaException {
-		CacheUtils.getInstance().ensureCurrentMachine(SB_MACHINE, this.getMachine());
+		CacheUtils.getInstance().ensureCurrentMachine(sbMachineKey, this.getMachine());
 
 		String[] targetsArray = (String[]) CacheUtils.getInstance()
-				.getCachedValue(SB_TARGETS);
+				.getCachedValue(sbTargetsKey);
 		if (targetsArray != null)
 			return Arrays.asList(targetsArray);
 
@@ -236,7 +268,9 @@
 		List<String> targets = listTargetsCommand
 				.performCommand(new ArrayList<String>());
 
-		CacheUtils.getInstance().setCachedValue(SB_TARGETS,
+		Collections.sort(targets);
+		
+		CacheUtils.getInstance().setCachedValue(sbTargetsKey,
 				(String[]) targets.toArray(new String[targets.size()]));
 
 		return targets;
@@ -249,9 +283,8 @@
 	 */
 	public IPath getSDKRoot() {
 		if (sdkRoot == null) {
-			String userPath = prefProvider
-					.getPreferenceValue(SB1PreferenceConstants.SB1_SBOX_SANDBOX);
-			sdkRoot = new Path(userPath);
+			String userName = getMachine().getUserName();
+			sdkRoot = installLocation.append("users").append(userName);
 		}
 		return sdkRoot;
 	}
@@ -271,7 +304,7 @@
 
 		removeTargetCommand = new RemoveTargetCommand(this,
 				getCommandAbstractor());
-		CacheUtils.getInstance().setCachedValue(SB_TARGETS, null);
+		CacheUtils.getInstance().setCachedValue(sbTargetsKey, null);
 
 		return (Boolean) removeTargetCommand.performCommand(params);
 	}
@@ -282,9 +315,12 @@
 	 * @see org.maemo.mica.maemosdk.sb1.core.IScratchbox1SDK#getDevkits()
 	 */
 	public List<String> getDevkits() throws MicaException {
-		ListDevkitsCommand listDevkitsCommand = new ListDevkitsCommand(
-				getCommandAbstractor());
-		return listDevkitsCommand.performCommand(new ArrayList<String>());
+		if (cachedDevkits == null || cachedDevkits.size() == 0) {
+			ListDevkitsCommand listDevkitsCommand = new ListDevkitsCommand(
+					getCommandAbstractor());
+			cachedDevkits = listDevkitsCommand.performCommand(new ArrayList<String>());
+		}
+		return cachedDevkits;
 	}
 
 	/*
@@ -325,6 +361,81 @@
 		return (Boolean) killallCommand.performCommand(params);
 	}
 
+	/* (non-Javadoc)
+	 * @see org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK#killSessions()
+	 */
+	public void killSessions() throws MicaException {
+		final IScratchboxSDKTarget currentTarget = getCurrentSDKTarget();
+		
+		// see if maemo is running, since it needs to be killed to switch
+		// targets but isn't considered a "session" every time
+		IMaemoLauncherAdapter launcher = (IMaemoLauncherAdapter)currentTarget.getAdapter(IMaemoLauncherAdapter.class);
+		
+		if (launcher != null && launcher.isMaemoRunning()) {
+			// a target selection may succeed even if X and maemo are
+			// running... kill them first.
+			// We kill X too because some processes won't be killed by
+			// maemo-launcher.
+			try {
+				launcher.killMaemo();
+			} catch (MicaException e2) {
+				// ignore
+			}
+			try {
+				XLauncher.getInstance().stopX(currentTarget);
+			} catch (MicaException e2) {
+				// ignore
+			}
+		}
+
+		// now kill the scratchbox sessions the "approved" way
+		try {
+			this.killProcess();
+
+			// wait politely
+			try {
+				Thread.sleep(1000);
+			} catch (InterruptedException e1) {
+
+			}
+
+		} catch (ScratchboxException e2) {
+			// sb-conf killall can fail in the event there is some
+			// process with a space in its
+			// name... just log it and keep going
+			Activator.getErrorLogger().logError(
+					"Problem killing scratchbox sessions", e2);
+		}
+
+		// double-check, since it doesn't really work!
+		List<String> sessions = this.getSessions();
+		if (sessions.size() > 0) {
+			// forcibly kill processes
+			List<String> cmdLine = CommandLineArguments
+					.createFromVarArgs("kill", "-9");
+			cmdLine.addAll(sessions);
+
+			IProcessLauncher processLauncher = ProcessLauncherCreator
+					.createProcessLauncher(this
+							.getMachineProcessLauncherFactory(), null,
+							cmdLine);
+			Process process;
+			try {
+				process = processLauncher.createProcess();
+				process.waitFor();
+			} catch (final Exception e1) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						MessageDialog.openError(null, "Scratchbox Target Conflict",
+							MessageFormat.format(
+								"Couldn''t kill scratchbox processes:\n\n{0}\n\nRetrying the target selection anyway.",
+								e1.getLocalizedMessage()));
+					};
+				});
+			}
+		}
+	}
+	
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -383,18 +494,128 @@
 	}
 
 	/**
-	 * Get a command abstractor that updates the PATH if sb1 tools are not on
-	 * the path.
-	 * 
-	 * @param commandAbstractor
-	 * @param machine
-	 * @return
+	 * Start the Scratchbox installation (ensure its daemons are running and
+	 * its mounts are mounted).
+	 * <p>
+	 * This command may cause UI requests since it needs sudo permissions.
+	 * It does not have to be run on the UI thread, though.
+	 * @param monitor progress monitor for cancellation
+	 * @param reporter progress reporter for logging
+	 * @return IStatus of operation
 	 */
-	private static ICommandAbstractor getSb1WrappedAbstractor(
-			ICommandAbstractor commandAbstractor, IMachine machine) {
-		// XXX: the default path should be provided some other way
-		return wrapCommandAbstractorForSDK(commandAbstractor, machine,
-				"sb-conf", "/scratchbox/tools/bin");
+	public static IStatus startup(IMachine machine, IPath installLocation,
+			IProgressMonitor monitor, IProgressReporter reporter) {
+		if (monitor == null)
+			monitor = new NullProgressMonitor();
+		
+		monitor.beginTask("", 1);
+		
+		MultiStatus multiStatus = new MultiStatus(Activator.PLUGIN_ID, 0,
+				"Failed to start up Scratchbox 1", null);
+		
+		monitor.subTask("Starting Scratchbox daemons...");
+		
+		String sboxCtl = installLocation.append("sbin/sbox_ctl").toPortableString();
+		
+		// always restart, just to be sure
+		List<String> cmdLine = CommandLineArguments.createFromVarArgs(sboxCtl, "restart");
+		IProcessLauncher processLauncher = getRootProcessLauncher(machine, null, cmdLine, null);
+		IStreamMonitor sudoSniffer = getRootProcessMonitor(machine, cmdLine);
+		
+		if (machine.getFileSystemAccess().getFileStore(new Path(sboxCtl)).fetchInfo().exists()) {
+			try {
+				ProcessLauncherUtils.launchAndMonitorStandardStreams(processLauncher, 
+						new IStreamMonitor[] {
+							new ProgressReporterStreamTextMonitor(reporter),
+							sudoSniffer,
+						},
+						new SubProgressMonitor(monitor, 1));
+				if (monitor.isCanceled())
+					return Status.CANCEL_STATUS;
+			} catch (MicaException e) {
+				IStatus status = Activator.createErrorStatus("Failed to start Scratchbox 1 daemons", e);
+				reporter.log(status);
+				multiStatus.add(status);
+			}
+		}
+		
+		return multiStatus.isOK() ? Status.OK_STATUS : multiStatus;
 	}
 
+	/**
+	 * Stop the Scratchbox installation (ensure its daemons are stopped and
+	 * all its mounts are closed).
+	 * <p>
+	 * This command may cause UI requests since it needs sudo permissions.
+	 * It does not have to be run on the UI thread, though.
+	 * @param monitor progress monitor for cancellation
+	 * @param reporter progress reporter for logging
+	 * @return IStatus of operation
+	 */
+	public static IStatus shutdown(IMachine machine, IPath installLocation,
+			IProgressMonitor monitor, IProgressReporter reporter) {
+		if (monitor == null)
+			monitor = new NullProgressMonitor();
+		
+		monitor.beginTask("", 2);
+		monitor.subTask("Terminating Scratchbox 1 daemons...");
+			
+		String sboxCtl = installLocation.append("sbin/sbox_ctl").toPortableString();
+		List<String> cmdLine = CommandLineArguments.createFromVarArgs(sboxCtl, "stop");
+		IProcessLauncher processLauncher = getRootProcessLauncher(machine, null, cmdLine, null);
+		IStreamMonitor sudoSniffer = getRootProcessMonitor(machine, cmdLine);
+		
+		MultiStatus multiStatus = new MultiStatus(Activator.PLUGIN_ID, 0,
+				"Failed to shut down Scratchbox 1", null);
+		
+		if (machine.getFileSystemAccess().getFileStore(new Path(sboxCtl)).fetchInfo().exists()) {
+			try {
+				ProcessLauncherUtils.launchAndMonitorStandardStreams(processLauncher, 
+						new IStreamMonitor[] {
+							new ProgressReporterStreamTextMonitor(reporter),
+							sudoSniffer,
+						},
+						new SubProgressMonitor(monitor, 1));
+				if (monitor.isCanceled())
+					return Status.CANCEL_STATUS;
+			} catch (MicaException e) {
+				IStatus status = Activator.createErrorStatus("Failed to turn off Scratchbox 1 daemon", e);
+				reporter.log(status);
+				multiStatus.add(status);
+			}
+		}
+		
+		// now, double-check and unmount any directories on the install location
+		monitor.subTask("Unmounting directories inside Scratchbox 1...");
+		
+		cmdLine = CommandLineArguments.createFromVarArgs("umount");
+		IMountPoint[] mounts = machine.getFileSystemAccess().getMounts();
+		for (IMountPoint mount : mounts) {
+			if (installLocation.isPrefixOf(mount.getPath())) {
+				cmdLine.add(mount.getPath().toPortableString());
+			}
+		}
+		if (cmdLine.size() > 1) {
+			processLauncher = getRootProcessLauncher(machine, null, cmdLine, null);
+			sudoSniffer = getRootProcessMonitor(machine, cmdLine);
+			
+			try {
+				ProcessLauncherUtils.launchAndMonitorStandardStreams(processLauncher, 
+						new IStreamMonitor[] {
+							new ProgressReporterStreamTextMonitor(reporter),
+							sudoSniffer,
+						},
+						new SubProgressMonitor(monitor, 1));
+				if (monitor.isCanceled())
+					return Status.CANCEL_STATUS;
+			} catch (MicaException e) {
+				IStatus status = Activator.createErrorStatus("Failed to unmount directories inside Scratchbox 1", e);
+				reporter.log(status);
+				multiStatus.add(status);
+			}
+		}
+		
+		return multiStatus.isOK() ? Status.OK_STATUS : multiStatus;
+	}
+
 }

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1SDKTarget.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1SDKTarget.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/core/Scratchbox1SDKTarget.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *    Petr Baranov (Nokia) - initial API and implementation
+ *    Ed Swartz (Nokia) - maintenance
  *******************************************************************************/
 package org.maemo.esbox.internal.scratchbox.sb1.core;
 
@@ -18,7 +19,6 @@
 import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxTarget;
 import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
 import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDKTarget;
-import org.maemo.mica.common.core.CorePreferenceConstants;
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.process.IProcessLauncherFactory;
 import org.maemo.mica.common.core.sdk.ISDKPlatform;
@@ -31,6 +31,7 @@
  * SDK target for Scratchbox 1
  * 
  * @author baranov
+ * @author eswartz
  * 
  */
 public class Scratchbox1SDKTarget extends AbstractScratchboxSDKTarget implements
@@ -43,8 +44,7 @@
 			String architecture, String target, IPath targetRoot) {
 		super(sdk, platform, architecture, target);
 		this.targetRoot = targetRoot;
-		init(new Scratchbox1FileSystemMapping(sdk.getSDKRoot(), target, sdk
-				.getPreferenceValue(CorePreferenceConstants.USER)));
+		init(new Scratchbox1FileSystemMapping(sdk.getInstallRoot(), sdk.getSDKRoot(), target));
 	}
 
 	/*
@@ -77,6 +77,17 @@
 		return new Scratchbox1ProcessLauncherFactory(this, false);
 	}
 
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.core.sdk.ISDKTarget#getProcessLauncherFactory(java.lang.String)
+	 */
+	public IProcessLauncherFactory getProcessLauncherFactory(String userName) {
+		if (userName.equals("root")) {
+			return new Scratchbox1ProcessLauncherFactory(this, true);
+		}
+		// no support for alternate users in Scratchbox 
+		return null;
+	}
+	
 	/*
 	 * (non-Javadoc)
 	 * 

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher/Scratchbox1PrepareTargetProcessLaunchAdapter.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher/Scratchbox1PrepareTargetProcessLaunchAdapter.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher/Scratchbox1PrepareTargetProcessLaunchAdapter.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -12,26 +12,19 @@
 package org.maemo.esbox.internal.scratchbox.sb1.launcher;
 
 import java.text.MessageFormat;
-import java.util.List;
 
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.swt.widgets.Display;
-import org.maemo.esbox.internal.api.maemosdk.core.tools.IMaemoLauncherAdapter;
-import org.maemo.esbox.internal.api.maemosdk.core.tools.XLauncher;
-import org.maemo.esbox.internal.scratchbox.sb1.Activator;
 import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
 import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
 import org.maemo.mica.common.core.GeneralUtils;
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.adapters.IPrepareTargetProcessLaunchAdapter;
-import org.maemo.mica.common.core.process.CommandLineArguments;
-import org.maemo.mica.common.core.process.IProcessLauncher;
-import org.maemo.mica.common.core.process.ProcessLauncherCreator;
 import org.maemo.mica.common.core.sdk.ISDKTarget;
 
 /**
- * Utility class to handle switching scratchbox targets and get user approval to
- * kill existing sessions if needed.
+ * This adapter handles the launch of processes for a particular SB1 target, taking
+ * care to switching scratchbox targets and get user approval to kill existing sessions if needed.
  * 
  * @author eswartz
  * 
@@ -51,14 +44,6 @@
 			return;
 		}
 
-		// see if maemo is running, since it needs to be killed to switch
-		// targets
-		// but isn't considered a "session" every time
-		IMaemoLauncherAdapter launcher = (IMaemoLauncherAdapter)sdkTarget.getAdapter(IMaemoLauncherAdapter.class);
-		if(launcher == null){
-			throw new MicaException("Cannot find IMaemoLauncherAdapter for " + sdkTarget);
-		}
-
 		// now try to switch and see if shells are open
 		boolean failedToSwitch = false;
 		try {
@@ -75,7 +60,7 @@
 			}
 		}
 
-		if (launcher.isMaemoRunning() || failedToSwitch) {
+		if (failedToSwitch || !sdk.getCurrentTarget().equals(targetName)) {
 			final boolean[] ret = { false };
 
 			if (!GeneralUtils.isJUnitRunning()) {
@@ -96,74 +81,11 @@
 
 			// if user accepts, kill existing ones
 			if (ret[0]) {
-				if (launcher.isMaemoRunning()) {
-					// a target selection may succeed even if X and maemo are
-					// running... kill them first.
-					// We kill X too because some processes won't be killed by
-					// maemo-launcher.
-					try {
-						launcher.killMaemo();
-					} catch (MicaException e2) {
-						// ignore
-					}
-					try {
-						XLauncher.getInstance().stopX(sdkTarget);
-					} catch (MicaException e2) {
-						// ignore
-					}
-				}
-
-				// now kill the scratchbox sessions the "approved" way
-				try {
-					sdk.killProcess();
-
-					// wait politely
-					try {
-						Thread.sleep(1000);
-					} catch (InterruptedException e1) {
-
-					}
-
-				} catch (ScratchboxException e2) {
-					// sb-conf killall can fail in the event there is some
-					// process with a space in its
-					// name... just log it and keep going
-					Activator.getErrorLogger().logError(
-							"Problem killing scratchbox sessions", e2);
-				}
-
-				// double-check, since it doesn't really work!
-				List<String> sessions = sdk.getSessions();
-				if (sessions.size() > 0) {
-					// forcibly kill processes
-					List<String> cmdLine = CommandLineArguments
-							.createFromVarArgs("kill", "-9");
-					cmdLine.addAll(sessions);
-
-					IProcessLauncher processLauncher = ProcessLauncherCreator
-							.createProcessLauncher(sdk
-									.getMachineProcessLauncherFactory(), null,
-									cmdLine);
-					Process process;
-					try {
-						process = processLauncher.createProcess();
-						process.waitFor();
-					} catch (final Exception e1) {
-						Display.getDefault().syncExec(new Runnable() {
-							public void run() {
-								MessageDialog.openError(null, "Scratchbox Target Conflict",
-									MessageFormat.format(
-										"Couldn''t kill scratchbox processes:\n\n{0}\n\nRetrying the target selection anyway.",
-										e1.getLocalizedMessage()));
-							};
-						});
-					}
-				}
-
+				sdk.killSessions();
+	
+				// always retry, and rethrow if fails
+				sdk.selectTarget(targetName);
 			}
-
-			// always retry, and rethrow if fails
-			sdk.selectTarget(targetName);
 		}
 	}
 }

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher/Scratchbox1ProcessLauncher.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher/Scratchbox1ProcessLauncher.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/launcher/Scratchbox1ProcessLauncher.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -13,6 +13,7 @@
 import org.eclipse.core.runtime.*;
 import org.maemo.esbox.internal.scratchbox.sb1.Activator;
 import org.maemo.esbox.internal.scratchbox.sb1.core.SB1PreferenceConstants;
+import org.maemo.esbox.internal.scratchbox.sb1.core.Scratchbox1SDK;
 import org.maemo.mica.common.core.GeneralUtils;
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.env.IEnvironmentModifierBlock;
@@ -77,11 +78,6 @@
 			IPath workingDirectory, List<String> cmdLine,
 			IEnvironmentModifierBlock environmentModifierBlock) {
 
-		// get the location where the launcher script will be copied on the
-		// target
-		String runScriptLocation = sdkTarget
-				.getPreferenceValue(SB1PreferenceConstants.RUN_SCRIPT_LOC);
-
 		// encode working directory inside scratchbox
 		if (workingDirectory == null) {
 			workingDirectory = new Path("/");
@@ -94,10 +90,15 @@
 		//
 		ShellTemplateSubstitutor substitutor = new ShellTemplateSubstitutor();
 
-		substitutor.define("RUN_SCRIPT_DIRECTORY", runScriptLocation);
+		substitutor.define("SBOX_ROOT", ((Scratchbox1SDK) sdkTarget.getSDK()).getInstallRoot().removeTrailingSeparator().toPortableString());
+		IPath targetRunScriptPath = sdkTarget.getMachineToSDKTargetFileSystemMapping().convertHostToTargetPath(getRunScriptLocation(sdkTarget));
+		// it better not be null
+		substitutor.define("RUN_SCRIPT_DIRECTORY", targetRunScriptPath.toPortableString());
 		substitutor.define("RUN_SCRIPT", RUN_SCRIPT_NAME);
 		substitutor.define("DIRECTORY", workingDirectory.toPortableString());
 
+		// this weird string is used for argument encoding since it's unlikely
+		// to appear in normal environment variables and doesn't need to be escaped
 		String exportsString = CommandLineArguments.toString(envArgs,
 				"}", false); //$NON-NLS-1$
 
@@ -119,6 +120,22 @@
 	}
 
 	/**
+	 * Get the location where the run script should be copied (on the host), so that it
+	 * is visible to the target.
+	 * @param sdkTarget
+	 * @return
+	 */
+	private static IPath getRunScriptLocation(ISDKTarget sdkTarget) {
+		IPath home = sdkTarget.getMachineToSDKTargetFileSystemMapping().
+				convertTargetToHostPath(sdkTarget.getMachine().getUserHome());
+		if (home == null) {
+			home = sdkTarget.getSDKTargetRoot();
+		}
+		IPath loc = home.append(".esbox");
+		return loc;
+	}
+
+	/**
 	 * Encode the add/replace and delete operations to run.sh
 	 * 
 	 * @param environmentModifierBlock
@@ -143,6 +160,9 @@
 		return mods;
 	}
 
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.core.process.BaseSDKTargetProcessLauncher#setupForLaunch()
+	 */
 	@Override
 	protected void setupForLaunch() throws MicaException {
 		super.setupForLaunch();
@@ -151,16 +171,16 @@
 		// /scratchbox/login doesn't pass environment variables the way we need to.
 		// Thus, we need to run under scratchbox a script which itself sets those
 		// variables.
-
 		GeneralUtils.cachedCopyScriptToMachine(
 				FileLocator.find(Activator.getDefault().getBundle(), 
 						new Path("conf/" + RUN_SCRIPT_NAME),
 						null),
 				sdkTarget.getMachine(),
-				new Path(sdkTarget.getPreferenceValue(SB1PreferenceConstants.RUN_SCRIPT_LOC)),
-				false);
+				getRunScriptLocation(sdkTarget),
+				false,
+				null);
 	}
-
+	
 	/*
 	 * (non-Javadoc)
 	 * 

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/provider/Scratchbox1SDKProvider.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/provider/Scratchbox1SDKProvider.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/provider/Scratchbox1SDKProvider.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -11,33 +11,37 @@
  *******************************************************************************/
 package org.maemo.esbox.internal.scratchbox.sb1.provider;
 
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
 import org.maemo.esbox.internal.api.scratchbox.core.sdk.CacheUtils;
 import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.esbox.internal.scratchbox.sb1.core.SB1PreferenceConstants;
 import org.maemo.esbox.internal.scratchbox.sb1.core.Scratchbox1SDK;
-import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
-import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK;
-import org.maemo.mica.common.core.*;
+import org.maemo.mica.common.core.CorePreferenceManager;
+import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.machine.IMachine;
 import org.maemo.mica.common.core.machine.MachineRegistry;
-import org.maemo.mica.common.core.sdk.*;
+import org.maemo.mica.common.core.sdk.IPreferenceProvider;
+import org.maemo.mica.common.core.sdk.ISDK;
+import org.maemo.mica.common.core.sdk.ISDKProvider;
 import org.maemo.mica.internal.api.common.core.sdk.UserAwarePreferenceProviderWrapper;
 
-import java.text.MessageFormat;
-import java.util.ArrayList;
-import java.util.List;
-
 /**
- * This implementation of the SDK provider searches for SB1 targets using the
- * 'sb-conf list --targets' command. If any aspect of SB1 communication fails,
- * we assume SB1 is not installed.
+ * This implementation of the SDK provider allows for multiple SB1 installations
+ * along the SB1_ROOTS preference path.  
  * 
  * @author eswartz
  * 
  */
 public class Scratchbox1SDKProvider implements ISDKProvider {
 
-	// only 1.0.x+ supported right now
 	private static final String SCRATCHBOX_VERSION_PATTERN = "1\\.\\d+\\..*"; //$NON-NLS-1$
 
 	/**
@@ -52,59 +56,76 @@
 	 * @see org.maemo.mica.common.core.sdk.ISDKProvider#createSDKs()
 	 */
 	public List<ISDK> createSDKs() throws MicaException {
-		ErrorLogger logger = Activator.getErrorLogger();
-
 		List<ISDK> sdks = new ArrayList<ISDK>();
 		for (IMachine machine : MachineRegistry.getInstance()
 				.getBuildMachines()) {
+			IPreferenceProvider prefProvider = new UserAwarePreferenceProviderWrapper(
+					CorePreferenceManager.getInstance()
+							.getPreferenceProvider(), machine);
+			getMachineSDKs(prefProvider, machine, sdks);
+		}
+		CacheUtils.getInstance().saveCachedData();
+		
+		Collections.sort(sdks, new Comparator<ISDK>() {
+
+			public int compare(ISDK o1, ISDK o2) {
+				return o1.getName().compareTo(o2.getName());
+			}
+			
+		});
+		
+		return sdks;
+	}
+
+	/**
+	 * Gather all the SB1 installations on the machine.
+	 * @param prefProvider
+	 * @throws MicaException
+	 */
+	private void getMachineSDKs(IPreferenceProvider prefProvider,
+			IMachine machine, List<ISDK> sdks) {
+		
+		String[] paths = prefProvider.getPreferenceValue(SB1PreferenceConstants.SB1_ROOTS).split(":");
+		for (String path: paths) {
 			try {
-				IPreferenceProvider prefProvider = new UserAwarePreferenceProviderWrapper(
-						CorePreferenceManager.getInstance()
-								.getPreferenceProvider(), machine);
-				IScratchboxSDK sdk = getMachineSDKs(prefProvider, machine);
-				if (sdk != null) {
-					sdks.add(sdk);
-					sdk.refresh();
-				}
-			} catch (ScratchboxException e) {
-				logger.log(IStatus.INFO,
+				getScratchboxSDK(prefProvider, machine, new Path(path), sdks);
+			} catch (MicaException e) {
+				Activator.getErrorLogger().log(IStatus.INFO,
 						"Problem scanning Scratchbox 1 installation", e);
 			}
 		}
-		CacheUtils.getInstance().saveCachedData();
-		return sdks;
 	}
 
 	/**
+	 * Validate one installation at the given path.
 	 * @param prefProvider
-	 * @return
-	 * @throws ScratchboxException
+	 * @param machine
+	 * @param installPath
+	 * @param sdks
 	 */
-	private IScratchboxSDK getMachineSDKs(IPreferenceProvider prefProvider,
-			IMachine machine) throws MicaException {
-		ErrorLogger logger = Activator.getErrorLogger();
+	private void getScratchboxSDK(IPreferenceProvider prefProvider,
+			IMachine machine, IPath installPath, List<ISDK> sdks) throws MicaException {
 
-		// only support one Scratchbox 1.x installation
-		String version = Scratchbox1SDK.getCurrentSboxVersion(machine);
+		Scratchbox1SDK sdk = new Scratchbox1SDK(machine, installPath.addTrailingSeparator(), 
+				null, prefProvider);
+		String version = sdk.getCurrentSboxVersion();
 		
 		if (version == null) {
 			// no scratchbox?
-			return null;
+			return;
 		}
 
 		if (!version.matches(SCRATCHBOX_VERSION_PATTERN)) {
-			logger
-					.logError(
-							MessageFormat
-									.format(
-											"Only Scratchbox 1.x is supported (detected {0}); disabling Scratchbox 1 support",
-											version), null);
-			return null;
+			Activator.getErrorLogger().logError(MessageFormat.format(
+				"Only Scratchbox 1.x is supported (detected {0}); disabling Scratchbox 1 support",
+				version), null);
+			return;
 		}
 
-		IScratchboxSDK sdk = new Scratchbox1SDK(machine, version, prefProvider);
-
-		return sdk;
+		sdk.setVersion(version);
+		
+		sdk.init();
+		sdks.add(sdk);
+		
 	}
-
 }

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters/MaemoScratchbox1SDKManageTargetAdapter.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters/MaemoScratchbox1SDKManageTargetAdapter.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters/MaemoScratchbox1SDKManageTargetAdapter.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -12,60 +12,29 @@
 
 package org.maemo.esbox.internal.scratchbox.sb1.ui.adapters;
 
-import org.eclipse.core.runtime.*;
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.wizard.WizardDialog;
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.swt.widgets.Shell;
 import org.maemo.esbox.internal.api.scratchbox.ui.adapters.MaemoScratchboxSDKManageTargetAdapterBase;
-import org.maemo.esbox.internal.scratchbox.sb1.Activator;
 import org.maemo.esbox.internal.scratchbox.sb1.core.Scratchbox1SDK;
-import org.maemo.esbox.internal.scratchbox.sb1.ui.wizard.NewScratchbox1TargetWizard;
 import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK;
 import org.maemo.mica.common.core.MicaException;
-import org.maemo.mica.common.core.Policy;
-import org.maemo.mica.common.core.adapters.ISDKManageTargetAdapter;
 import org.maemo.mica.common.core.sdk.ISDK;
 import org.maemo.mica.common.core.sdk.ISDKTarget;
 import org.maemo.mica.internal.api.maemosdk.ui.adapters.MaemoTargetRemover;
 
-import java.util.List;
-
 /**
  * @author eswartz
  * 
  */
-public class MaemoScratchbox1SDKManageTargetAdapter extends
-		MaemoScratchboxSDKManageTargetAdapterBase implements
-		ISDKManageTargetAdapter {
-
-	private Scratchbox1SDK sdk;
-
+public class MaemoScratchbox1SDKManageTargetAdapter extends MaemoScratchboxSDKManageTargetAdapterBase {
+	Scratchbox1SDK sdk;
+	
 	/**
 	 * @param adaptableObject
 	 */
 	public MaemoScratchbox1SDKManageTargetAdapter(Scratchbox1SDK sdk) {
 		this.sdk = sdk;
 	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.maemo.mica.common.core.adapters.ISDKManageTargetAdapter#installSDKTargets
-	 * (org.eclipse.swt.widgets.Shell, java.util.List)
-	 */
-	public IStatus installSDKTargets(Shell shell, List<ISDKTarget> installed) {
-		NewScratchbox1TargetWizard targetWizard;
-
-		targetWizard = new NewScratchbox1TargetWizard(sdk);
-		WizardDialog dlg = new WizardDialog(shell, targetWizard);
-		if (dlg.open() == Dialog.OK) {
-			return Status.OK_STATUS;
-		}
-
-		return Policy.getCancelStatus(Activator.getDefault());
-	}
-
 	
 	/*
 	 * (non-Javadoc)

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters/MaemoScratchbox1SDKManageTargetAdapterFactory.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters/MaemoScratchbox1SDKManageTargetAdapterFactory.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/adapters/MaemoScratchbox1SDKManageTargetAdapterFactory.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -19,7 +19,6 @@
  * @author eswartz
  * 
  */
- at SuppressWarnings("unchecked")
 public class MaemoScratchbox1SDKManageTargetAdapterFactory implements IAdapterFactory {
 
 	/*

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/preferences/Scratchbox1PreferencesPage.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/preferences/Scratchbox1PreferencesPage.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/preferences/Scratchbox1PreferencesPage.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -11,7 +11,8 @@
 
 package org.maemo.esbox.internal.scratchbox.sb1.ui.preferences;
 
-import org.eclipse.jface.preference.*;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.StringFieldEditor;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.events.ModifyEvent;
 import org.eclipse.swt.events.ModifyListener;
@@ -21,12 +22,7 @@
 import org.eclipse.ui.IWorkbenchPreferencePage;
 import org.maemo.esbox.internal.scratchbox.sb1.IHelpID;
 import org.maemo.esbox.internal.scratchbox.sb1.core.SB1PreferenceConstants;
-import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
-import org.maemo.esbox.scratchbox.core.sdk.IScratchboxSDK;
-import org.maemo.esbox.scratchbox.core.sdk.ScratchboxSDKFacade;
-import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
 import org.maemo.mica.common.core.GeneralUtils;
-import org.maemo.mica.common.core.machine.ILocalMachine;
 import org.maemo.mica.common.core.sdk.SDKFactory;
 
 /**
@@ -37,18 +33,11 @@
 public class Scratchbox1PreferencesPage extends FieldEditorPreferencePage
 		implements IWorkbenchPreferencePage {
 
-	/**
-	 * Field for sandbox root
-	 */
-	private DirectoryFieldEditor feSandboxRoot = null;
-	private StringFieldEditor feSandboxRootStr = null;
-
-	/**
-	 * Field for run scratchbox commands
-	 */
+	private StringFieldEditor feRootStr = null;
 	private StringFieldEditor feSboxCommands = null;
+	
 	protected boolean sdksChanged;
-	private String origSandboxRoot;
+	private String origRoots;
 
 	// private StringFieldEditor feGdbQemuCommand;
 
@@ -59,8 +48,7 @@
 		super(GRID);
 		setPreferenceStore(SB1PreferenceConstants.getPreferenceStore());
 		setDescription("Options configuring scratchbox 1");
-		origSandboxRoot = getPreferenceStore().getString(
-				SB1PreferenceConstants.SB1_SBOX_SANDBOX.toString());
+		origRoots = getPreferenceStore().getString(SB1PreferenceConstants.SB1_ROOTS);
 	}
 
 	/*
@@ -74,45 +62,21 @@
 		
 		GeneralUtils.setHelpID(getControl(), IHelpID.HID_GLOBAL_PREF_ESBOX_SCRATCHBOX_1);
 		
-		IScratchboxSDK sdk = null;
-		try {
-			sdk = ScratchboxSDKFacade.getInstance().getScratchboxSDK(
-					IScratchbox1SDK.class).get(0);
-		} catch (ScratchboxException e) {
-		}
-		if (false && sdk != null && sdk.getMachine() instanceof ILocalMachine) {
-			feSandboxRoot = new DirectoryFieldEditor(
-					SB1PreferenceConstants.SB1_SBOX_SANDBOX.toString(),
-					"Sandbox root directory:", getFieldEditorParent());
-			addField(feSandboxRoot);
-			feSandboxRoot.getTextControl(getFieldEditorParent())
-					.addModifyListener(new ModifyListener() {
+		feRootStr = new StringFieldEditor(SB1PreferenceConstants.SB1_ROOTS,
+				"Scratchbox search path:", getFieldEditorParent());
+		addField(feRootStr);
+		feRootStr.getTextControl(getFieldEditorParent())
+				.addModifyListener(new ModifyListener() {
 
-						public void modifyText(ModifyEvent e) {
-							sdksChanged = true;
-						}
+					public void modifyText(ModifyEvent e) {
+						sdksChanged = true;
+					}
 
-					});
-		} else {
-			feSandboxRootStr = new StringFieldEditor(
-					SB1PreferenceConstants.SB1_SBOX_SANDBOX.toString(),
-					"Sandbox root directory:", getFieldEditorParent());
-			addField(feSandboxRootStr);
-			feSandboxRootStr.getTextControl(getFieldEditorParent())
-					.addModifyListener(new ModifyListener() {
+				});
 
-						public void modifyText(ModifyEvent e) {
-							sdksChanged = true;
-						}
+		feRootStr.getTextControl(getFieldEditorParent()).setToolTipText(
+				"Multiple Scratchbox 1 installations may exist.  Specify a colon-separated search path for the ones you want to use.");
 
-					});
-		}
-
-		feSandboxRootStr
-		.getTextControl(getFieldEditorParent())
-		.setToolTipText(
-				"Specify the base path to scratchbox.  Leave ${USER} as is (it is substituted with the active user on the build machine).");
-
 		
 		feSboxCommands = new StringFieldEditor(
 				SB1PreferenceConstants.SB1_LOGIN_COMMAND.toString(),
@@ -154,12 +118,11 @@
 		boolean ret = super.performOk();
 		if (ret) {
 			if (sdksChanged) {
-				String curSandboxRoot = getPreferenceStore().getString(
-						SB1PreferenceConstants.SB1_SBOX_SANDBOX.toString());
-				if (!curSandboxRoot.equals(origSandboxRoot)) {
+				String curSandboxRoots = getPreferenceStore().getString(SB1PreferenceConstants.SB1_ROOTS);
+				if (!curSandboxRoots.equals(origRoots)) {
 					// asynchronous
 					SDKFactory.getInstance().refresh(true);
-					origSandboxRoot = curSandboxRoot;
+					origRoots = curSandboxRoots;
 				}
 			}
 		}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/BaseScratchbox1SDKInstallerEngine.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/BaseScratchbox1SDKInstallerEngine.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/BaseScratchbox1SDKInstallerEngine.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,200 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.net.URL;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.esbox.scratchbox.core.sdk.ScratchboxSDKFacade;
+import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
+import org.maemo.mica.common.core.GeneralUtils;
+import org.maemo.mica.common.core.IProgressReporter;
+import org.maemo.mica.common.core.MicaException;
+import org.maemo.mica.common.core.ProgressReporterStreamTextMonitor;
+import org.maemo.mica.common.core.env.IEnvironmentModifierBlock;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+import org.maemo.mica.common.core.process.CommandLineArguments;
+import org.maemo.mica.common.core.process.IProcessLauncher;
+import org.maemo.mica.common.core.process.IProcessLauncherFactory;
+import org.maemo.mica.common.core.process.IStreamMonitor;
+import org.maemo.mica.common.core.process.ProcessLauncherUtils;
+import org.maemo.mica.common.ui.SudoLauncherUtils;
+
+/**
+ * This engine runs the Scratchbox installer script,
+ * passing the settings from {@link Scratchbox1SDKInstallerData} to the script,
+ * feeding the output to the progress reporter, and checking the output for stderr
+ * text and other error messages. 
+ * @author eswartz
+ *
+ */
+public class BaseScratchbox1SDKInstallerEngine {
+
+	protected final IProgressReporter reporter;
+	protected final IBuildMachine machine;
+	protected final Shell shell;
+
+	public BaseScratchbox1SDKInstallerEngine(
+			Shell shell,
+			IBuildMachine machine,
+			IProgressReporter progressReporter) {
+		this.shell = shell;
+		this.machine = machine;
+		this.reporter = progressReporter;
+	}
+
+	protected IPath fetchInstallScript(MultiStatus multiStatus, IProgressMonitor monitor, URL url) {
+		reporter.logInfo("Fetching installer script from " + url);
+		
+		monitor.subTask("Fetching install script...");
+		IPath installScript = null;
+		try {
+			installScript = GeneralUtils.cachedCopyScriptToMachine(url, 
+					machine, 
+					machine.getUserHome().append(GeneralUtils.DEFAULT_MICA_HIDDEN_PATH),
+					false,
+					new SubProgressMonitor(monitor, 1));
+		} catch (MicaException e) {
+			IStatus status = Activator.createErrorStatus("Cannot fetch installer script to build machine", e);
+			reporter.log(status);
+			multiStatus.add(status);
+		}
+		return installScript;
+	}
+
+	/**
+	 * Get a process launcher for root programs
+	 * @return {@link IProcessLauncherFactory} or <code>null</code>
+	 */
+	protected IProcessLauncher getRootProcessLauncher(List<String> cmdLine) {
+		cmdLine = SudoLauncherUtils.convertToSudoCommandLine(cmdLine, "root");
+		
+		IProcessLauncherFactory factory = machine.getProcessLauncherFactory();
+		IEnvironmentModifierBlock envBlock = getProxySetupEnvironmentBlock(factory);
+		
+		IProcessLauncher launcher = factory.createProcessLauncher(
+				null, cmdLine, envBlock);
+		return launcher;
+	}
+
+	/**
+	 * Get a stream monitor to check for sudo password prompt
+	 * @return {@link IProcessLauncherFactory} or <code>null</code>
+	 */
+	protected IStreamMonitor getRootProcessMonitor(List<String> cmdLine) {
+		return SudoLauncherUtils.createSudoSnifferMonitor(machine.getUserName(), "root", cmdLine);
+	}
+	/**
+	 * Get the environment block which has proxy variables installed
+	 * @param factory
+	 * @return modified {@link IEnvironmentModifierBlock}
+	 */
+	protected IEnvironmentModifierBlock getProxySetupEnvironmentBlock(
+			IProcessLauncherFactory factory) {
+		IEnvironmentModifierBlock envBlock = factory.defaultEnvironmentModifierBlock();
+		ProcessLauncherUtils.defineProxyVariables(envBlock);
+		return envBlock;
+	}
+	
+	/**
+	 * Kill a running Scratchbox installation and turn off its daemons.
+	 */
+	protected void killAnyRunningScratchbox(MultiStatus multiStatus, IProgressMonitor monitor, IPath newSboxLocation) {
+		
+		Set<IPath> likelySboxLocations = new HashSet<IPath>();
+		likelySboxLocations.add(newSboxLocation.removeTrailingSeparator());
+		likelySboxLocations.add(new Path("/scratchbox"));
+		likelySboxLocations.add(new Path("/opt/scratchbox"));
+		
+		final boolean[] kill = { false };
+		shell.getDisplay().syncExec(new Runnable() {
+			public void run() {
+				kill[0] = MessageDialog.openQuestion(null,
+						"Clean Up Sessions",
+						"Nothing should be running in Scratchbox during the installation.\n\n"
+							+ "Kill existing Scratchbox sessions?  (You may manually close them first, if desired, then select 'No' to continue.)");		
+			}
+		});
+		
+		List<IScratchbox1SDK> sdks = ScratchboxSDKFacade.getInstance().getScratchboxSDK(
+				IScratchbox1SDK.class);
+
+		if (kill[0]) {
+			if (sdks.size() > 0) {
+				monitor.subTask("Cleaning Scratchbox sessions...");
+			
+				for (IScratchbox1SDK sdk : sdks) {
+					try {
+						sdk.killSessions();
+						monitor.worked(1);
+						if (monitor.isCanceled())
+							return;
+					} catch (MicaException e1) {
+						IStatus status = Activator.createErrorStatus("Cannot kill Scratchbox sessions in " + sdk +"; you may want to kill them yourself", e1);
+						reporter.log(status);
+						multiStatus.add(status);
+					}
+				}
+			}
+		}
+		
+		for (IPath sboxLocation : likelySboxLocations) {
+			killRunningScratchbox(sdks, multiStatus, monitor, sboxLocation);
+		}
+	}
+	
+	private void killRunningScratchbox(List<IScratchbox1SDK> sdks, MultiStatus multiStatus, 
+			IProgressMonitor monitor, IPath sboxLocation) {
+		
+		// always try to kill the daemon, even if we didn't find sbox or want to kill sessions
+		// (because installation may be busted, and because we must unmount before deleting 
+		// recursively, else we try to blow away system directories)
+		
+		
+		monitor.subTask("Terminating Scratchbox daemons...");
+		
+		String sboxCtl = sboxLocation.append("sbin/sbox_ctl").toPortableString();
+		List<String> cmdLine = CommandLineArguments.createFromVarArgs(sboxCtl, "stop");
+		IProcessLauncher processLauncher = getRootProcessLauncher(cmdLine);
+		IStreamMonitor sudoSniffer = getRootProcessMonitor(cmdLine);
+		
+		if (machine.getFileSystemAccess().getFileStore(new Path(sboxCtl)).fetchInfo().exists()) {
+			try {
+				ProcessLauncherUtils.launchAndMonitorStandardStreams(processLauncher, 
+						new IStreamMonitor[] {
+							new ProgressReporterStreamTextMonitor(reporter),
+							sudoSniffer,
+						},
+						new SubProgressMonitor(monitor, 1));
+				monitor.worked(1);
+				if (monitor.isCanceled())
+					return;
+			} catch (MicaException e) {
+				IStatus status = Activator.createErrorStatus("Failed to turn off Scratchbox daemon; you may want to stop it yourself", e);
+				reporter.log(status);
+				multiStatus.add(status);
+			}
+		}
+	}
+
+}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/MaemoScriptInstallerMonitor.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/MaemoScriptInstallerMonitor.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/MaemoScriptInstallerMonitor.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,214 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.eclipse.jface.dialogs.IDialogConstants;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.mica.common.core.IProgressReporter;
+import org.maemo.mica.common.core.process.StreamLineMonitorAdapter;
+
+class MaemoScriptInstallerMonitor extends StreamLineMonitorAdapter {
+
+	boolean readingLicense;
+	boolean gotLicense;
+	StringBuilder licenseText;
+	private OutputStream inputStream;
+	private StringBuilder errorText;
+	private final IProgressReporter reporter;
+	private final Shell shell;
+	
+	/**
+	 * 
+	 */
+	public MaemoScriptInstallerMonitor(Shell shell, IProgressReporter reporter) {
+		this.shell = shell;
+		this.reporter = reporter;
+		errorText = new StringBuilder();
+	}
+	
+	/**
+	 * Get well-marked error text 
+	 * @return error text or <code>null</code> if none seen
+	 */
+	public String getErrorText() {
+		return errorText.length() > 0 ? errorText.toString() : null;
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.core.process.IStreamTextMonitor#handleException(java.io.IOException)
+	 */
+	public void handleException(IOException e) {
+		reporter.log(Activator.createErrorStatus("Problem parsing script output", e));
+	}
+
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.core.process.StreamMonitorAdapter#processCreated(java.lang.Process)
+	 */
+	@Override
+	public void processCreated(Process process) {
+		super.processCreated(process);
+		inputStream = process.getOutputStream();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.core.process.IStreamTextMonitor#handleText(java.lang.String, boolean)
+	 */
+	public void handleLine(String text, boolean errorStream) throws InterruptedException {
+		System.out.println(text);
+		if (errorStream) {
+			appendErrorLine(text);
+			return;
+		}
+		if (handleErrorLine(text))
+			return;
+		
+		if (handleLicenseLine(text)) 
+			return;
+		
+		reporter.appendStreamText(text + "\n", errorStream);
+		
+	}
+
+	/**
+	 * Handle a line marked by the script as being error text (stderr text is
+	 * handled separately).
+	 * @param text
+	 * @return true: consumed line
+	 */
+	private boolean handleErrorLine(String text) {
+		if (text.startsWith("E:")) {
+			appendErrorLine(text);
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * @param text
+	 */
+	private void appendErrorLine(String text) {
+		errorText.append(text);
+		errorText.append('\n');
+		reporter.appendStreamText(text + "\n", true);
+	}
+
+	/**
+	 * @param text
+	 * @return
+	 * @throws InterruptedException 
+	 */
+	private boolean handleLicenseLine(String text) throws InterruptedException {
+		if (text.trim().length() >= 80 && text.trim().replaceAll("-", "").length() == 0) {
+			if (!readingLicense && !gotLicense) {
+				readingLicense = true;
+				licenseText = new StringBuilder();
+				return true;
+			} else if (!gotLicense) {
+				readingLicense = false;
+				gotLicense = true;
+				
+				final boolean[] accept = { true };
+				
+				shell.getDisplay().syncExec(new Runnable() {
+					public void run() {
+						MessageDialog dialog = new MessageDialog(shell,
+								"Closed Binaries License",
+								null,
+								"You must accept this license to install the closed Nokia binaries:",
+								MessageDialog.QUESTION,
+								new String[] { IDialogConstants.OK_LABEL, IDialogConstants.CANCEL_LABEL },
+								0
+								) {
+							
+							{
+								setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE);
+							}
+							
+							/* (non-Javadoc)
+							 * @see org.eclipse.jface.dialogs.Dialog#getInitialSize()
+							 */
+							@Override
+							protected Point getInitialSize() {
+								return new Point(500, 400);
+							}
+
+							/* (non-Javadoc)
+							 * @see org.eclipse.jface.dialogs.IconAndMessageDialog#createMessageArea(org.eclipse.swt.widgets.Composite)
+							 */
+							@Override
+							protected Control createMessageArea(
+									Composite parent) {
+								Composite composite = (Composite) super.createMessageArea(parent);
+								
+								Text text = new Text(composite, SWT.READ_ONLY | SWT.V_SCROLL | SWT.BORDER);
+								text.setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
+								text.setText(licenseText.toString());
+								
+								GridDataFactory.swtDefaults().grab(true, true).span(2, 1).applyTo(text);
+								
+								return composite;
+							}
+						};
+						accept[0] = dialog.open() == 0;
+					}
+				});
+				
+				if (accept[0]) {
+					sendNewline();
+				} else {
+					reporter.log(Activator.createErrorStatus("User declined license request (re-run with \"Open-source components only\" option)", null));
+					throw new InterruptedException();
+				}
+				return true;
+			}
+		} else if (readingLicense) {
+			licenseText.append(text);
+			licenseText.append('\n');
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * 
+	 */
+	private void sendNewline() throws InterruptedException{
+		try {
+			inputStream.write(new byte[] { '\n' });
+			inputStream.flush();
+		} catch (IOException e) {
+			reporter.log(Activator.createErrorStatus("Failed to send newline", e));
+			throw new InterruptedException();
+		}			
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.core.process.StreamMonitorAdapter#processExited(int)
+	 */
+	@Override
+	public void processExited(int exitCode) {
+		if (readingLicense) {
+			reporter.appendStreamText(licenseText.toString(), false);
+		}
+	}
+}
\ No newline at end of file

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/NewScratchbox1SDKWizard.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/NewScratchbox1SDKWizard.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/NewScratchbox1SDKWizard.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,194 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial implementation
+ *******************************************************************************/
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWizard;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.mica.common.core.Policy;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+import org.maemo.mica.common.core.machine.MachineRegistry;
+import org.maemo.mica.common.core.sdk.ISDKTarget;
+import org.maemo.mica.internal.api.maemosdk.ui.wizards.BadInstallationPage;
+
+/**
+ * This wizard provides an easy way to install the Scratchbox 1 SDK by
+ * downloading and running the scripts from the maemo.org website.
+ * 
+ */
+public class NewScratchbox1SDKWizard extends Wizard implements INewWizard {
+
+	protected Scratchbox1SDKInstallerSelectionWizardPage targetPage;
+
+	protected ISDKTarget createdTarget;
+
+	private final IBuildMachine buildMachine;
+
+	private Scratchbox1InstallerWorkPage workPage;
+
+	private void initialize() {
+		setNeedsProgressMonitor(true);
+		setWindowTitle("New Scratchbox 1 SDK");
+		ImageDescriptor image = Activator
+				.getImageDescriptor("./icons/full/wizban/target_wizban.gif");
+		setDefaultPageImageDescriptor(image);
+		initPages();
+	}
+
+	/**
+	 * Constructs a new target wizard for the given SDK (from the target
+	 * configuration page).  
+	 * 
+	 * @param sdk non-<code>null</code> SB1 SDK
+	 */
+	public NewScratchbox1SDKWizard() {
+		super();
+		IBuildMachine[] buildMachines = MachineRegistry.getInstance().getBuildMachines();
+		if (buildMachines.length == 0)
+			this.buildMachine = null;
+		else
+			this.buildMachine = buildMachines[0];
+		initialize();
+	}
+	
+	/**
+	 * Constructs a new target wizard for the given SDK (from the target
+	 * configuration page).  
+	 * 
+	 * @param sdk non-<code>null</code> SB1 SDK
+	 */
+	public NewScratchbox1SDKWizard(IBuildMachine machine) {
+		super();
+		this.buildMachine = machine;
+		initialize();
+	}
+	
+	/**
+	 * Inicializes the content of the pages.
+	 */
+	private void initPages() {
+		if (buildMachine == null) {
+			addPage(new BadInstallationPage());
+			return;
+		}
+		
+		targetPage = new Scratchbox1SDKInstallerSelectionWizardPage(buildMachine);
+		addPage(targetPage);
+		
+		workPage = new Scratchbox1InstallerWorkPage(
+				"Install Scratchbox", 
+				"This page reports the progress of the installation.  Please verify network settings first."
+				) {
+			private Label freeSpaceWarningLabel;
+
+			/* (non-Javadoc)
+			 * @see org.maemo.esbox.internal.scratchbox.sb1.ui.wizard.Scratchbox1InstallerWorkPage#addControlsBelowProgress(org.eclipse.swt.widgets.Composite)
+			 */
+			@Override
+			protected void addControlsBelowProgress(Composite body) {
+				super.addControlsBelowProgress(body);
+				
+				freeSpaceWarningLabel = new Label(body, SWT.NONE);
+				GridDataFactory.fillDefaults().grab(true, false).applyTo(freeSpaceWarningLabel);
+				freeSpaceWarningLabel.setText("NOTE: be sure you have at least 450M available in /tmp!");
+				freeSpaceWarningLabel.setForeground(body.getShell().getDisplay().getSystemColor(SWT.COLOR_BLUE));
+			}
+			
+			/* (non-Javadoc)
+			 * @see org.maemo.mica.common.ui.wizards.WizardWorkProgressPageBase#setVisible(boolean)
+			 */
+			@Override
+			public void setVisible(boolean visible) {
+				super.setVisible(visible);
+				if (visible) {
+					freeSpaceWarningLabel.setVisible(
+							targetPage.getSDKInstallerData().isNonDefaultInstallation());
+				}
+			}
+		};
+		addPage(workPage);
+		
+	}
+
+	public boolean canFinish() {
+		return super.canFinish();
+	}
+
+	@Override
+	public boolean performFinish() {
+		final IStatus status = doWork();
+		
+		String message = status.isMultiStatus() ?
+					status.isOK() ? "Installation succeeded" : "Installation encountered some errors"
+						: null;
+		
+		boolean goOn = workPage.reportOperationStatus("SDK Installation Results", message, status, true)
+			&& !status.matches(IStatus.CANCEL);
+		return goOn;
+	}
+	
+	public IStatus doWork() {
+		final IStatus[] statuses = { Policy.getCancelStatus(Activator.getDefault()) } ;
+		try {
+			getContainer().showPage(workPage);
+			workPage.showAndClearLog();
+			
+			getContainer().run(true, true, new IRunnableWithProgress() {
+	
+				public void run(IProgressMonitor monitor)
+						throws InvocationTargetException, InterruptedException {
+					
+					monitor.subTask("Installing targets...");
+
+					Scratchbox1SDKInstallerEngine engine = new Scratchbox1SDKInstallerEngine(
+							getShell(),
+							buildMachine,
+							targetPage.getSDKInstallerData(),
+							workPage.getProgressReporter());
+					
+					IStatus status = engine.installScratchbox(targetPage.isForceRemove(), monitor);
+					
+					if (status.matches(IStatus.CANCEL))
+						status = Activator.createErrorStatus("The installation was canceled.", null);
+					statuses[0] = status;
+				}
+				
+			});
+		} catch (InvocationTargetException e) {
+			Activator.getErrorLogger().logAndShowError(e.getMessage(), e.getCause());
+			statuses[0] = Activator.createErrorStatus("The installation failed unexpectedly", e);
+		} catch (InterruptedException e) {
+		}
+		return statuses[0];
+	}
+	
+	/**
+	 * We will accept the selection in the workbench to see if we can initialize
+	 * from it.
+	 * 
+	 * @see IWorkbenchWizard#init(IWorkbench, IStructuredSelection)
+	 */
+	public void init(IWorkbench workbench, IStructuredSelection selection) {
+	}
+}

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/NewScratchbox1TargetWizard.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/NewScratchbox1TargetWizard.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/NewScratchbox1TargetWizard.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -13,45 +13,59 @@
  *******************************************************************************/
 package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
 
-import org.eclipse.core.resources.IProject;
-import org.eclipse.jface.dialogs.MessageDialog;
+import java.lang.reflect.InvocationTargetException;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jface.operation.IRunnableWithProgress;
 import org.eclipse.jface.resource.ImageDescriptor;
 import org.eclipse.jface.viewers.IStructuredSelection;
-import org.eclipse.jface.wizard.*;
-import org.eclipse.swt.widgets.TableItem;
-import org.eclipse.ui.*;
-import org.maemo.esbox.internal.api.scratchbox.ui.wizards.*;
+import org.eclipse.jface.wizard.IWizardPage;
+import org.eclipse.jface.wizard.Wizard;
+import org.eclipse.jface.wizard.WizardPage;
+import org.eclipse.ui.INewWizard;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchWizard;
 import org.maemo.esbox.internal.scratchbox.sb1.Activator;
-import org.maemo.esbox.internal.scratchbox.sb1.core.Scratchbox1SDK;
-import org.maemo.mica.common.core.MicaException;
-import org.maemo.mica.common.core.ErrorLogger;
+import org.maemo.mica.common.core.Policy;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+import org.maemo.mica.common.core.machine.MachineRegistry;
 import org.maemo.mica.common.core.sdk.ISDKTarget;
-import org.maemo.mica.common.core.sdk.SDKFactory;
-import org.maemo.mica.internal.api.maemosdk.ui.wizards.sbrsh.SbrshConfigurationNFSServer;
-import org.maemo.mica.internal.api.maemosdk.ui.wizards.sbrsh.SbrshConfigurationTargetDevice;
+import org.maemo.mica.internal.api.maemosdk.ui.wizards.BadInstallationPage;
 
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
 /**
- * The target wizard provides a easy way to create a target for Scratchbox. As
- * Scratchbox target configuration, the user can configure your target.
+ * The target wizard provides an easier way to create a target for Scratchbox, by
+ * downloading and running the scripts from the maemo.org website.
  * 
  */
 public class NewScratchbox1TargetWizard extends Wizard implements INewWizard {
 
-	protected WizardPage targetNamePage;
-	protected WizardPage compilerNamePage;
-	protected WizardPage devkitsName;
-	protected WizardPage cpuMethodName;
+	protected Scratchbox1TargetInstallerSelectionWizardPage targetPage;
 	protected WizardPage sbrshConfigTargetDevice;
 	protected WizardPage sbrshConfigNFSServer;
-	protected IProject generatedProject;
 
-	private Scratchbox1SDK sdk;
-
 	protected ISDKTarget createdTarget;
 
+	private final IBuildMachine buildMachine;
+
+	private Scratchbox1InstallerWorkPage workPage;
+
+	/**
+	 * Constructs a new target wizard for the given SDK (from the target
+	 * configuration page).  
+	 * 
+	 * @param sdk non-<code>null</code> SB1 SDK
+	 */
+	public NewScratchbox1TargetWizard() {
+		super();
+		IBuildMachine[] buildMachines = MachineRegistry.getInstance().getBuildMachines();
+		if (buildMachines.length == 0)
+			this.buildMachine = null;
+		else
+			this.buildMachine = buildMachines[0];
+		initialize();
+	}
+	
 	private void initialize() {
 		setNeedsProgressMonitor(true);
 		setWindowTitle("New Scratchbox 1 Target");
@@ -61,70 +75,50 @@
 		initPages();
 	}
 
+	
+	
 	/**
-	 * Constructs a new target wizard for the given SDK (from the target
-	 * configuration page)
-	 * 
-	 * @param sdk
-	 */
-	public NewScratchbox1TargetWizard(Scratchbox1SDK sdk) {
-		super();
-		this.sdk = sdk;
-		initialize();
-	}
-
-	/**
 	 * Inicializes the content of the pages.
 	 */
 	private void initPages() {
-		if (sdk != null) {
-			targetNamePage = TargetWizardPageFactory.getInstance()
-					.createNamePage(sdk);
-			addPage(targetNamePage);
-			compilerNamePage = TargetWizardPageFactory.getInstance()
-					.createCompilerPage(sdk);
-			addPage(compilerNamePage);
-			devkitsName = new TargetWizardDevkitsPage(sdk);
-			addPage(devkitsName);
-			cpuMethodName = TargetWizardPageFactory.getInstance()
-					.createCPUMethod(sdk);
-			addPage(cpuMethodName);
-			sbrshConfigTargetDevice = TargetWizardPageFactory.getInstance()
-					.createSbrshConfigDeviceTargetPage();
-			addPage(sbrshConfigTargetDevice);
-			sbrshConfigNFSServer = TargetWizardPageFactory.getInstance()
-					.createSbrshConfigNFSSServer();
-			addPage(sbrshConfigNFSServer);
-		} else {
-			addPage(TargetWizardPageFactory.getInstance()
-					.createBadInstallationPage());
+		if (buildMachine == null) {
+			addPage(new BadInstallationPage());
+			return;
 		}
+		
+		targetPage = new Scratchbox1TargetInstallerSelectionWizardPage(buildMachine);
+		addPage(targetPage);
+		
+		workPage = new Scratchbox1InstallerWorkPage(
+				"Install target", 
+				"This page reports the progress of the target installation.  Please verify network settings first."
+				);
+		addPage(workPage);
+		
+		/*
+		sbrshConfigTargetDevice = TargetWizardPageFactory.getInstance()
+				.createSbrshConfigDeviceTargetPage();
+		addPage(sbrshConfigTargetDevice);
+		sbrshConfigNFSServer = TargetWizardPageFactory.getInstance()
+				.createSbrshConfigNFSSServer();
+		addPage(sbrshConfigNFSServer);
+		*/
 	}
 
 	public boolean canFinish() {
-		if (sdk == null)
-			return false;
-
-		boolean targetNamed = ((TargetWizardNamePage) targetNamePage).isPageComplete();
-		boolean devkitsChosen = ((TargetWizardDevkitsPage) devkitsName).isPageComplete();
-		boolean cpuPage = ((TargetWizardCPUMethod) cpuMethodName).canFinish();
-		boolean configDevice = ((SbrshConfigurationTargetDevice) sbrshConfigTargetDevice)
-				.canFinish();
-		boolean NFSServer = ((SbrshConfigurationNFSServer) sbrshConfigNFSServer)
-				.canFinish();
-		boolean sbrshConfigAccepted = ((TargetWizardCPUMethod) cpuMethodName)
-				.getSbrshConfigure();
-
+		/*
+		boolean sbrshConfigAccepted = isSBRSHSelected();
 		if (!sbrshConfigAccepted && (targetNamed && devkitsChosen && cpuPage))
 			return true;
 		if (sbrshConfigAccepted && NFSServer && configDevice)
 			return true;
-
-		return false;
+		 */
+		return super.canFinish();
 	}
 
 	@Override
 	public IWizardPage getNextPage(IWizardPage page) {
+		/*
 		if (page == cpuMethodName) {
 			boolean sbrshConfigAccepted = ((TargetWizardCPUMethod) cpuMethodName)
 					.getSbrshConfigure();
@@ -133,180 +127,59 @@
 			else
 				// user wants to configure sbrsh
 				return super.getNextPage(page);
-		}
+		}*/
 		return super.getNextPage(page);
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.eclipse.jface.wizard.IWizard#performFinish()
-	 */
+	@Override
 	public boolean performFinish() {
-		if (!setupTargetFromScratch())
-			return false;
-
-		// find the new target
-		SDKFactory.getInstance().refresh(false);
+		final IStatus status = doWork();
 		
-		boolean sbrshConfigSelected = ((TargetWizardCPUMethod) cpuMethodName)
-				.getSbrshConfigure();
-		if (sbrshConfigSelected) {
-			configureSbrshService();
-			showsDialog();
-		}
-
-		return true;
+		String message = status.isMultiStatus() ?
+					status.isOK() ? "Installation succeeded" : "Installation encountered some errors"
+						: null;
+		
+		boolean goOn = workPage.reportOperationStatus("Target Installation Results", message, status, true)
+			&& !status.matches(IStatus.CANCEL);
+		return goOn;
 	}
-
-	private boolean setupTargetFromScratch() {
-		String targetName;
-		// in this mode, construct a target from the user's settings
-		targetName = getTargetNameSelected();
-		String compilerName = getCompilerNameSelected();
-		String cpuMethod = getCputranspSelected();
+	
+	public IStatus doWork() {
+		final IStatus[] statuses = { Policy.getCancelStatus(Activator.getDefault()) } ;
 		try {
+			getContainer().showPage(workPage);
+			workPage.showAndClearLog();
+			
+			getContainer().run(true, true, new IRunnableWithProgress() {
+	
+				public void run(IProgressMonitor monitor)
+						throws InvocationTargetException, InterruptedException {
+					
+					monitor.subTask("Installing targets...");
 
-			String devkits = getDevkitsSelected();
-			// ScratchboxFacade.getInstance().createTarget((IScratchbox1SDK)
-			// sdk, targetName, compilerName, devkits, cpuMethod);
-			if (!sdk.createTarget(targetName, compilerName, devkits, cpuMethod))
-				return false;
-
-			createdTarget = sdk.findSDKTarget(targetName);
-			return true;
-		} catch (MicaException e) {
-			ErrorLogger errorLogger = Activator.getErrorLogger();
-			errorLogger.logAndShowError("Cannot create target "
-					+ targetName, e);
-			return false;
+					Scratchbox1TargetInstallerEngine engine = new Scratchbox1TargetInstallerEngine(
+							getShell(),
+							buildMachine,
+							targetPage.getTargetInstallerData(),
+							workPage.getProgressReporter());
+					
+					IStatus status = engine.installTargets(monitor);
+					
+					if (status.matches(IStatus.CANCEL))
+						status = Activator.createErrorStatus("The installation was canceled.", null);
+					statuses[0] = status;
+				}
+				
+			});
+		} catch (InvocationTargetException e) {
+			Activator.getErrorLogger().logAndShowError(e.getMessage(), e.getCause());
+			statuses[0] = Activator.createErrorStatus("The installation failed unexpectedly", e);
+		} catch (InterruptedException e) {
 		}
+		return statuses[0];
 	}
 
 	/**
-	 * Return the name of the target to be created.
-	 * 
-	 * @return the name of the target to be created.
-	 */
-	private String getTargetNameSelected() {
-		return ((TargetWizardNamePage) targetNamePage).getTextControl()
-				.getText();
-	}
-
-	/**
-	 * Return the compiler name of the target to be created.
-	 * 
-	 * @return the compiler name of the target to be created.
-	 */
-	private String getCompilerNameSelected() {
-		TableItem item = ((TargetWizardCompilerPage) compilerNamePage)
-				.getTableControl().getSelection()[0];
-		return item.getText();
-	}
-
-	/**
-	 * Return the devkits selected.
-	 * 
-	 * @return the devkits selected.
-	 */
-	private String getDevkitsSelected() {
-		String devkits = "";
-		TableItem devkitItems[] = ((TargetWizardDevkitsPage) devkitsName).table.getItems();
-		String separator = "";
-		for (int i = 0; i < devkitItems.length; i++) {
-			TableItem devkit = devkitItems[i];
-			if (devkit.getChecked()) {
-				devkits += separator + devkit.getText();
-				separator = ":";
-			}
-		}
-		return devkits;
-	}
-
-	/**
-	 * Return the cputransp name of the target to be created.
-	 * 
-	 * @return the cputransp name of the target to be created.
-	 */
-	private String getCputranspSelected() {
-		TableItem item = ((TargetWizardCPUMethod) cpuMethodName).getTable()
-				.getSelection()[0];
-		return item.getText();
-	}
-
-	/**
-	 * Configure sbrsh service.
-	 */
-	private void configureSbrshService() {
-		String targetName = getTargetNameSelected();
-		String deviceTargetAddr = ((SbrshConfigurationTargetDevice) sbrshConfigTargetDevice)
-				.getTargetDeviceAddr();
-		String nfsHostname = ((SbrshConfigurationNFSServer) sbrshConfigNFSServer)
-				.getNFSHostname();
-
-		try {
-			// ScratchboxFacade.getInstance().configureSbrsh(sdk, targetName,
-			// deviceTargetAddr, nfsHostname);
-			sdk.configureSbrsh(targetName, deviceTargetAddr, nfsHostname);
-		} catch (MicaException e) {
-			ErrorLogger errorLogger = Activator.getErrorLogger();
-			errorLogger.logAndShowError("Cannot configure sbrsh", e);
-		}
-	}
-
-	/**
-	 * Add user at access list of the sbrshd running at the target device.
-	 */
-	private void addUser() {
-		String deviceTargetIP = ((SbrshConfigurationTargetDevice) sbrshConfigTargetDevice)
-				.getTargetDeviceIP();
-		String username = System.getProperty("user.name");
-		ErrorLogger errorLogger = Activator.getErrorLogger();
-
-		try {
-			String localAddr = getLocalIP();
-			// ScratchboxFacade.getInstance().addSbrshAccessList(sdk,
-			// deviceTargetIP, username, localAddr);
-			sdk.addSbrshAccessList(deviceTargetIP, username, localAddr);
-		} catch (MicaException e) {
-			errorLogger
-					.logAndShowError(
-							"Cannot add user to the access list of sbrshd at the target device",
-							e);
-		} catch (UnknownHostException e) {
-			errorLogger.logAndShowError("Cannot get local IP address", e);
-		}
-	}
-
-	/**
-	 * Shows the dialog to ask the user if s/he wants to add his/herself to the
-	 * acess list of the sbrshd.
-	 */
-	private void showsDialog() {
-		String deviceTargetAddr = ((SbrshConfigurationTargetDevice) sbrshConfigTargetDevice)
-				.getTargetDeviceIP();
-		String text = "Do you want to add yourself to the access list of the sbrshd running on target device? \n";
-		text += "(This requires that "
-				+ deviceTargetAddr
-				+ " has ssh daemon running and sbrshd already installed, and that you have root access).";
-		boolean userAddedAtAccessList = MessageDialog.openQuestion(getShell(),
-				"Scratchbox Configuration", text);
-		if (userAddedAtAccessList) {
-			addUser();
-		}
-	}
-
-	/**
-	 * Get the local IP address.
-	 * 
-	 * @return the local IP address.
-	 * @throws UnknownHostException
-	 */
-	private String getLocalIP() throws UnknownHostException {
-		return InetAddress.getLocalHost().getHostAddress();
-	}
-
-	/**
 	 * We will accept the selection in the workbench to see if we can initialize
 	 * from it.
 	 * 
@@ -314,14 +187,4 @@
 	 */
 	public void init(IWorkbench workbench, IStructuredSelection selection) {
 	}
-
-	/**
-	 * Get the target created. Only valid after wizard dialog completes.
-	 * 
-	 * @return newly created ISDKTarget or <code>null</code>
-	 */
-	public ISDKTarget getCreatedTarget() {
-		return createdTarget;
-	}
-
 }
\ No newline at end of file

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1InstallerWorkPage.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1InstallerWorkPage.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1InstallerWorkPage.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import org.eclipse.swt.widgets.Composite;
+import org.maemo.mica.common.ui.wizards.WizardWorkProgressPageBase;
+
+/**
+ * This page reports the progress and script output from installing.
+ * @author eswartz
+ *
+ */
+public class Scratchbox1InstallerWorkPage extends
+		WizardWorkProgressPageBase {
+
+	/**
+	 * @param title
+	 * @param description
+	 */
+	public Scratchbox1InstallerWorkPage(String title, String description) {
+		super(title, description);
+		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.ui.wizards.WizardWorkProgressPageBase#addControlsBelowProgress(org.eclipse.swt.widgets.Composite)
+	 */
+	@Override
+	protected void addControlsBelowProgress(Composite body) {
+		addStockNetworkSettingHyperlink(body);
+	}
+}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerData.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerData.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerData.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,256 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+
+import com.nokia.cpp.internal.api.utils.core.TextUtils;
+
+/**
+ * This class represents the data used to run the installer script for Scratchbox.
+ * @author eswartz
+ *
+ */
+class Scratchbox1SDKInstallerData {
+	
+	private URL installerURL;
+	private final String name;
+	private String installLocation;
+	private String userGroup;
+	private String userList;
+	private final IBuildMachine machine;
+	private boolean useCache;
+	
+	/**
+	 * 
+	 */
+	public Scratchbox1SDKInstallerData(String name, URL installerURL, IBuildMachine machine) {
+		if (name == null || installerURL == null || machine == null) 
+			throw new NullPointerException();
+		
+		this.machine = machine;
+		this.name = name;
+		this.installerURL = installerURL;
+		this.installLocation = "/scratchbox";
+		this.userGroup = "sbox";
+		this.userList = machine.getUserName();
+	}
+	
+
+	
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((installLocation == null) ? 0 : installLocation.hashCode());
+		result = prime * result
+				+ ((installerURL == null) ? 0 : installerURL.hashCode());
+		result = prime * result + ((machine == null) ? 0 : machine.hashCode());
+		result = prime * result + ((name == null) ? 0 : name.hashCode());
+		result = prime * result
+				+ ((userGroup == null) ? 0 : userGroup.hashCode());
+		result = prime * result
+				+ ((userList == null) ? 0 : userList.hashCode());
+		return result;
+	}
+
+
+
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		Scratchbox1SDKInstallerData other = (Scratchbox1SDKInstallerData) obj;
+		if (installLocation == null) {
+			if (other.installLocation != null)
+				return false;
+		} else if (!installLocation.equals(other.installLocation))
+			return false;
+		if (installerURL == null) {
+			if (other.installerURL != null)
+				return false;
+		} else if (!installerURL.equals(other.installerURL))
+			return false;
+		if (machine == null) {
+			if (other.machine != null)
+				return false;
+		} else if (!machine.equals(other.machine))
+			return false;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		if (userGroup == null) {
+			if (other.userGroup != null)
+				return false;
+		} else if (!userGroup.equals(other.userGroup))
+			return false;
+		if (userList == null) {
+			if (other.userList != null)
+				return false;
+		} else if (!userList.equals(other.userList))
+			return false;
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return name;
+	}
+	
+	/**
+	 * @return the display name of the platform/SDK/etc to install
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	/**
+	 * Get the URL to the installer script
+	 * @return
+	 */
+	public URL getInstallerURL() {
+		return installerURL;
+	}
+
+	
+	/**
+	 * Get the location we're installing to
+	 */
+	public String getScratchboxLocation() {
+		return installLocation;
+	}
+	
+	/**
+	 * Set the location we're installing to
+	 */
+	public void setInstallLocation(String installLocation) {
+		this.installLocation = new Path(installLocation).removeTrailingSeparator().toPortableString();
+	}
+
+	/**
+	 * Get the user group to which to add users
+	 */
+	public String getUserGroup() {
+		return userGroup;
+	}
+	
+	/**
+	 * Set the user group to which to add users
+	 */
+	public void setUserGroup(String userGroup) {
+		this.userGroup = userGroup;
+	}
+	
+	/**
+	 * Get the list of users to register (comma-separated)
+	 */
+	public String getUserList() {
+		return userList;
+	}
+	
+	/**
+	 * Set the list of users to register (comma-separated)
+	 */
+	public void setUserList(String userList) {
+		this.userList = userList;
+	}
+
+	/**
+	 * Tell whether to use existing download
+	 */
+	public void setUseCache(boolean cache) {
+		this.useCache = cache;
+	}
+	
+	/**
+	 * Tell whether to use existing download
+	 */
+	public boolean isUseCache() {
+		return useCache;
+	}
+	
+	/**
+	 * Get the command line to run the installer
+	 * @param installScript
+	 * @return command line
+	 */
+	public List<String> createInstallerCommandLine(IPath installScript) {
+		List<String> cmdLine = new ArrayList<String>();
+		
+		cmdLine.add(installScript.toPortableString());
+		
+		// default for apt/dpkg will use /scratchbox already
+		if (getScratchboxLocation() != null
+				&& !getScratchboxLocation().equals("/scratchbox")) {
+			cmdLine.add("-s");
+			cmdLine.add(getScratchboxLocation());
+		}
+		if (!TextUtils.isEmpty(getUserGroup())) {
+			cmdLine.add("-g");
+			cmdLine.add(getUserGroup());
+		}
+		if (!TextUtils.isEmpty(getUserList())) {
+			cmdLine.add("-u");
+			cmdLine.add(getUserList());
+		}
+		if (isUseCache()) {
+			cmdLine.add("-c");
+		}
+		return cmdLine;
+	}
+
+
+
+	/**
+	 * Tell if the installation is not the default.
+	 * <p>
+	 * This is currently the case if you use a location other than /scratchbox to install.
+	 * @return flag
+	 */
+	public boolean isNonDefaultInstallation() {
+		return !installLocation.equals("/scratchbox");
+	}
+
+	/**
+	 * Tell if the installer will need to use a lot of space in /tmp.
+	 * <p>
+	 * This is currently the case if you use a location other than /scratchbox to install.
+	 * @return flag
+	 */
+	public boolean requiresMassiveTmpSpace() {
+		return isNonDefaultInstallation();
+	}
+}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerDataContentLabelProvider.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerDataContentLabelProvider.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerDataContentLabelProvider.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.BaseLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.graphics.Image;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+import org.maemo.mica.common.ui.CommonUIImages;
+
+/**
+ * @author eswartz
+ *
+ */
+public class Scratchbox1SDKInstallerDataContentLabelProvider extends BaseLabelProvider 
+	implements IStructuredContentProvider, ITableLabelProvider {
+
+	private List<Scratchbox1SDKInstallerData> platforms;
+
+	private Image platformImage;
+	
+	/**
+	 * 
+	 */
+	public Scratchbox1SDKInstallerDataContentLabelProvider() {
+		platforms = new ArrayList<Scratchbox1SDKInstallerData>();
+		platformImage = CommonUIImages.getImage(CommonUIImages.SDK_OBJ);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+	 */
+	public Object[] getElements(Object inputElement) {
+		synchronized (platforms) {
+			return platforms.toArray();
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+	 */
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		if (newInput != null) {
+	
+			platforms.clear();
+	
+			// TODO: make this list more dynamic
+			try {
+				platforms.add(new Scratchbox1SDKInstallerData(
+						"Maemo 4 Series (Diablo)",
+						new URL("http://repository.maemo.org/stable/4.1.2/maemo-scratchbox-install_4.1.2.sh"),
+						((IBuildMachine) newInput)
+				));
+				platforms.add(new Scratchbox1SDKInstallerData(
+						"Maemo 5 Series (Fremantle) (UNSTABLE)",
+						new URL("http://repository.maemo.org/unstable/fremantle/maemo-scratchbox-install_5.0.sh"),
+						((IBuildMachine) newInput)
+				));
+			} catch (MalformedURLException e) {
+				Activator.getErrorLogger().logAndShowError(null, e);
+			}
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+	 */
+	public String getColumnText(Object element, int column) {
+		if (element instanceof Scratchbox1SDKInstallerData) {
+			Scratchbox1SDKInstallerData data = (Scratchbox1SDKInstallerData) element;
+			if (column == 0)
+				return data.getName();
+			else
+				return data.getInstallerURL().toString();
+		}
+		return "";
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
+	 */
+	public Image getColumnImage(Object element, int column) {
+		if (element instanceof Scratchbox1SDKInstallerData) {
+			if (column == 0)
+				return platformImage;
+		}
+		return null;
+	}
+
+}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerEngine.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerEngine.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerEngine.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,273 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.eclipse.core.filesystem.IFileStore;
+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.MultiStatus;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.mica.common.core.IProgressReporter;
+import org.maemo.mica.common.core.MicaException;
+import org.maemo.mica.common.core.ProgressReporterStreamTextMonitor;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+import org.maemo.mica.common.core.machine.IMachine;
+import org.maemo.mica.common.core.process.CommandLineArguments;
+import org.maemo.mica.common.core.process.IProcessLauncher;
+import org.maemo.mica.common.core.process.IStreamMonitor;
+import org.maemo.mica.common.core.process.ProcessLauncherUtils;
+import org.maemo.mica.common.core.process.StreamLineMonitorAdapter;
+
+/**
+ * This engine runs the Scratchbox installer script,
+ * passing the settings from {@link Scratchbox1SDKInstallerData} to the script,
+ * feeding the output to the progress reporter, and checking the output for stderr
+ * text and other error messages. 
+ * @author eswartz
+ *
+ */
+public class Scratchbox1SDKInstallerEngine extends BaseScratchbox1SDKInstallerEngine {
+
+	private final Scratchbox1SDKInstallerData installerData;
+
+	/**
+	 * @param progressReporter
+	 */
+	public Scratchbox1SDKInstallerEngine(
+			Shell shell,
+			IBuildMachine machine,
+			Scratchbox1SDKInstallerData installerData,
+			IProgressReporter progressReporter) {
+		super(shell, machine, progressReporter);
+		this.installerData = installerData;
+	}
+
+	/**
+	 * Handle the case where the script bails on an invalid cached file.
+	 */
+	static class DeleteFailedFilesMonitor extends StreamLineMonitorAdapter {
+		Pattern pattern = Pattern.compile("E:.*file \'([^']+)\' failed.*");
+		private final Shell shell;
+		private final IProgressReporter reporter;
+		private final IMachine machine;
+		/**
+		 * @param shell
+		 * @param reporter
+		 */
+		public DeleteFailedFilesMonitor(IMachine machine, Shell shell, IProgressReporter reporter) {
+			this.machine = machine;
+			this.shell = shell;
+			this.reporter = reporter;
+		}
+		
+		/* (non-Javadoc)
+		 * @see org.maemo.mica.common.core.process.IStreamLineMonitor#handleLine(java.lang.String, boolean)
+		 */
+		public void handleLine(String text, boolean errorStream)
+				throws InterruptedException {
+			Matcher matcher = pattern.matcher(text);
+			if (matcher.matches()) {
+				final String file = matcher.group(1);
+				final IFileStore store = machine.getFileSystemAccess().getFileStore(new Path("/tmp").append(file));
+				if (store.fetchInfo().exists()) {
+					Display.getDefault().syncExec(new Runnable() {
+						public void run() {
+							boolean ret =MessageDialog.openQuestion(shell, "Delete invalid file?", 
+									MessageFormat.format(
+											"The file ''{0}'' didn't download properly.  Delete it?\n\n(Note, you must restart the installer.)",
+											file));
+							if (ret) {
+								try {
+									reporter.logInfo("Deleting " + store.toURI().getPath());
+									store.delete(0, null);
+								} catch (CoreException e) {
+									Activator.getErrorLogger().logAndShowError(
+											MessageFormat.format(
+													"Failed to delete ''{0}''.  Please log in and diagnose the problem.",
+													store.toURI().getPath()), e);
+								}
+							}
+						}
+					});
+				}
+			}
+		}
+	}
+	static class FailRemoveErrorsMonitor extends StreamLineMonitorAdapter {
+		private final Shell shell;
+		private final IProgressMonitor monitor;
+		private boolean warned;
+		private final MultiStatus multiStatus;
+		
+		/**
+		 * @param shell
+		 * @param monitor
+		 */
+		public FailRemoveErrorsMonitor(Shell shell, MultiStatus multiStatus, IProgressMonitor monitor) {
+			this.shell = shell;
+			this.multiStatus = multiStatus;
+			this.monitor = monitor;
+		}
+
+		/* (non-Javadoc)
+		 * @see org.maemo.mica.common.core.process.IStreamLineMonitor#handleLine(java.lang.String, boolean)
+		 */
+		public void handleLine(String text, boolean errorStream)
+				throws InterruptedException {
+			if (warned)
+				return;
+			
+			if (errorStream && text.contains("Operation not permitted")) {
+				Display.getDefault().syncExec(new Runnable() {
+					public void run() {
+						warned = true;
+						boolean ret = MessageDialog.openQuestion(shell, "Problems deleting", 
+								"Some files cannot be removed (see log).  Do you want to keep going?");
+						if (!ret) {
+							multiStatus.add(Activator.createErrorStatus("User canceled.", null));
+							monitor.setCanceled(true);
+						}
+					}
+				});
+			}
+		}
+	}
+	/**
+	 * Perform the installation, logging results to the progress reporter.
+	 * Return the overall status (OK, CANCEL, ERROR)
+	 * @param shell
+	 * @param monitor
+	 * @return IStatus
+	 */
+	public IStatus installScratchbox(boolean forceRemove, IProgressMonitor monitor) {
+		MultiStatus multiStatus = new MultiStatus(Activator.PLUGIN_ID, 0, null, null);
+		
+		IStatus status;
+		monitor.beginTask("", IProgressMonitor.UNKNOWN);
+		
+		reporter.logInfo("Installing " + installerData.getName());
+		
+		IPath installScript = fetchInstallScript(multiStatus, monitor, installerData.getInstallerURL());
+		
+		// our own work that the script doesn't handle
+		killAnyRunningScratchbox(multiStatus, monitor, new Path(installerData.getScratchboxLocation()));
+		if (multiStatus.matches(IStatus.ERROR))
+			return multiStatus;
+		
+		if (forceRemove) {
+			deleteScratchbox(multiStatus, monitor);
+			if (monitor.isCanceled() || multiStatus.matches(IStatus.ERROR))
+				return multiStatus;
+		}
+
+		reporter.logInfo("Running installer script...");
+		monitor.subTask("Running installer script...");
+		
+		List<String> cmdLine = installerData.createInstallerCommandLine(installScript);
+		
+		IProcessLauncher processLauncher = getRootProcessLauncher(cmdLine);
+		IStreamMonitor sudoSniffer = getRootProcessMonitor(cmdLine);
+		
+		int exit;
+		try {
+			exit = ProcessLauncherUtils.launchAndMonitorStandardStreams(
+					processLauncher,
+					new IStreamMonitor[] {
+						new MaemoScriptInstallerMonitor(shell, reporter),
+						sudoSniffer,
+						new DeleteFailedFilesMonitor(machine, shell, reporter),
+					},
+					new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
+		} catch (MicaException e) {
+			status = Activator.createErrorStatus("Failed to run installer script", e);
+			reporter.log(status);
+			multiStatus.add(status);
+			return multiStatus;
+		}
+		
+		if (exit != 0) {
+			multiStatus.add(Activator.createErrorStatus("Installation script failed with exit code " + exit, null));
+		}
+		
+		monitor.done();
+		
+		
+		return multiStatus;
+	}
+	
+	/**
+	 * Delete existing Scratchbox.
+	 * @param monitor
+	 */
+	private void deleteScratchbox(MultiStatus multiStatus, IProgressMonitor monitor) {
+		IStatus status;
+		
+		final String sboxHome = installerData.getScratchboxLocation();
+		monitor.subTask("Deleting old Scratchbox installation at " + sboxHome + "...");
+		
+		final boolean[] delete = { false };
+		shell.getDisplay().syncExec(new Runnable() {
+			public void run() {
+				delete[0] = MessageDialog.openQuestion(null,
+						"Delete Scratchbox",
+						MessageFormat.format(
+						"Are you sure you want to delete the current contents of ''{0}''?\n\n" +
+						"This includes your Scratchbox user home directories, all targets, etc. and cannot be undone!",
+						sboxHome));
+			}
+		});
+		
+		if (!delete[0]) {
+			status = Activator.createErrorStatus("Not deleting Scratchbox.  Please re-run without the \"Remove existing\" option.", null);
+			reporter.log(status);
+			multiStatus.add(status);
+			monitor.setCanceled(true);
+			return;
+		}
+		
+		reporter.logInfo("Deleting Scratchbox from " + sboxHome + "...");
+		
+		final IProcessLauncher processLauncher = getRootProcessLauncher(
+				CommandLineArguments.createFromVarArgs("rm", "-rf", sboxHome));
+		
+		try {
+			ProcessLauncherUtils.launchAndMonitorStandardStreams(processLauncher, 
+					new IStreamMonitor[] {
+						new ProgressReporterStreamTextMonitor(reporter),
+						new FailRemoveErrorsMonitor(shell, multiStatus, monitor),
+					},
+					new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
+			if (monitor.isCanceled())
+				return;
+		} catch (MicaException e) {
+			status = Activator.createErrorStatus("Could not delete " + sboxHome + "; you must delete Scratchbox yourself", e);
+			reporter.log(status);
+			multiStatus.add(status);
+			return;
+		}
+	}
+
+	
+
+}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerSelectionWizardPage.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerSelectionWizardPage.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1SDKInstallerSelectionWizardPage.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,341 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.text.MessageFormat;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+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.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+
+import com.nokia.cpp.internal.api.utils.core.TextUtils;
+
+/**
+ * This page allows the user to select one of the supported installer scripts
+ * to install a Scratchbox 1 setup.
+ * @author eswartz
+ *
+ */
+public class Scratchbox1SDKInstallerSelectionWizardPage extends WizardPage {
+
+	private TableViewer sdkTable;
+	private final IBuildMachine buildMachine;
+	private Scratchbox1SDKInstallerData sdkInstallerData;
+	private Text scratchboxLocationText;
+	private Text userGroup;
+	private Text userList;
+	protected boolean isForceRemove;
+	protected boolean useCache;
+	private Button useCacheButton;
+
+	/**
+	 * @param pageName
+	 */
+	protected Scratchbox1SDKInstallerSelectionWizardPage( 
+			IBuildMachine buildMachine) {
+		super("target", "Select SDK", Activator.getImageDescriptor("icons/wizban/target_wizban.gif"));
+		this.buildMachine = buildMachine;
+		setDescription("Select and configure the Scratchbox 1 version you want to install.");
+		setPageComplete(false);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
+		setControl(composite);
+		
+		createSDKSelector(composite);
+		createOptionsContent(composite);
+
+		createAdvancedContent(composite);
+		
+		sdkTable.setInput(buildMachine);
+		for (TableColumn column : sdkTable.getTable().getColumns()) {
+			column.pack();
+		}
+	}
+
+	/**
+	 * @param composite
+	 */
+	private void createSDKSelector(Composite composite) {
+		Label label = new Label(composite, SWT.NONE);
+		label.setText("Select a platform:");
+		GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).span(2, 1).applyTo(label);
+		
+		sdkTable = new TableViewer(composite, SWT.BORDER);
+		Scratchbox1SDKInstallerDataContentLabelProvider platformProvider = 
+			new Scratchbox1SDKInstallerDataContentLabelProvider();
+		
+		sdkTable.setContentProvider(platformProvider);
+		sdkTable.setLabelProvider(platformProvider);
+		
+		Table table = sdkTable.getTable();
+		GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo(table);
+		
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		
+		TableColumn column = new TableColumn(table, SWT.LEFT);
+		column.setText("Name");
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText("URL");
+		
+		sdkTable.addSelectionChangedListener(new ISelectionChangedListener() {
+
+			public void selectionChanged(SelectionChangedEvent event) {
+				doChangeSDKChoice((Scratchbox1SDKInstallerData) 
+						((IStructuredSelection) event.getSelection()).getFirstElement());
+				validatePage();
+			}
+			
+		});
+	}
+
+	/**
+	 * @param composite
+	 */
+	private void createScratchboxLocation(Composite composite) {
+		Label label;
+		////
+		
+		label = new Label(composite, SWT.NONE);
+		label.setText("Scratchbox location:");
+		GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+
+		// TODO: make browse button if on local machine...
+		scratchboxLocationText = new Text(composite, SWT.BORDER);
+		scratchboxLocationText.setToolTipText("Specify where Scratchbox 1 will be installed.");
+		
+		GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo(scratchboxLocationText);
+		scratchboxLocationText.addModifyListener(new ModifyListener() {
+
+			public void modifyText(ModifyEvent e) {
+				sdkInstallerData.setInstallLocation(scratchboxLocationText.getText().trim());
+				validatePage();
+			}
+			
+		});
+	}
+
+	/**
+	 * @param composite
+	 */
+	private void createOptionsContent(Composite composite) {
+		final Button forceRemove = new Button(composite, SWT.CHECK);
+		GridDataFactory.swtDefaults().span(2, 1).align(SWT.LEFT, SWT.CENTER).applyTo(forceRemove);
+		forceRemove.setText("Remove existing Scratchbox 1");
+		forceRemove.setToolTipText("If checked, deletes Scratchbox 1 if it is already present.  Back up your user directory first!"); 
+
+		forceRemove.addSelectionListener(new SelectionAdapter() {
+
+			/* (non-Javadoc)
+			 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+			 */
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				isForceRemove = forceRemove.getSelection();
+				validatePage();
+			}
+		});
+
+		useCacheButton = new Button(composite, SWT.CHECK);
+		GridDataFactory.swtDefaults().span(2, 1).align(SWT.LEFT, SWT.CENTER).applyTo(useCacheButton);
+		useCacheButton.setText("Use previous download");
+		useCacheButton.setToolTipText("If checked, continue from a previous download of the components if possible, else, always download."); 
+
+		useCacheButton.addSelectionListener(new SelectionAdapter() {
+
+			/* (non-Javadoc)
+			 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+			 */
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				sdkInstallerData.setUseCache(useCacheButton.getSelection());
+				validatePage();
+			}
+		});
+		
+	}
+
+	/**
+	 * @param composite
+	 */
+	private void createAdvancedContent(Composite composite) {
+		Label label;
+		
+		// spacer
+		label = new Label(composite, SWT.NONE);
+		GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).span(2, 1).applyTo(label);
+		
+		final Button advanced = new Button(composite, SWT.TOGGLE);
+		GridDataFactory.swtDefaults().span(2, 1).applyTo(advanced);
+		advanced.setText("Advanced >>");
+		advanced.setSelection(false);
+		
+		final Composite advancedContent = new Composite(composite, SWT.NONE);
+		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(advancedContent);
+		
+		// exclude content from initial layout
+		GridDataFactory.fillDefaults().grab(true, false).exclude(true).span(2, 1).applyTo(advancedContent);
+		advancedContent.setVisible(false);
+		
+		///
+		
+		// do not recommend moving from /scratchbox, since .tar.gz installation
+		// might fail to properly install due to user group issues
+		createScratchboxLocation(advancedContent);
+
+		label = new Label(advancedContent, SWT.NONE);
+		label.setText("Users to register:");
+		GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+		
+		userList = new Text(advancedContent, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(userList);
+		userList.setToolTipText("Specify the comma-separated list of users who will use Scratchbox.");
+
+		userList.addModifyListener(new ModifyListener() {
+
+			public void modifyText(ModifyEvent e) {
+				sdkInstallerData.setUserList(userList.getText().replaceAll("\\s+", ""));
+				validatePage();
+			}
+		});
+
+		label = new Label(advancedContent, SWT.NONE);
+		label.setText("Scratchbox user group:");
+		GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+		
+		userGroup = new Text(advancedContent, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(userGroup);
+		userGroup.setToolTipText("Specify the user group for Scratchbox users.  This is usually 'sbox' unless you have specific needs.");
+
+		userGroup.addModifyListener(new ModifyListener() {
+
+			public void modifyText(ModifyEvent e) {
+				sdkInstallerData.setUserGroup(userGroup.getText().trim());
+				validatePage();
+			}
+		});
+		
+		///
+
+		advanced.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				if (advanced.getSelection()) {
+					advancedContent.setVisible(true);
+					((GridData) advancedContent.getLayoutData()).exclude = false;
+					advanced.setText("<< Advanced");
+				} else {
+					advancedContent.setVisible(false);
+					((GridData) advancedContent.getLayoutData()).exclude = true;
+					advanced.setText("Advanced >>");
+				}
+				//advancedContent.layout(true, true);
+				//getShell().layout(true, true);
+				getShell().pack();
+			}
+		});
+	}
+
+	/**
+	 * 
+	 */
+	protected void validatePage() {
+		setErrorMessage(null);
+		setMessage(null);
+		setPageComplete(false);
+
+		if (sdkInstallerData == null) {
+			setErrorMessage("An SDK must be selected");
+			return;
+		}
+		
+		String loc = sdkInstallerData.getScratchboxLocation();
+		if (TextUtils.isEmpty(loc) || !loc.endsWith("/scratchbox")) {
+			setErrorMessage("The location of Scratchbox 1 must end in '/scratchbox'.");
+			return;
+		}
+		if (!isForceRemove) {
+			IFileStore sboxRoot = buildMachine.getFileSystemAccess().getFileStore(
+					new Path(sdkInstallerData.getScratchboxLocation()));
+			if (sboxRoot.fetchInfo().exists()) {
+				setErrorMessage(MessageFormat.format(
+						"The directory ''{1}'' already exists on ''{0}''",
+						buildMachine.getName(),
+						sdkInstallerData.getScratchboxLocation()));
+				return;
+			}
+		}
+		if (sdkInstallerData.isNonDefaultInstallation()) {
+			setMessage(
+					"Using the non-default directory is not recommended; you may need to manually fix some issues after installation.", 
+					WARNING);
+		}
+		setPageComplete(true);
+	}
+
+	/**
+	 * @param data
+	 */
+	protected void doChangeSDKChoice(Scratchbox1SDKInstallerData data) {
+		sdkInstallerData = data;
+		if (data != null) {
+			userList.setText(data.getUserList());
+			userGroup.setText(data.getUserGroup());
+			scratchboxLocationText.setText(data.getScratchboxLocation());
+			useCacheButton.setSelection(data.isUseCache());
+		}
+	}
+
+	/**
+	 * Get the data collected from the wizard page.
+	 * @return data or <code>null</code>
+	 * 
+	 */
+	public Scratchbox1SDKInstallerData getSDKInstallerData() {
+		return sdkInstallerData;
+	}
+	
+	/**
+	 * Tell whether the user wants to delete an existing Scratchbox 1 installation
+	 */
+	public boolean isForceRemove() {
+		return isForceRemove;
+	}
+}
+

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerData.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerData.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerData.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,275 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
+
+/**
+ * This class represents the data used to run the installer script for a Maemo 
+ * Scratchbox 1 platform.
+ * @author eswartz
+ *
+ */
+class Scratchbox1TargetInstallerData {
+	
+	private URL installerURL;
+	private final String name;
+	private final String[] requiredCompilers;
+	private final String[] requiredDevkits;
+	private final String[] qemuChoices;
+	private String baseTarget;
+	
+	private String qemu;
+	private IScratchbox1SDK sdk;
+	private boolean freeComponentsOnly;
+	private boolean forceRemove;
+	
+	/**
+	 * 
+	 */
+	public Scratchbox1TargetInstallerData(String name, URL installerURL, 
+			IScratchbox1SDK sdk, String baseTarget, 
+			String[] qemuChoices,
+			String[] requiredCompilers,
+			String[] requiredDevkits
+		) {
+		if (name == null || installerURL == null || qemuChoices == null || requiredDevkits == null ||
+				requiredCompilers == null) 
+			throw new NullPointerException();
+		
+		this.name = name;
+		this.installerURL = installerURL;
+		this.sdk = sdk;
+		this.baseTarget = baseTarget;
+		this.qemuChoices = qemuChoices;
+		this.requiredCompilers = requiredCompilers;
+		this.requiredDevkits = requiredDevkits;
+		this.qemu = qemuChoices != null && qemuChoices.length > 0 ? qemuChoices[0] : null;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((installerURL == null) ? 0 : installerURL.hashCode());
+		result = prime * result + ((name == null) ? 0 : name.hashCode());
+		return result;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		Scratchbox1TargetInstallerData other = (Scratchbox1TargetInstallerData) obj;
+		if (installerURL == null) {
+			if (other.installerURL != null)
+				return false;
+		} else if (!installerURL.equals(other.installerURL))
+			return false;
+		if (name == null) {
+			if (other.name != null)
+				return false;
+		} else if (!name.equals(other.name))
+			return false;
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		return name;
+	}
+	
+	/**
+	 * @return the display name of the platform/SDK/etc to install
+	 */
+	public String getName() {
+		return name;
+	}
+	
+	/**
+	 * Get the URL to the installer script
+	 * @return
+	 */
+	public URL getInstallerURL() {
+		return installerURL;
+	}
+
+	/**
+	 * Get the legal QEMU choices for the target (first one is preferred)
+	 * @return QEMU binaries (never <code>null</code>)
+	 */
+	public String[] getQEMUChoices() {
+		return qemuChoices;
+	}
+	
+	/**
+	 * @return the array of devkits that must be available in scratchbox
+	 */
+	public String[] getRequiredDevkits() {
+		return requiredDevkits;
+	}
+	
+	/**
+	 * @return the array of toolchains that must be available in scratchbox
+	 */
+	public String[] getRequiredCompilers() {
+		return requiredCompilers;
+	}
+	
+	/**
+	 * @return the scratchboxLocation
+	 */
+	public String getScratchboxLocation() {
+		return sdk.getInstallRoot().toPortableString();
+	}
+	
+	/**
+	 * Get the SDK we're installing into.
+	 */
+	public IScratchbox1SDK getScratchbox1SDK() {
+		return sdk;
+	}
+
+	/**
+	 * Set the SDK we're installing into.
+	 */
+	public void setScratchbox1SDK(IScratchbox1SDK sdk) {
+		this.sdk = sdk;
+	}
+	
+	/**
+	 * Set the QEMU (CPU transparency) to use
+	 */
+	public void setQemu(String qemu) {
+		this.qemu = qemu;
+	}
+	
+	/**
+	 * Get the QEMU (CPU transparency) to use
+	 */
+	public String getQemu() {
+		return qemu;
+	}
+
+	/**
+	 * Get the base name used in the target(s) installed.
+	 */
+	public String getBaseTarget() {
+		return baseTarget;
+	}
+	
+	/**
+	 * @param baseTarget the baseTarget to set
+	 */
+	public void setBaseTarget(String baseTarget) {
+		this.baseTarget = baseTarget;
+	}
+
+	/**
+	 * Tell whether the user should be prompted to install Nokia EUSA binaries
+	 */
+	public boolean isFreeComponentsOnly() {
+		return freeComponentsOnly;
+	}
+	
+	/**
+	 * Tell whether the user should be prompted to install Nokia EUSA binaries
+	 */
+	public void setFreeComponentsOnly(boolean freeComponentsOnly) {
+		this.freeComponentsOnly = freeComponentsOnly;
+	}
+
+	/**
+	 * Tell whether existing targets should be deleted if present
+	 */
+	public boolean isForceRemove() {
+		return forceRemove;
+	}
+	
+	/**
+	 * Tell whether existing targets should be deleted if present
+	 */
+	public void setForceRemove(boolean forceRemove) {
+		this.forceRemove = forceRemove;
+	}
+
+	/**
+	 * Get the name of the X86 target, given the default basename
+	 */
+	public String getX86TargetName() {
+		return baseTarget + "_X86";
+	}
+
+	/**
+	 * Get the name of the ARMEL target, given the default basename
+	 */
+	public String getARMELTargetName() {
+		return baseTarget + "_ARMEL";
+	}
+
+	/**
+	 * Get the command line to run the installer
+	 * @param installScript
+	 * @return command line
+	 */
+	public List<String> createInstallerCommandLine(IPath installScript) {
+		List<String> cmdLine = new ArrayList<String>();
+		
+		cmdLine.add(installScript.toPortableString());
+		
+		// use defaults: we cannot run interactively, since this
+		// script pops up dialogs which we can't handle outside a TTY
+		cmdLine.add("-d");
+		
+		if (getScratchboxLocation() != null) {
+			cmdLine.add("-s");
+			cmdLine.add(getScratchboxLocation());
+		}
+		if (getBaseTarget() != null) {
+			cmdLine.add("-n");
+			cmdLine.add(getBaseTarget());
+		}
+		if (getQemu() != null) {
+			cmdLine.add("-q");
+			cmdLine.add(getQemu());
+		}
+		if (isFreeComponentsOnly()) {
+			cmdLine.add("-f");
+		}
+		if (isForceRemove()) {
+			cmdLine.add("-y");
+		}
+		
+		
+		return cmdLine;
+	}
+
+}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerDataContentLabelProvider.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerDataContentLabelProvider.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerDataContentLabelProvider.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.viewers.BaseLabelProvider;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.graphics.Image;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.esbox.scratchbox.core.sdk.ScratchboxSDKFacade;
+import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
+import org.maemo.mica.common.ui.CommonUIImages;
+
+/**
+ * @author eswartz
+ *
+ */
+public class Scratchbox1TargetInstallerDataContentLabelProvider extends BaseLabelProvider 
+	implements IStructuredContentProvider, ITableLabelProvider {
+
+	private List<Scratchbox1TargetInstallerData> platforms;
+
+	private Image platformImage;
+	
+	/**
+	 * 
+	 */
+	public Scratchbox1TargetInstallerDataContentLabelProvider() {
+		platforms = new ArrayList<Scratchbox1TargetInstallerData>();
+		platformImage = CommonUIImages.getImage(CommonUIImages.SDK_OBJ);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
+	 */
+	public Object[] getElements(Object inputElement) {
+		synchronized (platforms) {
+			return platforms.toArray();
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
+	 */
+	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
+		if (newInput != null) {
+	
+			List<IScratchbox1SDK> sdks = ScratchboxSDKFacade.getInstance().getScratchboxSDK(
+					IScratchbox1SDK.class);
+			
+			platforms.clear();
+	
+			// TODO: make this list more dynamic
+			try {
+				platforms.add(new Scratchbox1TargetInstallerData(
+						"Maemo 4.1.2 Diablo",
+						new URL("http://repository.maemo.org/stable/4.1.2/maemo-sdk-install_4.1.2.sh"),
+						sdks.size() > 0 ? sdks.get(0) : null,
+						"DIABLO",
+						new String[] { "qemu-arm-0.8.2-sb2", "qemu-arm-cvs", "qemu-arm-cvs-m" },
+						new String[] { "cs2005q3.2-glibc2.5-arm", "cs2005q3.2-glibc2.5-i386"  },
+						new String[] { "perl", "debian-etch", "maemo3-tools", "cputransp" }
+				));
+				platforms.add(new Scratchbox1TargetInstallerData(
+						"Maemo 5.0 Fremantle (UNSTABLE)",
+						new URL("http://repository.maemo.org/unstable/fremantle/maemo-sdk-install_5.0.sh"),
+						sdks.size() > 0 ? sdks.get(0) : null,
+						"FREMANTLE",
+						new String[] { "qemu-arm-cvs-m", "qemu-arm-cvs" },
+						new String[] { "cs2007q3-glibc2.5-arm7", "cs2007q3-glibc2.5-i486" },
+						new String[] { "perl", "debian-etch", "doctools", "svn", "git", "cputransp" }
+				));
+			} catch (MalformedURLException e) {
+				Activator.getErrorLogger().logAndShowError(null, e);
+			}
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.LabelProvider#getText(java.lang.Object)
+	 */
+	public String getColumnText(Object element, int column) {
+		if (element instanceof Scratchbox1TargetInstallerData) {
+			Scratchbox1TargetInstallerData data = (Scratchbox1TargetInstallerData) element;
+			if (column == 0)
+				return data.getName();
+			else
+				return data.getInstallerURL().toString();
+		}
+		return "";
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.viewers.LabelProvider#getImage(java.lang.Object)
+	 */
+	public Image getColumnImage(Object element, int column) {
+		if (element instanceof Scratchbox1TargetInstallerData) {
+			if (column == 0)
+				return platformImage;
+		}
+		return null;
+	}
+
+}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerEngine.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerEngine.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerEngine.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,137 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.util.List;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.MultiStatus;
+import org.eclipse.core.runtime.SubProgressMonitor;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.swt.widgets.Shell;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.mica.common.core.IProgressReporter;
+import org.maemo.mica.common.core.MicaException;
+import org.maemo.mica.common.core.env.IEnvironmentModifierBlock;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+import org.maemo.mica.common.core.process.IProcessLauncherFactory;
+import org.maemo.mica.common.core.process.IStreamMonitor;
+import org.maemo.mica.common.core.process.ProcessLauncherCreator;
+import org.maemo.mica.common.core.process.ProcessLauncherUtils;
+
+/**
+ * This engine runs the SDK installer script in non-interactive mode,
+ * passing the settings from {@link Scratchbox1TargetInstallerData} to the script,
+ * feeding the output to the progress reporter, and checking the output for stderr
+ * text and other error messages.  Also, it presents the license agreement to the user
+ * in an SWT confirmation dialog.
+ * <p>
+ * The script must be run in "defaults" mode, which limits some of the settings
+ * we can control, because otherwise it runs "dialog" which won't work in 
+ * our non-terminal process launch model.
+ * @author eswartz
+ *
+ */
+public class Scratchbox1TargetInstallerEngine extends BaseScratchbox1SDKInstallerEngine {
+
+	private final Scratchbox1TargetInstallerData installerData;
+
+	/**
+	 * @param progressReporter
+	 */
+	public Scratchbox1TargetInstallerEngine(
+			Shell shell,
+			IBuildMachine machine,
+			Scratchbox1TargetInstallerData installerData,
+			IProgressReporter progressReporter) {
+		super(shell, machine, progressReporter);
+		this.installerData = installerData;
+	}
+
+	/**
+	 * Perform the installation, logging results to the progress reporter.
+	 * Return the overall status (OK, CANCEL, ERROR)
+	 * @param shell
+	 * @param monitor
+	 * @return IStatus
+	 */
+	public IStatus installTargets(IProgressMonitor monitor) {
+		MultiStatus multiStatus = new MultiStatus(Activator.PLUGIN_ID, 0, null, null);
+		
+		IStatus status;
+		monitor.beginTask("", IProgressMonitor.UNKNOWN);
+		
+		reporter.logInfo("Installing " + installerData.getName());
+		
+		IPath installScript = fetchInstallScript(multiStatus, monitor, installerData.getInstallerURL());
+		
+		// our own work that the script doesn't handle
+		monitor.subTask("Cleaning Scratchbox sessions...");
+		final boolean[] kill = { false };
+		shell.getDisplay().syncExec(new Runnable() {
+			public void run() {
+				kill[0] = MessageDialog.openQuestion(null,
+						"Clean Up Sessions",
+						"Nothing should be running in Scratchbox during the installation.\n\n"
+							+ "Kill existing Scratchbox sessions?  (You may manually close them first, if desired, then select 'No' to continue.)");		
+			}
+		});
+		
+		if (kill[0]) {
+			try {
+				installerData.getScratchbox1SDK().killSessions();
+			} catch (MicaException e1) {
+				status = Activator.createErrorStatus("Cannot kill Scratchbox sessions", e1);
+				reporter.log(status);
+				multiStatus.add(status);
+			}
+		}
+		
+		reporter.logInfo("Running script...");
+		monitor.subTask("Running script...");
+		
+		IProcessLauncherFactory factory = machine.getProcessLauncherFactory();
+		
+		List<String> cmdLine = installerData.createInstallerCommandLine(installScript);
+		IEnvironmentModifierBlock envBlock = getProxySetupEnvironmentBlock(factory);
+		
+		int exit;
+		try {
+			exit = ProcessLauncherUtils.launchAndMonitorStandardStreams(
+					ProcessLauncherCreator.createProcessLauncher(factory, 
+							null,
+							cmdLine,
+							envBlock),
+					new IStreamMonitor[] {
+						new MaemoScriptInstallerMonitor(shell, reporter)
+					},
+					new SubProgressMonitor(monitor, IProgressMonitor.UNKNOWN));
+		} catch (MicaException e) {
+			status = Activator.createErrorStatus("Failed to run installer script", e);
+			reporter.log(status);
+			multiStatus.add(status);
+			return multiStatus;
+		}
+		
+		if (exit != 0) {
+			multiStatus.add(Activator.createErrorStatus("Installation script failed with exit code " + exit, null));
+		}
+		
+		monitor.done();
+		
+		
+		return multiStatus;
+	}
+
+}

Added: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerSelectionWizardPage.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerSelectionWizardPage.java	                        (rev 0)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/internal/scratchbox/sb1/ui/wizard/Scratchbox1TargetInstallerSelectionWizardPage.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -0,0 +1,518 @@
+/*******************************************************************************
+ * Copyright (c) 2009 Nokia Corporation
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *    Ed Swartz (Nokia) - initial API and implementation
+ *******************************************************************************/
+
+package org.maemo.esbox.internal.scratchbox.sb1.ui.wizard;
+
+import java.lang.reflect.InvocationTargetException;
+import java.text.MessageFormat;
+import java.util.List;
+
+import org.eclipse.core.filesystem.IFileStore;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.Path;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.jface.viewers.ArrayContentProvider;
+import org.eclipse.jface.viewers.ComboViewer;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+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.layout.GridData;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.maemo.esbox.internal.scratchbox.sb1.Activator;
+import org.maemo.esbox.scratchbox.core.sdk.ScratchboxSDKFacade;
+import org.maemo.esbox.scratchbox.sb1.sdk.IScratchbox1SDK;
+import org.maemo.mica.common.core.MicaException;
+import org.maemo.mica.common.core.machine.IBuildMachine;
+import org.maemo.mica.common.core.sdk.SDKFactory;
+
+import com.nokia.cpp.internal.api.utils.core.TextUtils;
+
+/**
+ * This page allows the user to select one of the supported installer scripts
+ * to install a Scratchbox 1 Maemo SDK (which installs multiple targets).
+ * @author eswartz
+ *
+ */
+public class Scratchbox1TargetInstallerSelectionWizardPage extends WizardPage {
+
+	private TableViewer platformTable;
+	private final IBuildMachine buildMachine;
+	private ComboViewer qemuCombo;
+	private Scratchbox1TargetInstallerData targetInstallerData;
+	private Text baseTargetText;
+	private boolean doRefreshSDK;
+	private ComboViewer sboxCombo;
+	protected IScratchbox1SDK sdk;
+
+	/**
+	 * @param sdk 
+	 * @param pageName
+	 */
+	protected Scratchbox1TargetInstallerSelectionWizardPage(IBuildMachine buildMachine) {
+		super("target", "Select Platform", Activator.getImageDescriptor("icons/wizban/target_wizban.gif"));
+		this.buildMachine = buildMachine;
+		setDescription("Select the platform with which you want to use Scratchbox and configure it for your needs.");
+		setPageComplete(false);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite)
+	 */
+	public void createControl(Composite parent) {
+		Composite composite = new Composite(parent, SWT.NONE);
+		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(composite);
+		GridDataFactory.fillDefaults().grab(true, true).applyTo(composite);
+		setControl(composite);
+		
+		// first, show what SDK we're using
+		//Label label = new Label(composite, SWT.NONE);
+		//label.setText("Installing target under " + sdk.getDisplayName() + " at " + sdk.getInstallLocation());
+		//GridDataFactory.fillDefaults().grab(true, false).span(2, 1).applyTo(label);
+		//
+		//label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
+		//GridDataFactory.fillDefaults().grab(true, false).span(2, 3).applyTo(label);
+
+		createTargetSelector(composite);
+		createOptionsContent(composite);
+
+		createAdvancedContent(composite);
+		
+		List<IScratchbox1SDK> sdks = ScratchboxSDKFacade.getInstance().getScratchboxSDK(IScratchbox1SDK.class);
+		sboxCombo.setInput(sdks);
+		if (sdks.size() > 0)
+			sboxCombo.setSelection(new StructuredSelection(sdks.get(0)));
+		
+		platformTable.setInput(new Object());
+		for (TableColumn column : platformTable.getTable().getColumns()) {
+			column.pack();
+		}
+	}
+
+	/**
+	 * @param composite
+	 */
+	private void createTargetSelector(Composite composite) {
+		
+		Label label = new Label(composite, SWT.NONE);
+		label.setText("Scratchbox installation to use:");
+		GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+
+		sboxCombo = new ComboViewer(composite, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(sboxCombo.getControl());
+		sboxCombo.setContentProvider(new ArrayContentProvider());
+		sboxCombo.setLabelProvider(new LabelProvider());
+		sboxCombo.addSelectionChangedListener(new ISelectionChangedListener() {
+
+			public void selectionChanged(SelectionChangedEvent event) {
+				sdk = ((IScratchbox1SDK) ((IStructuredSelection) event.getSelection()).getFirstElement());
+				if (targetInstallerData != null)
+					targetInstallerData.setScratchbox1SDK(sdk);
+				validatePage();
+			}
+			
+		});
+		
+		label = new Label(composite, SWT.NONE);
+		label.setText("Select a platform:");
+		GridDataFactory.fillDefaults().align(SWT.LEFT, SWT.CENTER).span(2,1).applyTo(label);
+		
+		platformTable = new TableViewer(composite, SWT.BORDER);
+		Scratchbox1TargetInstallerDataContentLabelProvider platformProvider = 
+			new Scratchbox1TargetInstallerDataContentLabelProvider();
+		
+		platformTable.setContentProvider(platformProvider);
+		platformTable.setLabelProvider(platformProvider);
+		
+		Table table = platformTable.getTable();
+		GridDataFactory.fillDefaults().grab(true, true).span(2,1).applyTo(table);
+		
+		table.setHeaderVisible(true);
+		table.setLinesVisible(true);
+		
+		TableColumn column = new TableColumn(table, SWT.LEFT);
+		column.setText("Name");
+		column = new TableColumn(table, SWT.LEFT);
+		column.setText("URL");
+		
+		platformTable.addSelectionChangedListener(new ISelectionChangedListener() {
+
+			public void selectionChanged(SelectionChangedEvent event) {
+				doChangeTargetChoice((Scratchbox1TargetInstallerData) 
+						((IStructuredSelection) event.getSelection()).getFirstElement());
+				validatePage();
+			}
+			
+		});
+	}
+
+	/**
+	 * @param composite
+	 */
+	/*
+	private void createScratchboxLocation(Composite composite) {
+		Label label;
+		////
+		
+		label = new Label(composite, SWT.NONE);
+		label.setText("Scratchbox location:");
+		GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+
+		// TODO: make browse button if on local machine...
+		scratchboxLocationText = new Text(composite, SWT.BORDER);
+		scratchboxLocationText.setToolTipText("Specify where Scratchbox 1 was installed.");
+		
+		GridDataFactory.swtDefaults().align(SWT.FILL, SWT.CENTER).applyTo(scratchboxLocationText);
+		scratchboxLocationText.addModifyListener(new ModifyListener() {
+
+			public void modifyText(ModifyEvent e) {
+				sdkInstallerData.setScratchboxLocation(scratchboxLocationText.getText());
+				validatePage();
+			}
+			
+		});
+	}*/
+
+	/**
+	 * @param composite
+	 */
+	private void createOptionsContent(Composite composite) {
+		
+		// spacer
+		//Label label = new Label(composite, SWT.NONE);
+		//GridDataFactory.swtDefaults().span(2, 1).align(SWT.LEFT, SWT.CENTER).applyTo(label);
+		
+		final Button forceRemove = new Button(composite, SWT.CHECK);
+		GridDataFactory.swtDefaults().span(2, 1).align(SWT.LEFT, SWT.CENTER).applyTo(forceRemove);
+		forceRemove.setText("Remove existing targets");
+		forceRemove.setToolTipText("If checked, remove existing targets if they already exist."); 
+
+		forceRemove.addSelectionListener(new SelectionAdapter() {
+
+			/* (non-Javadoc)
+			 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+			 */
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				targetInstallerData.setForceRemove(forceRemove.getSelection());
+				validatePage();
+			}
+		});
+
+		final Button freeOrLicensed = new Button(composite, SWT.CHECK);
+		GridDataFactory.swtDefaults().span(2, 1).align(SWT.LEFT, SWT.CENTER).applyTo(freeOrLicensed);
+		freeOrLicensed.setText("Open source content only?");
+		freeOrLicensed.setToolTipText("If checked, do not ask to install Nokia closed-source binaries."); 
+
+		freeOrLicensed.addSelectionListener(new SelectionAdapter() {
+
+			/* (non-Javadoc)
+			 * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+			 */
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				targetInstallerData.setFreeComponentsOnly(freeOrLicensed.getSelection());
+			}
+		});
+	}
+
+	/**
+	 * @param composite
+	 */
+	private void createAdvancedContent(Composite composite) {
+		Label label;
+		
+		// spacer
+		label = new Label(composite, SWT.NONE);
+		GridDataFactory.swtDefaults().span(2, 1).align(SWT.LEFT, SWT.CENTER).applyTo(label);
+		
+		//Group group = new Group(composite, SWT.NONE);
+		//GridLayoutFactory.fillDefaults().numColumns(2).applyTo(group);
+		//GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo(group);
+		Composite group = composite;
+		
+		final Button advanced = new Button(group, SWT.TOGGLE);
+		GridDataFactory.swtDefaults().span(2, 1).applyTo(advanced);
+		advanced.setText("Advanced >>");
+		advanced.setSelection(false);
+		
+		final Composite advancedContent = new Composite(group, SWT.NONE);
+		GridLayoutFactory.fillDefaults().numColumns(2).applyTo(advancedContent);
+		
+		// exclude content from initial layout
+		GridDataFactory.fillDefaults().grab(true, false).span(2, 1).exclude(true).applyTo(advancedContent);
+		advancedContent.setVisible(false);
+		
+		///
+		
+		label = new Label(advancedContent, SWT.NONE);
+		label.setText("QEMU version to use:");
+		GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+
+		qemuCombo = new ComboViewer(advancedContent, SWT.BORDER);
+		GridDataFactory.fillDefaults().grab(true, false).applyTo(qemuCombo.getControl());
+		qemuCombo.setContentProvider(new ArrayContentProvider());
+		qemuCombo.setLabelProvider(new LabelProvider());
+		qemuCombo.addSelectionChangedListener(new ISelectionChangedListener() {
+
+			public void selectionChanged(SelectionChangedEvent event) {
+				targetInstallerData.setQemu(((String) ((IStructuredSelection) event.getSelection()).getFirstElement()));
+				validatePage();
+			}
+			
+		});
+		
+		///
+		
+		label = new Label(advancedContent, SWT.NONE);
+		label.setText("Base target name:");
+		GridDataFactory.swtDefaults().align(SWT.LEFT, SWT.CENTER).applyTo(label);
+
+		baseTargetText = new Text(advancedContent, SWT.BORDER);
+		baseTargetText.setToolTipText("Specify the base target name for the X86 and ARMEL targets.");
+		
+		GridDataFactory.fillDefaults().hint(200, -1).applyTo(baseTargetText);
+		
+		label = new Label(advancedContent, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(label);
+		
+		final Label targetPreview = new Label(advancedContent, SWT.NONE);
+		GridDataFactory.fillDefaults().applyTo(targetPreview);
+		
+		baseTargetText.addModifyListener(new ModifyListener() {
+
+			public void modifyText(ModifyEvent e) {
+				String baseTarget = baseTargetText.getText();
+				targetInstallerData.setBaseTarget(baseTarget);
+				targetPreview.setText("(targets: " + targetInstallerData.getX86TargetName() 
+						+ " and " + targetInstallerData.getARMELTargetName() + ")");
+				validatePage();
+			}
+			
+		});
+
+		///
+
+		advanced.addSelectionListener(new SelectionAdapter() {
+			@Override
+			public void widgetSelected(SelectionEvent e) {
+				if (advanced.getSelection()) {
+					advancedContent.setVisible(true);
+					((GridData) advancedContent.getLayoutData()).exclude = false;
+					advanced.setText("<< Advanced");
+				} else {
+					advancedContent.setVisible(false);
+					((GridData) advancedContent.getLayoutData()).exclude = true;
+					advanced.setText("Advanced >>");
+				}
+				//advancedContent.layout(true, true);
+				//getShell().layout(true, true);
+				getShell().pack();
+			}
+		});
+	}
+
+	/* (non-Javadoc)
+	 * @see org.eclipse.jface.dialogs.DialogPage#setVisible(boolean)
+	 */
+	@Override
+	public void setVisible(boolean visible) {
+		super.setVisible(visible);
+		if (visible) {
+			// recheck if the page is seen again, in case previous installation was aborted
+			doRefreshSDK = true;
+			validatePage();
+		}
+	}
+	
+	/**
+	 * 
+	 */
+	protected void validatePage() {
+		setErrorMessage(null);
+		setMessage(null);
+		setPageComplete(false);
+
+		if (sdk == null) {
+			setErrorMessage("An installation of Scratchbox 1 must be selected");
+			return;
+		}
+		if (targetInstallerData == null) {
+			setErrorMessage("A platform must be selected");
+			return;
+		}
+		IFileStore sboxRoot = buildMachine.getFileSystemAccess().getFileStore(
+				new Path(targetInstallerData.getScratchboxLocation()));
+		if (!sboxRoot.fetchInfo().exists()) {
+			setErrorMessage(MessageFormat.format(
+					"Directory not found on build machine ''{0}'':  ''{1}''",
+					buildMachine.getName(),
+					targetInstallerData.getScratchboxLocation()));
+			return;
+		}
+		
+		if (TextUtils.isEmpty(targetInstallerData.getQemu())) {
+			setErrorMessage("The QEMU variant must be specified");
+			return;
+		}
+		if (TextUtils.isEmpty(targetInstallerData.getBaseTarget())) {
+			setErrorMessage("The target name must be non-empty");
+			return;
+		}
+		
+		// validate scratchbox itself
+		final boolean[] validated = { false };
+		try {
+			getContainer().run(false, true, new IRunnableWithProgress() {
+
+				public void run(IProgressMonitor monitor)
+						throws InvocationTargetException, InterruptedException {
+					validated[0] = validateScratchbox(monitor, targetInstallerData.getScratchbox1SDK());	
+				}
+				
+			});
+		} catch (InvocationTargetException e) {
+			Activator.getErrorLogger().logAndShowError(null, e);
+		} catch (InterruptedException e) {
+		}
+		
+		if (!validated[0])
+			return;
+		
+		setPageComplete(true);
+	}
+
+	/**
+	 * Do ahead of time some of the checks that the script does, so the user doesn't waste time.
+	 * @param sdk
+	 * @return true: the SDK is suitable for the target
+	 */
+	private boolean validateScratchbox(IProgressMonitor monitor, IScratchbox1SDK sdk) {
+		monitor.beginTask("Validating Scratchbox installation", IProgressMonitor.UNKNOWN);
+		
+		StringBuilder errors = new StringBuilder();
+		try {
+			if (doRefreshSDK) {
+				sdk.refresh();
+				SDKFactory.getInstance().fireListeners();
+				doRefreshSDK = false;
+			} else {
+				monitor.worked(5);
+			}
+			
+			List<String> devkits = sdk.getDevkits();
+			List<String> compilers = sdk.getCompilers();
+			for (String reqdDevkit : targetInstallerData.getRequiredDevkits()) {
+				boolean matched = false;
+				for (String devkit : devkits) {
+					if (devkit.equals(reqdDevkit)) {
+						matched = true;
+						break;
+					}
+				}
+				if (!matched) {
+					errors.append("no devkit '" + reqdDevkit + "'; ");
+				}
+			}
+			
+			for (String reqdToolchain : targetInstallerData.getRequiredCompilers()) {
+				boolean matched = false;
+				for (String compiler : compilers) {
+					if (compiler.equals(reqdToolchain)) {
+						matched = true;
+						break;
+					}
+				}
+				if (!matched) {
+					errors.append("no compiler '" + reqdToolchain + "'; ");
+				}
+			}
+			
+			if (errors.length() != 0) {
+				setErrorMessage("This Scratchbox 1 installation is not suitable: " + errors + "please upgrade it or install a new one.");
+				return false;
+			}
+			
+			// check existing targets
+			if (!targetInstallerData.isForceRemove()) {
+				String x86Target = targetInstallerData.getX86TargetName();
+				String armelTarget = targetInstallerData.getARMELTargetName();
+				String targets = "";
+				for (String target : sdk.getTargets()) {
+					if (target.equals(x86Target)
+							|| target.equals(armelTarget)) {
+						if (targets.length() == 0)
+							targets += target;
+						else
+							targets +=", " + target;
+						
+					}
+				}
+				if (targets.length() > 0) {
+					setErrorMessage("This Scratchbox 1 already has targets: " + targets + "; select ''Remove existing targets'' or rename the targets under Advanced.");
+					return false;
+				}
+				
+			}
+			
+			// seems valid (as far as we care in this wizard)
+			return true;
+		} catch (MicaException e) {
+			setErrorMessage("The Scratchbox 1 installation at " + sdk + " has problems; please fix or reinstall it:\n" + e.getMessage());
+			return false;
+		}
+	
+	}
+
+	/**
+	 * @param data
+	 */
+	protected void doChangeTargetChoice(Scratchbox1TargetInstallerData data) {
+		targetInstallerData = data;
+		if (data != null) {
+			//scratchboxLocationText.setText(data.getScratchboxLocation());
+			baseTargetText.setText(data.getBaseTarget());
+			
+			String[] choices = data.getQEMUChoices();
+			qemuCombo.setInput(choices);
+			if (data.getQemu() != null) {
+				qemuCombo.setSelection(new StructuredSelection(data.getQemu()));
+			} else if (choices.length > 0) {
+				// pick one
+				qemuCombo.setSelection(new StructuredSelection(choices[0]));
+			}
+		}
+	}
+
+	/**
+	 * Get the data collected from the wizard page.
+	 * @return data or <code>null</code>
+	 * 
+	 */
+	public Scratchbox1TargetInstallerData getTargetInstallerData() {
+		return targetInstallerData;
+	}
+}

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/scratchbox/sb1/sdk/IScratchbox1SDK.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/scratchbox/sb1/sdk/IScratchbox1SDK.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb1/src/org/maemo/esbox/scratchbox/sb1/sdk/IScratchbox1SDK.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -71,6 +71,14 @@
 	 *             if some problem related to Scratchbox communication occurs.
 	 */
 	public boolean killProcess(String signal) throws MicaException;
+
+	/**
+	 * Kill all the running Scratchbox sessions and processes for any target.
+	 * @throws MicaException 
+	 * @see #killProcess()
+	 * @see #killProcess(String)
+	 */
+	public void killSessions() throws MicaException;
 	
 	public boolean createTarget(String targetName, String compiler,
 			List<String> devkits, String cputransp, boolean force) throws MicaException;

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/command/CreateTargetSb2Command.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/command/CreateTargetSb2Command.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/command/CreateTargetSb2Command.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -17,6 +17,7 @@
 import org.maemo.mica.common.core.MicaException;
 import org.maemo.mica.common.core.process.*;
 import org.maemo.mica.common.core.sdk.ISDK;
+import org.maemo.mica.common.core.sdk.SDKFactory;
 import org.maemo.mica.common.core.sdk.commands.ICommandAbstractor;
 
 import java.util.List;
@@ -94,7 +95,8 @@
 		}
 
 		sdk.refresh();
-
+		SDKFactory.getInstance().fireListeners();
+		
 		return true;
 	}
 

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core/Scratchbox2SDK.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core/Scratchbox2SDK.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core/Scratchbox2SDK.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -63,9 +63,10 @@
 
 	private MaemoRootstrapCommand maemoRootstrapCommand;
 	
-	public Scratchbox2SDK(IMachine machine, String version,
+	public Scratchbox2SDK(IMachine machine, IPath installLocation, 
+			String version,
 			IPreferenceProvider prefProvider) {
-		super(machine, version, "Scratchbox 2", SB2_MACHINE, SB2_VERSION,
+		super(machine, installLocation, version, "Scratchbox 2", SB2_MACHINE, SB2_VERSION,
 				"sb2_targets", 2);
 		this.prefProvider = prefProvider;
 		
@@ -92,13 +93,8 @@
 		return maemoSdkCommand;
 	}
 	
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.maemo.mica.maemosdk.core.sdk.AbstractScratchboxSDK#refresh()
-	 */
-	public void refresh() {
-		super.refresh();
+	public void init() {
+		super.init();
 		
 		// delete any outstanding sessions
 		Activator.getDefault().removeSessions();
@@ -113,10 +109,6 @@
 		
 		List<ISDKTarget> newTargets = new ArrayList<ISDKTarget>();
 		for (String target : targetNames) {
-			// ignore this one, left behind by errant rootstrap installations
-			if (target.equals("libtool_build"))
-				continue;
-			
 			if (maemoRootstrapCommand != null) {
 				IPath rootstrapLocation = null;
 				try{
@@ -135,8 +127,6 @@
 		this.targets = newTargets;
 	}
 
-	
-	
 	public int installRootstrap(String rootstrap, IProgressMonitor monitor) throws MicaException {
 		if (maemoRootstrapCommand == null)
 			throw new MicaException("Cannot launch programs for "+ getName());
@@ -155,7 +145,7 @@
 		// check cached value
 		CacheUtils.getInstance().ensureCurrentMachine(SB2_MACHINE, this.getMachine());
 		String[] targetsArray = (String[]) CacheUtils.getInstance()
-				.getCachedValue(SB_TARGETS);
+				.getCachedValue(sbTargetsKey);
 		if (targetsArray != null)
 			return Arrays.asList(targetsArray);
 		
@@ -164,7 +154,9 @@
 		List<String> targets = listTargetsCommand
 				.performCommand(new ArrayList<String>());
 		
-		CacheUtils.getInstance().setCachedValue(SB_TARGETS, 
+		Collections.sort(targets);
+		
+		CacheUtils.getInstance().setCachedValue(sbTargetsKey, 
 				(String[]) targets.toArray(new String[targets.size()]));
 		
 		return targets;
@@ -178,8 +170,8 @@
 	 * ()
 	 */
 	public ICommandAbstractor getCommandAbstractor() throws MicaException {
-		return getSb2WrappedAbstractor(super.getCommandAbstractor(), this
-				.getMachine());
+		return wrapCommandAbstractorForSDK(super.getCommandAbstractor(),
+				"sb2", getInstallRoot().toPortableString());
 	}
 
 	/*
@@ -310,7 +302,7 @@
 	public synchronized List<String> getInstalledMaemoRootstraps()
 			throws MicaException {
 		ListInstalledMaemoRootstrapsSb2Command command = new ListInstalledMaemoRootstrapsSb2Command(
-				MachineUtils.getHostCommandAbstractor(this.getMachine()));
+				MachineUtils.getHostCommandAbstractor(getMachine()));
 		return command.performCommand(EMPTY_ARGS);
 	}
 
@@ -325,7 +317,7 @@
 	public List<MaemoRootstrap> getAvailableMaemoRootstraps(IMachine machine)
 			throws MicaException {
 		ListAvailableMaemoRootstrapsSb2Command command = new ListAvailableMaemoRootstrapsSb2Command(
-				MachineUtils.getHostCommandAbstractor(this.getMachine()));
+				MachineUtils.getHostCommandAbstractor(getMachine()));
 		return command.performCommand(EMPTY_ARGS);
 	}
 
@@ -348,7 +340,7 @@
 		CreateMaemoRootstrapSb2Command createTargetCommand = new CreateMaemoRootstrapSb2Command(
 				this, getCommandAbstractor(), monitor);
 
-		CacheUtils.getInstance().setCachedValue(SB_TARGETS, null);
+		CacheUtils.getInstance().setCachedValue(sbTargetsKey, null);
 
 		return createTargetCommand.performCommand(params);
 	}
@@ -431,19 +423,20 @@
 	}
 
 	/**
-	 * Return the current version of Scratchbox 2
+	 * Return the current version of Scratchbox 2 (fetched from cache or from command)
 	 * 
 	 * @return the current version of Scratchbox 2.
 	 * @throws MicaException
 	 *             if any problem related to Scratchbox communication occurs,
 	 *             including no scratchbox 2 detected
 	 */
-	public static synchronized String getCurrentSboxVersion(IMachine machine)
+	public synchronized String getCurrentSboxVersion()
 			throws MicaException {
 		// find cached value
+		IMachine machine = getMachine();
 		CacheUtils.getInstance().ensureCurrentMachine(SB2_MACHINE, machine);
-		String version = (String) CacheUtils.getInstance().getCachedValue(
-				SB2_VERSION);
+		String version = (String) CacheUtils.getInstance().getCachedValue(SB2_VERSION);
+		
 		// empty string cached if we didn't detect it
 		if ("".equals(version))
 			return null;
@@ -452,17 +445,13 @@
 
 		// do the hard work
 		MachineUtils.acquireMachine(machine);
-		ICommandAbstractor commandAbstractor = MachineUtils
-				.getHostCommandAbstractor(machine);
-		commandAbstractor = getSb2WrappedAbstractor(commandAbstractor, machine);
 		GetVersionScratchboxCommand getVersionCommand = new GetVersionScratchboxCommand(
-				commandAbstractor);
+				getCommandAbstractor());
 
 		String currentVersion;
 		MicaException exception = null;
 		try {
-			currentVersion = getVersionCommand
-				.performCommand(new ArrayList<String>());
+			currentVersion = getVersionCommand.performCommand(new ArrayList<String>());
 		} catch (MicaException e) {
 			currentVersion = "";
 			exception = e;
@@ -477,20 +466,4 @@
 		return currentVersion;
 	}
 
-
-	/**
-	 * Get a command abstractor that updates the PATH if sb2 tools are not on
-	 * the path.
-	 * 
-	 * @param commandAbstractor
-	 * @param machine
-	 * @return
-	 */
-	private static ICommandAbstractor getSb2WrappedAbstractor(
-			ICommandAbstractor commandAbstractor, IMachine machine) {
-		// XXX: the default path should be provided some other way
-		return wrapCommandAbstractorForSDK(commandAbstractor, machine, "sb2",
-				"/usr/bin");
-	}
-
 }

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core/Scratchbox2SDKTarget.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core/Scratchbox2SDKTarget.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/core/Scratchbox2SDKTarget.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -95,6 +95,18 @@
 					SB2PreferenceConstants.SB2_MAPPING_MODE, false);
 	}
 
+	/* (non-Javadoc)
+	 * @see org.maemo.mica.common.core.sdk.ISDKTarget#getProcessLauncherFactory(java.lang.String)
+	 */
+	public IProcessLauncherFactory getProcessLauncherFactory(String userName) {
+		if (userName.equals("root")) {
+			return new Scratchbox2ProcessLauncherFactory(this,
+					SB2PreferenceConstants.SB2_MAPPING_MODE, true);
+		}
+		// no support for alternate users in Scratchbox
+		return null;
+	}
+		
 	/*
 	 * (non-Javadoc)
 	 * 

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/launcher/Scratchbox2ProcessLauncherFactory.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/launcher/Scratchbox2ProcessLauncherFactory.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/launcher/Scratchbox2ProcessLauncherFactory.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -38,8 +38,8 @@
 	 * @param mappingModeKey
 	 *            one of SB2PreferenceConstants.MAPPING_MODE or
 	 *            SB2PreferenceConstants.INSTALL_MAPPING_MODE
-	 * @param isBuildMode
-	 *            true: build mode, false: installation mode
+	 * @param runAsRoot
+	 *            true: use root privileges; false: run as normal user
 	 */
 	public Scratchbox2ProcessLauncherFactory(IScratchbox2SDKTarget sdkTarget,
 			String mappingModeKey, boolean runAsRoot) {

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/provider/Scratchbox2SDKProvider.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/provider/Scratchbox2SDKProvider.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/provider/Scratchbox2SDKProvider.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -12,12 +12,15 @@
 package org.maemo.esbox.internal.scratchbox.sb2.provider;
 
 import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.core.runtime.Platform;
+import org.eclipse.jface.wizard.IWizardNode;
 import org.maemo.esbox.internal.api.scratchbox.core.sdk.CacheUtils;
 import org.maemo.esbox.internal.scratchbox.sb2.Activator;
 import org.maemo.esbox.internal.scratchbox.sb2.core.Scratchbox2SDK;
 import org.maemo.esbox.scratchbox.core.scratchbox.ScratchboxException;
 import org.maemo.mica.common.core.*;
+import org.maemo.mica.common.core.machine.IBuildMachine;
 import org.maemo.mica.common.core.machine.IMachine;
 import org.maemo.mica.common.core.machine.MachineRegistry;
 import org.maemo.mica.common.core.sdk.*;
@@ -25,6 +28,8 @@
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 /**
@@ -45,7 +50,7 @@
 	 */
 	public Scratchbox2SDKProvider() {
 	}
-
+	
 	/*
 	 * (non-Javadoc)
 	 * 
@@ -68,16 +73,23 @@
 				Scratchbox2SDK sdk = getMachineSDK(prefProvider, machine);
 				if (sdk != null) {
 					sdks.add(sdk);
-					sdk.refresh();
+					sdk.init();
 				}
 			} catch (ScratchboxException e) {
 				logger.log(IStatus.INFO,
 						"Problem scanning Scratchbox 2 installation", e);
 			}
 		}
-
 		CacheUtils.getInstance().saveCachedData();
 
+		Collections.sort(sdks, new Comparator<ISDK>() {
+
+			public int compare(ISDK o1, ISDK o2) {
+				return o1.getName().compareTo(o2.getName());
+			}
+			
+		});
+		
 		return sdks;
 	}
 
@@ -90,28 +102,27 @@
 	 */
 	private Scratchbox2SDK getMachineSDK(IPreferenceProvider prefProvider,
 			IMachine machine) throws MicaException {
+		
 		ErrorLogger logger = Activator.getErrorLogger();
+		
+		// only support one Scratchbox 2 installation
+		Scratchbox2SDK sdk = new Scratchbox2SDK(machine, new Path("/usr/bin"), null, prefProvider);
 
-		// only support one Scratchbox 2 installation
-		String version = Scratchbox2SDK.getCurrentSboxVersion(machine);
+		String version = sdk.getCurrentSboxVersion();
 		if (version == null) {
 			// no scratchbox?
 			return null;
 		}
 
 		if (!version.matches(SCRATCHBOX_VERSION_PATTERN)) {
-			logger
-					.logError(
-							MessageFormat
-									.format(
-											"Only Scratchbox 2 version 1.99.x is supported (detected {0}); disabling Scratchbox 2 support",
-											version), null);
+			logger.logError(MessageFormat.format(
+				"Only Scratchbox 2 version 1.99.x is supported (detected {0}); disabling Scratchbox 2 support",
+				version), null);
 			return null;
 		}
 
-		Scratchbox2SDK sdk = new Scratchbox2SDK(machine, version, prefProvider);
+		sdk.setVersion(version);
 
 		return sdk;
 	}
-
 }

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters/MaemoScratchbox2SDKManageTargetAdapter.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters/MaemoScratchbox2SDKManageTargetAdapter.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters/MaemoScratchbox2SDKManageTargetAdapter.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -12,35 +12,27 @@
 
 package org.maemo.esbox.internal.scratchbox.sb2.ui.adapters;
 
-import org.eclipse.core.runtime.*;
-import org.eclipse.jface.dialogs.Dialog;
-import org.eclipse.jface.dialogs.IDialogConstants;
-import org.eclipse.jface.wizard.WizardDialog;
+import java.util.List;
+
+import org.eclipse.core.runtime.IProgressMonitor;
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.MessageBox;
 import org.eclipse.swt.widgets.Shell;
 import org.maemo.esbox.internal.api.scratchbox.ui.adapters.MaemoScratchboxSDKManageTargetAdapterBase;
 import org.maemo.esbox.internal.scratchbox.sb2.Activator;
-import org.maemo.esbox.internal.scratchbox.sb2.ui.wizard.NewScratchbox2TargetWizard;
 import org.maemo.esbox.scratchbox.sb2.sdk.IScratchbox2SDK;
 import org.maemo.esbox.scratchbox.sb2.sdk.MaemoRootstrap;
 import org.maemo.mica.common.core.MicaException;
-import org.maemo.mica.common.core.Policy;
-import org.maemo.mica.common.core.adapters.ISDKManageTargetAdapter;
 import org.maemo.mica.common.core.sdk.ISDK;
 import org.maemo.mica.common.core.sdk.ISDKTarget;
 import org.maemo.mica.internal.api.maemosdk.ui.adapters.MaemoTargetRemover;
 
-import java.util.List;
-
 /**
  * @author eswartz
  * 
  */
-public class MaemoScratchbox2SDKManageTargetAdapter extends
-		MaemoScratchboxSDKManageTargetAdapterBase implements
-		ISDKManageTargetAdapter {
+public class MaemoScratchbox2SDKManageTargetAdapter extends MaemoScratchboxSDKManageTargetAdapterBase {
 
 	private final IScratchbox2SDK sdk;
 
@@ -51,25 +43,6 @@
 		this.sdk = sdk;
 	}
 
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.maemo.mica.common.core.adapters.ISDKManageTargetAdapter#installSDKTargets
-	 * (org.eclipse.swt.widgets.Shell, java.util.List)
-	 */
-	public IStatus installSDKTargets(Shell shell, List<ISDKTarget> installed) {
-		NewScratchbox2TargetWizard targetWizard;
-
-		targetWizard = new NewScratchbox2TargetWizard(sdk);
-		WizardDialog dlg = new WizardDialog(shell, targetWizard);
-		if (dlg.open() == Dialog.OK) {
-			return Status.OK_STATUS;
-		}
-
-		return Policy.getCancelStatus(Activator.getDefault());
-	}
-
 	protected MaemoTargetRemover createTargetRemover(Shell shell,
 			ISDKTarget target, boolean deleteRootstrap) {
 		return new MaemoTargetRemover(shell, target) {

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters/MaemoScratchbox2SDKManageTargetAdapterFactory.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters/MaemoScratchbox2SDKManageTargetAdapterFactory.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/adapters/MaemoScratchbox2SDKManageTargetAdapterFactory.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -20,7 +20,6 @@
  * @author eswartz
  * 
  */
- at SuppressWarnings("unchecked")
 public class MaemoScratchbox2SDKManageTargetAdapterFactory implements IAdapterFactory {
 
 	/*

Modified: branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/wizard/NewScratchbox2TargetWizard.java
===================================================================
--- branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/wizard/NewScratchbox2TargetWizard.java	2009-02-27 21:29:06 UTC (rev 1248)
+++ branches/work_Ed/org.maemo.esbox.scratchbox.sb2/src/org/maemo/esbox/internal/scratchbox/sb2/ui/wizard/NewScratchbox2TargetWizard.java	2009-02-27 22:27:06 UTC (rev 1249)
@@ -143,7 +143,7 @@
 			} catch (MicaException e) {
 				ErrorLogger errorLogger = Activator.getErrorLogger();
 				errorLogger.logAndShowError(
-						"Cannot get create rootstrap target " + targetName, e);
+						"Cannot get created rootstrap target " + targetName, e);
 				return false;
 			}
 		}



More information about the Esbox-commits mailing list