diff options
Diffstat (limited to 'src/plugins/emulator/src/com/motorola/studio/android/emulator/device/instance/options/StartupOptionsMgt.java')
-rw-r--r-- | src/plugins/emulator/src/com/motorola/studio/android/emulator/device/instance/options/StartupOptionsMgt.java | 785 |
1 files changed, 785 insertions, 0 deletions
diff --git a/src/plugins/emulator/src/com/motorola/studio/android/emulator/device/instance/options/StartupOptionsMgt.java b/src/plugins/emulator/src/com/motorola/studio/android/emulator/device/instance/options/StartupOptionsMgt.java new file mode 100644 index 0000000..bd5710d --- /dev/null +++ b/src/plugins/emulator/src/com/motorola/studio/android/emulator/device/instance/options/StartupOptionsMgt.java @@ -0,0 +1,785 @@ +/* +* Copyright (C) 2012 The Android Open Source Project +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.motorola.studio.android.emulator.device.instance.options; + +import java.io.File; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +import org.eclipse.core.runtime.Path; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.eclipse.osgi.util.NLS; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +import com.motorola.studio.android.common.log.StudioLogger; +import com.motorola.studio.android.emulator.EmulatorPlugin; +import com.motorola.studio.android.emulator.i18n.EmulatorNLS; + +/** + * This class provides methods to manage startup options + * + */ +public class StartupOptionsMgt implements IStartupOptionsConstants +{ + + /** + * List of all startup options groups (the startup options themselves will + * be accessed through the use of a method in the group object that returns + * the startup options in that group) + */ + private static List<StartupOptionsGroup> startupOptionsGroupsList = null; + + /** + * List of all startup options, indexed by their names, for fast access + */ + private static Map<String, StartupOption> startupOptionsMap = + new HashMap<String, StartupOption>(); + + /* + * Load the startup options / groups list + */ + static + { + load(); + } + + /** + * Get the startup options groups list + * + * @return startup options groups list + */ + public static List<StartupOptionsGroup> getStartupOptionsGroupsList() + { + return startupOptionsGroupsList; + } + + /** + * Read all groups and startup options available for editing from a XML + * and stores the information in the correspondent beans + */ + public static void load() + { + + try + { + // Clear startup options groups list + startupOptionsGroupsList = new ArrayList<StartupOptionsGroup>(); + + // Define XML path + InputStream xmlStream = + EmulatorPlugin.getDefault().getBundle().getEntry(STARTUP_OPTIONS_XML_PATH) + .openStream(); + + // Load XML + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document document = builder.parse(xmlStream); + + /* + * Iterate through Startup Groups + */ + Element rootNode = document.getDocumentElement(); + NodeList startupOptionsGroups = rootNode.getElementsByTagName(GROUP_TAG); + for (int i = 0; i < startupOptionsGroups.getLength(); i++) + { + /* + * Create group + */ + Element group = (Element) startupOptionsGroups.item(i); + + String strKey = group.getAttributeNode(GROUP_TAG_ID).getNodeValue(); + strKey = + Platform.getResourceString(EmulatorPlugin.getDefault().getBundle(), strKey); + + StartupOptionsGroup startupOptionsGroup = new StartupOptionsGroup(strKey); + startupOptionsGroup.setTitle(startupOptionsGroup.getId()); + + /* + * Iterate through Startup Options in this group + */ + NodeList startupOptions = group.getElementsByTagName(STARTUP_OPT_TAG); + startupOptionsGroup.setStartupOptions(new ArrayList<StartupOption>()); // clear startup options + for (int j = 0; j < startupOptions.getLength(); j++) + { + /* + * Create startup option + */ + Element option = (Element) startupOptions.item(j); + StartupOption startupOption = + new StartupOption(option.getAttributeNode(STARTUP_OPT_TAG_NAME) + .getNodeValue(), getStartupOptionType(option.getAttributeNode( + STARTUP_OPT_TAG_TYPE).getNodeValue())); // name and type + strKey = option.getAttributeNode(STARTUP_OPT_TAG_FRIENDLY_NAME).getNodeValue(); + + strKey = + Platform.getResourceString(EmulatorPlugin.getDefault().getBundle(), + strKey); + + startupOption.setUserFriendlyName(strKey); // friendly name + + strKey = + option.getElementsByTagName(STARTUP_OPT_TAG_DESCRIPTION).item(0) + .getTextContent(); + + strKey = + Platform.getResourceString(EmulatorPlugin.getDefault().getBundle(), + strKey); + + startupOption.setDescription(strKey); // description + + if (option.getAttributeNode(STARTUP_OPT_TAG_TYPE_DETAILS) != null) + { + startupOption.setTypeDetails(option.getAttributeNode( + STARTUP_OPT_TAG_TYPE_DETAILS).getNodeValue()); // type details + } + // Iterate through startup option pre-defined values, if any + NodeList preDefinedValuesContainer = + option.getElementsByTagName(PREDEFINED_VALUES_TAG); + startupOption.setPreDefinedValues(new ArrayList<String>()); // clear pre-defined values + if (preDefinedValuesContainer.getLength() > 0) + { + NodeList preDefinedValues = + ((Element) preDefinedValuesContainer.item(0)) + .getElementsByTagName(PREDEFINED_VALUE_TAG); + for (int k = 0; k < preDefinedValues.getLength(); k++) + { + // Add pre-defined values to the option + Element preDefinedValue = (Element) preDefinedValues.item(k); + startupOption.getPreDefinedValues().add( + preDefinedValue.getTextContent()); + } + } + + /* + * Add startup options to the group + */ + startupOptionsGroup.getStartupOptions().add(startupOption); + + startupOptionsMap.put(startupOption.getName(), startupOption); + + } + + /* + * Add groups to the groups list + */ + startupOptionsGroupsList.add(startupOptionsGroup); + } + + } + catch (Exception e) + { + StudioLogger.error("Failed to load startup options"); + } + + } + + /** + * Validate the values assigned for the startup options marked as checked (the ones that are + * being used), according to its type and type details. + * + * @return Status object with the result of the validation + */ + public static Status validate() + { + Status status = (Status) Status.OK_STATUS; + String msg = null; + + /* + * Iterate through Startup Groups + */ + for (StartupOptionsGroup group : getStartupOptionsGroupsList()) + { + /* + * Iterate through Startup Options in this group + */ + for (StartupOption startupOption : group.getStartupOptions()) + { + /* + * Check if the Startup Option is checked + */ + if (startupOption.isChecked() && (status.isOK())) + { + + String name = startupOption.getName(); // startup option name + String ufname = startupOption.getUserFriendlyName(); // user-friendly startup option name + String value = startupOption.getValue(); // startup option value + String typeDetails = startupOption.getTypeDetails(); // startup option type detail + + /* + * General validation: no quotes in values + */ + if ((!startupOption.getName().equals(OTHERS_OTHER)) + && (value.indexOf("\"") >= 0)) + { + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_NoQuotes, + ufname); + } + else + { + + /* + * Call the appropriate validation method + */ + switch (startupOption.getType()) + { + case TYPE_TEXT: + msg = validateTextField(name, ufname, value, typeDetails); + break; + + case TYPE_NUMBER: + msg = validadeNumberField(name, ufname, value, typeDetails); + break; + + case TYPE_PATH: + msg = validadePathField(name, ufname, value, typeDetails); + break; + } + } + + /* + * If some validation has failed, return with an error message + */ + if (msg != null) + { + status = new Status(Status.ERROR, EmulatorPlugin.PLUGIN_ID, msg); + break; + } + + } + } + } + + return status; + + } + + /** + * Validate the startup option value for an startup option of "text" type + * + * @param name the startup option name + * @param ufname the user-friendly startup option name + * @param value the current assigned value for the startup option + * @param typeDetails any special requirements that the assigned value must be match + * @return null if the value assigned for the startup option is a valid one or an error message otherwise + */ + private static String validateTextField(String name, String ufName, String value, + String typeDetails) + { + String msg = null; + + // Check if the value is blank + if ((value == null) || (value.equals(""))) + { + msg = NLS.bind(EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_TextBlank, ufName); + } + + return msg; + + } + + /** + * Validate the startup option value for an startup option of "number" type + * + * @param name the startup option name + * @param ufname the user-friendly startup option name + * @param value the current assigned value for the startup option + * @param typeDetails any special requirements that the assigned value must be match + * @return null if the value assigned for the startup option is a valid one or an error message otherwise + */ + private static String validadeNumberField(String name, String ufName, String value, + String typeDetails) + { + String msg = null; + + // Check if the value is blank + if ((value == null) || (value.equals(""))) + { + msg = + NLS.bind(EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_NumberRequired, + ufName); + } + else + { + + try + { + /* + * Check if it's an Integer. + * If it's not, an exception will be thrown + */ + int intValue = Integer.parseInt(value); + + /* + * Check if it's positive + */ + if (intValue < 0) + { + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_NumberMustBePositiveInteger, + ufName); + } + else + { + + /* + * Check if the value is in the correct range + */ + if (typeDetails != null) + { + String[] valueRange = typeDetails.split(";"); + if ((intValue < Integer.parseInt(valueRange[0])) + || (intValue > Integer.parseInt(valueRange[1]))) + { + // the value is not in the correct range + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_NumberIntRange, + new String[] + { + ufName, valueRange[0], valueRange[1] + }); + } + } + } + + } + catch (NumberFormatException ex) + { + // it's not a number + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_NumberMustBeInteger, + ufName); + } + } + + return msg; + + } + + /** + * Validate the startup option value for an startup option of "path" type + * + * @param name the startup option name + * @param ufname the user-friendly startup option name + * @param value the current assigned value for the startup option + * @param typeDetails any special requirements that the assigned value must be match + * @return null if the value assigned for the startup option is a valid one or an error message otherwise + */ + private static String validadePathField(String name, String ufName, String value, + String typeDetails) + { + String msg = null; + + if ((value == null) || (value.equals(""))) + { + msg = NLS.bind(EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_PathRequired, ufName); + } + else + { + + File file = new File(value); + + /* + * Validate folder + */ + if (typeDetails.equals(TYPE_PATH_DIR)) + { + /* + * Check if the path exists + */ + if (!file.exists()) + { + // the folder doesn't exist + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_PathDirNotExist, + ufName); + } + else + { + if (file.isFile()) + { + // it's not a folder + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_PathMustBeDir, + ufName); + } + } + } + /* + * Validate file + */ + else + { + if (!file.exists()) + { + // the file doesn't exist + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_PathFileNotExist, + ufName); + } + else + { + // it's not a file + if (file.isDirectory()) + { + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_PathMustBeFile, + ufName); + } + // it doesn't have the correct extension + else + { + if (!typeDetails.equals("." + (new Path(value)).getFileExtension())) + { + msg = + NLS.bind( + EmulatorNLS.ERR_PropertiesMainComposite_StartupOpt_PathIncorrectFileType, + new String[] + { + ufName, typeDetails + }); + } + } + } + } + } + return msg; + + } + + /** + * Generates the list of parameters that shall to be sent to the Emulator + * + * @return the list of parameters that shall to be sent to the Emulator + */ + public static String getParamList() + { + String paramList = ""; + + /* + * Iterate through Startup Groups + */ + for (StartupOptionsGroup group : getStartupOptionsGroupsList()) + { + /* + * Iterate through Startup Options in this group + */ + int startupOptionType; + for (StartupOption startupOption : group.getStartupOptions()) + { + startupOptionType = startupOption.getType(); + if (startupOption.isChecked()) // check if the startup option is being used + { + if (startupOptionType == TYPE_NONE) + { + paramList += ((paramList.equals("")) ? "" : " ") + startupOption.getName(); + } + else + { + if ((startupOption.getName().equals(OTHERS_OTHER))) + { + + paramList += + ((paramList.equals("")) ? "" : " ") + startupOption.getValue(); + + } + else + { + String value = startupOption.getValue(); + + if (Platform.getOS().equals(Platform.OS_WIN32)) + { + if (value.contains(" ")) + { + value = "\"" + value + "\""; + } + } + else + { + if (value.contains("\\")) + { + value = value.replace("\\", "\\\\"); + } + + if (value.contains(" ")) + { + value = value.replace(" ", "\\ "); + } + } + + paramList += + ((paramList.equals("")) ? "" : " ") + startupOption.getName() + + (value.trim().length() > 0 ? " " + value : ""); + } + } + } + } + } + + return paramList; + + } + + /** + * Load values from a Properties object + * + * @param properties properties object containing the values that must be loaded into de model + */ + private static void loadValues(Properties properties) + { + /* + * Iterate through Startup Groups + */ + for (StartupOptionsGroup group : getStartupOptionsGroupsList()) + { + /* + * Iterate through Startup Options in this group + */ + String soValue = ""; + for (StartupOption startupOption : group.getStartupOptions()) + { + soValue = properties.getProperty(startupOption.getName()); + if (soValue != null) + { + startupOption.setChecked(true); + startupOption.setValue(soValue); + } + else + { + startupOption.setChecked(false); + startupOption.setValue(""); + } + startupOption.updateUI(); + } + } + + } + + /** + * Create a properties object with the information contained in a command line + * + * @param commandLine the command line used to start the emulator + * @return properties object with the information contained in a command line + */ + public static Properties parseCommandLine(String commandLine) + { + Properties properties = new Properties(); + + if (!commandLine.equals("")) + { + + /* + * Iterate through Startup Groups + */ + for (StartupOptionsGroup group : getStartupOptionsGroupsList()) + { + /* + * Iterate through Startup Options in this group + */ + String soName, soValue = ""; + int soType, shift = 0; + for (StartupOption startupOption : group.getStartupOptions()) + { + soName = startupOption.getName(); + soType = startupOption.getType(); + if (commandLine.startsWith(soName)) + { + if (soType == TYPE_NONE) + { + soValue = new Boolean(true).toString(); + shift = soName.length() + 1; + } + else + { + commandLine = + commandLine + .substring(soName.length() + 1, commandLine.length()); + //int endValueIndex = commandLine.indexOf("\""); + ParameterBean param = getNextParameterValue(commandLine); + soValue = param.getValue(); + shift = param.getLastPosition() + 1; + } + + properties.put(startupOption.getName(), soValue); + + if (shift < commandLine.length() - 1) + { + commandLine = commandLine.substring(shift, commandLine.length()); + } + else + { + commandLine = ""; + } + } + } + } + + if (!commandLine.equals("")) + { + properties.put(OTHERS_OTHER, commandLine); + } + } + + return properties; + + } + + /** + * Load values from a command line + * + * @param commandLine the command line used to start the emulator + */ + public static void loadFromCommandLine(String commandLine) + { + loadValues(parseCommandLine(commandLine)); + } + + /** + * Convert the type of the startup option from a string + * to a number + * + * @param type string that represents the type + * @return number that represents the type + */ + private static int getStartupOptionType(String type) + { + return (TYPE_MAP.get(type)).intValue(); + } + + /** + * Parses the next parameter value on a command line + * + * @param commandLine the command line + * + * @return a bean containing the parameter value and the last position looked at + * the command line + */ + private static ParameterBean getNextParameterValue(String commandLine) + { + boolean isWin32 = Platform.getOS().equals(Platform.OS_WIN32); + boolean escaped = false; + boolean quoted = false; + + char c; + String value = ""; + int i; + + for (i = 0; i < commandLine.length(); i++) + { + c = commandLine.charAt(i); + + if (escaped) + { + value += c; + escaped = false; + } + else if (c == '\\' && !isWin32) + { + escaped = true; + } + else if (c == '"' && isWin32) + { + if (value.length() == 0) + { + quoted = true; + } + else if (quoted) + { + break; + } + else + { + value += c; + } + } + else if ((c == ' ') && (!quoted)) + { + break; + } + else + { + value += c; + } + } + + return new ParameterBean(value, ((quoted) ? i + 1 : i)); + } + + /** + * Bean used to identify a parameter value when parsing the + * startup options + * + */ + private static class ParameterBean + { + private final String value; + + private final int lastPosition; + + /** + * Constructor + * + * @param value The parameter value + * @param lastPosition The last position looked at the command line before stopping + * the parse operation + */ + public ParameterBean(String value, int lastPosition) + { + this.value = value; + this.lastPosition = lastPosition; + } + + /** + * Retrieves the parameter value + * + * @return the parameter value + */ + public String getValue() + { + return value; + } + + /** + * Retrieves the last position looked at the command line before stopping + * the parse operation + * + * @return the last position looked at the command line before stopping + * the parse operation + */ + public int getLastPosition() + { + return lastPosition; + } + } +} |