[Bug 8934] Ensure we create the devices.xml at the same location where we try to read it. Refactor copied method so single method called from SDKManager in core by SDKPreferencePage in ui. Ensure errors are reported in error log. Show dialog when unable to add SDK.
authordadubrow
Wed, 01 Jul 2009 08:54:31 -0500
changeset 335 a28d71356238
parent 334 18833d0cd6cf
child 336 0bdee354f078
[Bug 8934] Ensure we create the devices.xml at the same location where we try to read it. Refactor copied method so single method called from SDKManager in core by SDKPreferencePage in ui. Ensure errors are reported in error log. Show dialog when unable to add SDK.
core/com.nokia.carbide.cpp.sdk.core/META-INF/MANIFEST.MF
core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/SDKManager.java
core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/sdk/core/ISDKManager.java
core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/SDKPreferencePage.java
--- a/core/com.nokia.carbide.cpp.sdk.core/META-INF/MANIFEST.MF	Tue Jun 30 16:04:16 2009 -0500
+++ b/core/com.nokia.carbide.cpp.sdk.core/META-INF/MANIFEST.MF	Wed Jul 01 08:54:31 2009 -0500
@@ -15,7 +15,8 @@
  com.nokia.carbide.cpp.epoc.engine,
  org.eclipse.update.core,
  com.nokia.carbide.templatewizard,
- org.eclipse.core.filesystem
+ org.eclipse.core.filesystem,
+ com.nokia.cpp.utils.ui;bundle-version="1.0.0"
 Bundle-ActivationPolicy: lazy
 Export-Package: com.nokia.carbide.cpp.internal.api.sdk,
  com.nokia.carbide.cpp.internal.sdk.core.model;x-friends:="com.nokia.carbide.cpp.sdk.core.test",
--- a/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/SDKManager.java	Tue Jun 30 16:04:16 2009 -0500
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/internal/sdk/core/model/SDKManager.java	Wed Jul 01 08:54:31 2009 -0500
@@ -14,6 +14,7 @@
 
 import java.io.*;
 import java.net.*;
+import java.text.MessageFormat;
 import java.util.*;
 
 import javax.xml.parsers.*;
@@ -25,6 +26,7 @@
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.*;
 import org.eclipse.emf.common.util.EList;
+import org.eclipse.jface.dialogs.ErrorDialog;
 import org.eclipse.jface.dialogs.MessageDialog;
 import org.eclipse.osgi.service.datalocation.Location;
 import org.eclipse.swt.widgets.Shell;
@@ -41,8 +43,9 @@
 import com.nokia.carbide.cpp.internal.sdk.core.xml.DevicesLoader;
 import com.nokia.carbide.cpp.sdk.core.*;
 import com.nokia.carbide.cpp.sdk.core.ICarbideInstalledSDKChangeListener.SDKChangeEventType;
-import com.nokia.cpp.internal.api.utils.core.FileUtils;
+import com.nokia.cpp.internal.api.utils.core.*;
 import com.nokia.cpp.internal.api.utils.core.ListenerList;
+import com.nokia.cpp.internal.api.utils.ui.WorkbenchUtils;
 import com.sun.org.apache.xpath.internal.XPathAPI;
 
 public class SDKManager implements ISDKManager, ISDKManagerInternal {
@@ -50,11 +53,13 @@
 	private static List<ISymbianSDK> sdkList = new ArrayList<ISymbianSDK>();
 	private HashMap<String,ISymbianSDK> missingSdkMap = new HashMap<String,ISymbianSDK>();
 
-	public final String SYMBIAN_COMMON_REG_PATH="SOFTWARE\\Symbian\\EPOC SDKs\\";
-	public final String SYMBIAN_COMMON_PATH = "CommonPath";
+	private static final String SYMBIAN_COMMON_REG_PATH = "SOFTWARE\\Symbian\\EPOC SDKs\\";
+	private static final String SYMBIAN_COMMON_PATH = "CommonPath";
 	
-	public final String WINDOWS_SYSTEM_ROOT_REG = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\";
-	public final String WINDOWS_SYSTEM_ROOD_KEY = "SystemRoot";
+	private static final String WINDOWS_SYSTEM_ROOT_REG = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\";
+	private static final String WINDOWS_SYSTEM_ROOT_KEY = "SystemRoot";
+
+	private static final String EMPTY_DEVICES_XML_CONTENT = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><devices version=\"1.0\"></devices>";
 	
 	private static final String CARBIDE_SDK_CACHE_FILE_NAME = "carbideSDKCache.xml";
 	private static final String SDK_CACHE_ID_ATTRIB = "id";
@@ -217,7 +222,7 @@
 	}
 
 	
-	public void updateSDK(ISymbianSDK sdk){
+	public void updateSDK(ISymbianSDK sdk) {
 		try {
 			File devicesFile = getDevicesXMLFile();
 			
@@ -225,23 +230,28 @@
 			DevicesLoader.updateDevice(sdk, devicesFile.toURL());
 			updateCarbideSDKCache();
 			
-		} catch (MalformedURLException e) {
-			e.printStackTrace();
-		} catch (URISyntaxException e) {
-			e.printStackTrace();
-		} catch (IOException e) {
-			e.printStackTrace();
+		} catch (Exception e) { 
+			// must catch and rethrow as unchecked exception this 
+			// because no throws clause in API method
+			throw new RuntimeException(e);
 		}
 	}
 	
 	public void addSDK(ISymbianSDK sdk) {
 		synchronized(sdkList)
 		{
-			updateSDK(sdk);
-			sdkList.add(sdk);
-			SDKManagerInternalAPI.removeMissingSdk(sdk.getUniqueId());
-			// tell others about it
-			fireInstalledSdkChanged(SDKChangeEventType.eSDKAdded);
+			try {
+				updateSDK(sdk);
+				sdkList.add(sdk);
+				SDKManagerInternalAPI.removeMissingSdk(sdk.getUniqueId());
+				// tell others about it
+				fireInstalledSdkChanged(SDKChangeEventType.eSDKAdded);
+			}
+			catch (Exception e) {
+				logError("Could not add SDK", e);
+				String message = "Could not add this SDK. Your devices.xml file may be corrupt. If you remove the file from its current location and then rescan SDKs, Carbide will offer to create a new one.";
+				Logging.showErrorDialog(WorkbenchUtils.getSafeShell(), null, message, Logging.newSimpleStatus(1, e));
+			}
 		}
 	}
 	
@@ -323,41 +333,30 @@
 		return true;
 	}
 
-	/**
-	 * Read the devices.xml locaiton from the local machine registry.
-	 * @return String with full path to file if it exists. Empty string File (may be null) if file does not exist or regisry not read.
-	 */
-	private File getDevicesXMLFromRegistry(){
-		WindowsRegistry wr = WindowsRegistry.getRegistry();
-		String regPath = wr.getLocalMachineValue(SYMBIAN_COMMON_REG_PATH, SYMBIAN_COMMON_PATH);
-		boolean devicesFileExists = true;
+	// Read the devices.xml locaiton from the local machine registry.
+	// return IPath with absolute path to file if it exists or null if file does not exist or registry entry not found.
+	private IPath getDevicesXMLFromRegistry(){
+		String regValue = WindowsRegistry.getRegistry().getLocalMachineValue(SYMBIAN_COMMON_REG_PATH, SYMBIAN_COMMON_PATH);
+		IPath regPath = regValue != null ? new Path(regValue) : null;
 		
-		if (regPath == null || !new File(regPath).exists()){
+		if (regPath == null){
 			// No registry entry found...
-			String errMsg = "Could not read registry for local machine key: " +  SYMBIAN_COMMON_REG_PATH + " Cannot get devices.xml for installed SDKs.";
-			ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.getPluginId(), IStatus.ERROR, errMsg, null));
-			devicesFileExists = false;
+			String errMsg = MessageFormat.format(
+							"Could not read registry for local machine key: {0} Cannot get devices.xml for installed SDKs.",
+							SYMBIAN_COMMON_REG_PATH);
+			logError(errMsg, null);
+			return null;
+		}
+
+		// registry entry exists, check existence of file
+		regPath = regPath.append(DEVICES_FILE_NAME);
+		if (!regPath.toFile().exists()){
+			String errMsg = MessageFormat.format("Devices.xml does not exist at: {0}", regPath);
+			logError(errMsg, null);
+			return null;
 		}
 		
-		if (devicesFileExists){
-			// path exists, not try to check for fullpath + file
-			int len = regPath.length();
-			if (regPath.charAt(len-1) != '\\'){
-				regPath += "\\";
-			}
-			regPath += "devices.xml";
-			if (!new File(regPath).exists()){
-				String errMsg = "Devices.xml does not exist at: " + regPath;
-				ResourcesPlugin.getPlugin().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.getPluginId(), IStatus.ERROR, errMsg, null));
-				devicesFileExists = false;
-			}
-		}
-		
-		if (!devicesFileExists){
-			regPath = "";
-		}
-		
-		return new File(regPath);
+		return regPath;
 	}
 	
 	private void scanCarbideSDKCache(){
@@ -572,29 +571,19 @@
 	}
 
 	public File getDevicesXMLFile() {
-		File devicesFile = getDevicesXMLFromRegistry();
+		IPath devicesPath = getDevicesXMLFromRegistry();
 		
-		if (!devicesFile.exists()) {
-			// Not in registry, get the OS drive from the windows registry
-			WindowsRegistry wr = WindowsRegistry.getRegistry();
-			String regPath = "";
-			if (wr != null) {
-				regPath = wr.getLocalMachineValue(WINDOWS_SYSTEM_ROOT_REG,
-						WINDOWS_SYSTEM_ROOD_KEY);
-			}
-
-			String osDriveSpec;
-			if (regPath.length() > 2 && regPath.substring(1, 2).equals(":")) {
-				osDriveSpec = regPath.substring(0, 2);
-			} else {
-				osDriveSpec = DEFAULT_DEVICES_DRIVE_SPEC; // Just use the default drive spec, some problem reading the registry
-			}
-
-			devicesFile = new File(osDriveSpec + DEFAULT_DEVICES_XML_DIR
-					+ DEVICES_FILE_NAME);
+		if (devicesPath != null && devicesPath.toFile().exists()) {
+			return devicesPath.toFile();
 		}
 
-		return devicesFile;
+		// Not in registry, get the OS drive from the windows registry
+		String regValue = WindowsRegistry.getRegistry().getLocalMachineValue(WINDOWS_SYSTEM_ROOT_REG, WINDOWS_SYSTEM_ROOT_KEY);
+
+		String osDriveSpec = regValue != null ? new Path(regValue).getDevice() : DEFAULT_DEVICES_DRIVE_SPEC;
+
+		IPath deviceDirPath = new Path(osDriveSpec, DEFAULT_DEVICES_XML_DIR);
+		return deviceDirPath.append(DEVICES_FILE_NAME).toFile();
 	}
 	
 	public String getCSLArmToolchainInstallPathAndCheckReqTools() throws SDKEnvInfoFailureException{
@@ -712,7 +701,7 @@
 				}
 			}
 			catch (IOException e) {
-				// armcc isnt' in this directory, ignore....
+				// armcc isn't in this directory, ignore....
 			}
 		}
 				
@@ -729,50 +718,38 @@
 		
 	}
 	
-	private boolean checkDevicesXMLExistAndCreate(){
-		boolean fileCreated = false;
-		ISDKManager sdkMgr = SDKCorePlugin.getSDKManager();
-		if (sdkMgr == null){
-			return false; 
-		}
-		
-		IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
-		Shell shell = null;
-		if (window != null) {
-			shell = window.getShell();
-		} else {
-			return false; 
-		}
-		
-		File devicesFile = sdkMgr.getDevicesXMLFile();
+	public boolean checkDevicesXMLExistAndCreate() {
+		Shell shell = WorkbenchUtils.getSafeShell();
+		File devicesFile = getDevicesXMLFile();
 		if (!devicesFile.exists()){
-			if (true == MessageDialog.openQuestion(shell, "Cannot find devices.xml.", "Cannot find devices.xml under:\n\n" + DEFAULT_DEVICES_XML_DIR + DEVICES_FILE_NAME + "\n or \nRegistry: HKEY_LOCAL_MACHINE\\SOFTWARE\\Symbian\\EPOC SDKs\\\n\nThis file is required for Carbide.c++ use.\n\nDo you want Carbide to create this file?\n\n")){
+			if (MessageDialog.openQuestion(shell, "Devices.xml Not Found", 
+					"Carbide.c++ requires a valid devices.xml file to manage SDKs.\n\nDo you want Carbide to create this file?")) {
 				try {
 					// First check to make sure the directory exists....
-					File devicesPath = new File(DEFAULT_DEVICES_XML_DIR);
-					if (!devicesPath.exists()){
-						devicesPath.mkdirs();
+					if (!devicesFile.getParentFile().exists()){
+						devicesFile.getParentFile().mkdirs();
 					}
 					
-					devicesFile = new File(DEFAULT_DEVICES_XML_DIR + DEVICES_FILE_NAME);
 					devicesFile.createNewFile();
+
 					FileWriter fw = new FileWriter(devicesFile);
-					fw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?><devices version=\"1.0\"></devices>");
+					fw.write(EMPTY_DEVICES_XML_CONTENT);
 					fw.close();
-					fileCreated = true;
-					MessageDialog.openInformation(shell, "Devices.xml added", "Devices.xml was created successfully. Please add an SDK under the SDK Preferences page with the \"Add\" button before you attempt to create a project.");
-					
+
+					MessageDialog.openInformation(shell, "Devices.xml File Created", 
+							MessageFormat.format(
+								"{0} was created successfully. Please add an SDK under the SDK Preferences page with the \"Add\" button before you attempt to create a project.",
+								devicesFile.getAbsolutePath()));
+					return true;
 				} catch (IOException e){
-					MessageDialog.openError(shell, "Cannot create file.", "Could not create file: " + devicesFile.toString());
-					e.printStackTrace();
+					String message = "Could not create file: " + devicesFile.getAbsolutePath();
+					MessageDialog.openError(shell, "Cannot Create File", message);
+					logError(message, e);
 				}
-				
-			} else {
-				MessageDialog.openError(shell, "File not created.", "Devices.xml not created. You will be unable to create projects in Carbide.c++ until this file exists.");
 			}
 		}
 		
-		return fileCreated;
+		return false;
 	}
 	
 	protected void checkPerlInstallation(){
@@ -936,4 +913,8 @@
 			return true;
 		}
 	}
+	
+	private void logError(String message, Throwable t) {
+		SDKCorePlugin.getDefault().getLog().log(new Status(IStatus.ERROR, SDKCorePlugin.getPluginId(), message, t));		
+	}
 }
--- a/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/sdk/core/ISDKManager.java	Tue Jun 30 16:04:16 2009 -0500
+++ b/core/com.nokia.carbide.cpp.sdk.core/src/com/nokia/carbide/cpp/sdk/core/ISDKManager.java	Wed Jul 01 08:54:31 2009 -0500
@@ -132,8 +132,10 @@
 	public List<BuildPlat> getPlatformList();
 	
 	/**
-	 * Get the full path to the devices.xml file. This scans first the windows registry under 'SOFTWARE\Symbian\EPOC SDKs\CommonPath'.
-	 * If  CommonPath is not defined then the system drive spec is used with the folder location at '\Program Files\Common Files\Symbian'.
+	 * Get the absolute path to the devices.xml file. 
+	 * This first scans the windows registry under 'SOFTWARE\Symbian\EPOC SDKs\CommonPath'.
+	 * If  CommonPath is not defined then the system drive spec is used with the folder location at:
+	 * '\Program Files\Common Files\Symbian'.
 	 * @return File object. Clients should check File.exists() to make sure the file exists on disk.
 	 */
 	public File getDevicesXMLFile();
--- a/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/SDKPreferencePage.java	Tue Jun 30 16:04:16 2009 -0500
+++ b/core/com.nokia.carbide.cpp.sdk.ui/src/com/nokia/carbide/cpp/internal/sdk/ui/SDKPreferencePage.java	Wed Jul 01 08:54:31 2009 -0500
@@ -33,6 +33,7 @@
 import org.eclipse.swt.widgets.*;
 import org.eclipse.ui.*;
 
+import com.nokia.carbide.cpp.internal.sdk.core.model.SDKManager;
 import com.nokia.carbide.cpp.sdk.core.*;
 import com.nokia.carbide.cpp.sdk.ui.SDKUIPlugin;
 import com.nokia.carbide.cpp.sdk.ui.shared.AddSDKDialog;
@@ -100,7 +101,7 @@
 		GRAY = shell.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
 		
 		// check that devices.xml actually exists
-		checkDevicesXMLExist();
+		((SDKManager) sdkMgr).checkDevicesXMLExistAndCreate();
 		
 		Composite content = new Composite(parent, SWT.NONE);
 		setControl(content);
@@ -533,36 +534,4 @@
 	protected ISDKManager getSDKManager(){
 		return sdkMgr;
 	}
-	
-	private void checkDevicesXMLExist(){
-		if (sdkMgr == null){
-			return;
-		}
-		
-		File devicesFile = sdkMgr.getDevicesXMLFile();
-		if (!devicesFile.exists()){
-			if (true == MessageDialog.openQuestion(shell, "Cannot find devices.xml.", "Devices.xml is required for Carbide.c++ use. Do you want to create this file?\n\n" + ISDKManager.DEFAULT_DEVICES_XML_DIR + ISDKManager.DEVICES_FILE_NAME)){
-				try {
-					//First check to make sure the directory exists....
-					File devicesPath = new File(ISDKManager.DEFAULT_DEVICES_XML_DIR);
-					if (!devicesPath.exists()){
-						devicesPath.mkdirs();
-					}
-					
-					devicesFile = new File(ISDKManager.DEFAULT_DEVICES_XML_DIR + ISDKManager.DEVICES_FILE_NAME);
-					devicesFile.createNewFile();
-					FileWriter fw = new FileWriter(devicesFile);
-					fw.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?><devices version=\"1.0\"></devices>");
-					fw.close();
-				} catch (IOException e){
-					MessageDialog.openError(shell, "Cannot create file.", "Could not create file: " + devicesFile.toString());
-					e.printStackTrace();
-				}
-			} else {
-				MessageDialog.openError(shell, "File not created.", "File not created. You will be unable to create project in Carbide.c++.");
-			}
-			
-		}
-	}
-	
 }
\ No newline at end of file