diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:19 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-01-09 17:51:19 -0800 |
commit | a1514dae8668c48feae5436285e3db0ba2133ec3 (patch) | |
tree | 115c685f5c4c810cd317e8a6903e8d2d96749051 /sdkmanager/app/src | |
parent | 9ca1c0b33cc3fc28c21a915730797ec01e71a152 (diff) | |
download | sdk-a1514dae8668c48feae5436285e3db0ba2133ec3.zip sdk-a1514dae8668c48feae5436285e3db0ba2133ec3.tar.gz sdk-a1514dae8668c48feae5436285e3db0ba2133ec3.tar.bz2 |
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'sdkmanager/app/src')
3 files changed, 830 insertions, 124 deletions
diff --git a/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java b/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java new file mode 100644 index 0000000..ef3d0ee --- /dev/null +++ b/sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java @@ -0,0 +1,580 @@ +/* + * Copyright (C) 2008 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.android.sdkmanager; + +import java.util.HashMap; +import java.util.Map.Entry; + +/** + * Parses the command-line and stores flags needed or requested. + * <p/> + * This is a base class. To be useful you want to: + * <ul> + * <li>override it. + * <li>pass an action array to the constructor. + * <li>define flags for your actions. + * </ul> + * <p/> + * To use, call {@link #parseArgs(String[])} and then call {@link #getValue(String, String)}. + */ +public class CommandLineProcessor { + + /** Internal action name for all global flags. */ + public final static String GLOBAL_FLAG = "global"; + /** Internal action name for internally hidden flags. + * This is currently used to store the requested action name. */ + public final static String INTERNAL_FLAG = "internal"; + + /** The global help flag. */ + public static final String KEY_HELP = "help"; + /** The global verbose flag. */ + public static final String KEY_VERBOSE = "verbose"; + /** The internal action flag. */ + public static final String KEY_ACTION = "action"; + + /** List of available actions. + * <p/> + * Each entry must be a 2-string array with first the action name and then + * a description. + */ + private final String[][] mActions; + /** The hash of all defined arguments. + * <p/> + * The key is a string "action/longName". + */ + private final HashMap<String, Arg> mArguments = new HashMap<String, Arg>(); + + public CommandLineProcessor(String[][] actions) { + mActions = actions; + + define(MODE.STRING, false, INTERNAL_FLAG, null, KEY_ACTION, "Selected Action", null); + + define(MODE.BOOLEAN, false, GLOBAL_FLAG, "v", KEY_VERBOSE, "Verbose mode", false); + define(MODE.BOOLEAN, false, GLOBAL_FLAG, "h", KEY_HELP, "This help", false); + } + + //------------------ + // Helpers to get flags values + + /** Helper that returns true if --verbose was requested. */ + public boolean isVerbose() { + return ((Boolean) getValue(GLOBAL_FLAG, KEY_VERBOSE)).booleanValue(); + } + + /** Helper that returns true if --help was requested. */ + public boolean isHelpRequested() { + return ((Boolean) getValue(GLOBAL_FLAG, KEY_HELP)).booleanValue(); + } + + /** Helper that returns the requested action name. */ + public String getActionRequested() { + return (String) getValue(INTERNAL_FLAG, KEY_ACTION); + } + + //------------------ + + /** + * Raw access to parsed parameter values. + * @param action The action name, including {@link #GLOBAL_FLAG} and {@link #INTERNAL_FLAG} + * @param longFlagName The long flag name for the given action. + * @return The current value object stored in the parameter, which depends on the argument mode. + */ + public Object getValue(String action, String longFlagName) { + String key = action + "/" + longFlagName; + Arg arg = mArguments.get(key); + return arg.getCurrentValue(); + } + + /** + * Internal setter for raw parameter value. + * @param action The action name, including {@link #GLOBAL_FLAG} and {@link #INTERNAL_FLAG} + * @param longFlagName The long flag name for the given action. + * @param value The new current value object stored in the parameter, which depends on the + * argument mode. + */ + protected void setValue(String action, String longFlagName, Object value) { + String key = action + "/" + longFlagName; + Arg arg = mArguments.get(key); + arg.setCurrentValue(value); + } + + /** + * Parses the command-line arguments. + * <p/> + * This method will exit and not return if a parsing error arise. + * + * @param args The arguments typically received by a main method. + */ + public void parseArgs(String[] args) { + String needsHelp = null; + String action = null; + + int n = args.length; + for (int i = 0; i < n; i++) { + Arg arg = null; + String a = args[i]; + if (a.startsWith("--")) { + arg = findLongArg(action, a.substring(2)); + } else if (a.startsWith("-")) { + arg = findShortArg(action, a.substring(1)); + } + + // Not a keyword and we don't have an action yet, this should be an action + if (arg == null && action == null) { + + if (a.startsWith("-")) { + // Got a keyword but not valid for global flags + needsHelp = String.format( + "Flag '%1$s' is not a valid global flag. Did you mean to specify it after the action name?", + a, action); + break; + } + + for (String[] actionDesc : mActions) { + if (actionDesc[0].equals(a)) { + action = a; + break; + } + } + + if (action == null) { + needsHelp = String.format( + "Expected action name after global parameters but found %1$s instead.", + a); + break; + } + } else if (arg == null && action != null) { + // Got a keyword but not valid for the current action + needsHelp = String.format( + "Flag '%1$s' is not valid for action '%2$s'.", + a, action); + break; + + } else if (arg != null) { + // Process keyword + String error = null; + if (arg.getMode().needsExtra()) { + if (++i >= n) { + needsHelp = String.format("Missing argument for flag %1$s.", a); + break; + } + + error = arg.getMode().process(arg, args[i]); + } else { + error = arg.getMode().process(arg, null); + + // If we just toggled help, we want to exit now without printing any error. + // We do this test here only when a Boolean flag is toggled since booleans + // are the only flags that don't take parameters and help is a boolean. + if (isHelpRequested()) { + printHelpAndExit(null); + // The call above should terminate however in unit tests we override + // it so we still need to return here. + return; + } + } + + if (error != null) { + needsHelp = String.format("Invalid usage for flag %1$s: %2$s.", a, error); + break; + } + } + } + + if (needsHelp == null) { + if (action == null) { + needsHelp = "Missing action name."; + } else { + // Validate that all mandatory arguments are non-null for this action + for (Entry<String, Arg> entry : mArguments.entrySet()) { + Arg arg = entry.getValue(); + if (arg.getAction().equals(action)) { + if (arg.isMandatory() && arg.getCurrentValue() == null) { + needsHelp = String.format("The parameter --%1$s must be defined for action '%2$s'", + arg.getLongArg(), + action); + break; + } + } + } + + setValue(INTERNAL_FLAG, KEY_ACTION, action); + } + } + + if (needsHelp != null) { + printHelpAndExitForAction(action, needsHelp); + } + } + + /** + * Finds an {@link Arg} given an action name and a long flag name. + * @return The {@link Arg} found or null. + */ + protected Arg findLongArg(String action, String longName) { + if (action == null) { + action = GLOBAL_FLAG; + } + String key = action + "/" + longName; + return mArguments.get(key); + } + + /** + * Finds an {@link Arg} given an action name and a short flag name. + * @return The {@link Arg} found or null. + */ + protected Arg findShortArg(String action, String shortName) { + if (action == null) { + action = GLOBAL_FLAG; + } + + for (Entry<String, Arg> entry : mArguments.entrySet()) { + Arg arg = entry.getValue(); + if (arg.getAction().equals(action)) { + if (shortName.equals(arg.getShortArg())) { + return arg; + } + } + } + + return null; + } + + /** + * Prints the help/usage and exits. + * + * @param errorFormat Optional error message to print prior to usage using String.format + * @param args Arguments for String.format + */ + public void printHelpAndExit(String errorFormat, Object... args) { + printHelpAndExitForAction(null /*actionFilter*/, errorFormat, args); + } + + /** + * Prints the help/usage and exits. + * + * @param actionFilter If null, displays help for all actions. If not null, display help only + * for that specific action. In all cases also display general usage and action list. + * @param errorFormat Optional error message to print prior to usage using String.format + * @param args Arguments for String.format + */ + public void printHelpAndExitForAction(String actionFilter, String errorFormat, Object... args) { + if (errorFormat != null) { + stderr(errorFormat, args); + } + + /* + * usage should fit in 80 columns + * 12345678901234567890123456789012345678901234567890123456789012345678901234567890 + */ + stdout("\n" + + "Usage:\n" + + " android [global options] action [action options]\n" + + "\n" + + "Global options:"); + listOptions(GLOBAL_FLAG); + + stdout("\nValid actions:"); + for (String[] action : mActions) { + String filler = ""; + int len = action[0].length(); + if (len < 10) { + filler = " ".substring(len); + } + + stdout("- %1$s:%2$s %3$s", action[0], filler, action[1]); + } + + for (String[] action : mActions) { + if (actionFilter == null || actionFilter.equals(action[0])) { + stdout("\nAction \"%1$s\":", action[0]); + stdout(" %1$s", action[1]); + stdout("Options:"); + listOptions(action[0]); + } + } + + exit(); + } + + /** + * Internal helper to print all the option flags for a given action name. + */ + protected void listOptions(String action) { + int numOptions = 0; + for (Entry<String, Arg> entry : mArguments.entrySet()) { + Arg arg = entry.getValue(); + if (arg.getAction().equals(action)) { + + String value = null; + if (arg.getDefaultValue() instanceof String[]) { + value = ""; + for (String v : (String[]) arg.getDefaultValue()) { + if (value.length() > 0) { + value += "|"; + } + value += v; + } + } else if (arg.getDefaultValue() != null) { + value = arg.getDefaultValue().toString(); + } + + stdout(" -%1$s %2$-10s %3$s%4$s", + arg.getShortArg(), + "--" + arg.getLongArg(), + arg.getDescription(), + value == null ? "" : " (" + value + ")"); + numOptions++; + } + } + + if (numOptions == 0) { + stdout(" No options"); + } + } + + //---- + + /** + * The mode of an argument specifies the type of variable it represents, + * whether an extra parameter is required after the flag and how to parse it. + */ + static enum MODE { + /** Argument value is a Boolean. Default value is a Boolean. */ + BOOLEAN { + @Override + public boolean needsExtra() { + return false; + } + @Override + public String process(Arg arg, String extra) { + // Toggle the current value + arg.setCurrentValue(! ((Boolean) arg.getCurrentValue()).booleanValue()); + return null; + } + }, + + /** Argument value is an Integer. Default value is an Integer. */ + INTEGER { + @Override + public boolean needsExtra() { + return true; + } + @Override + public String process(Arg arg, String extra) { + try { + arg.setCurrentValue(Integer.parseInt(extra)); + return null; + } catch (NumberFormatException e) { + return String.format("Failed to parse '%1$s' as an integer: %2%s", + extra, e.getMessage()); + } + } + }, + + /** Argument value is a String. Default value is a String[]. */ + ENUM { + @Override + public boolean needsExtra() { + return true; + } + @Override + public String process(Arg arg, String extra) { + StringBuilder desc = new StringBuilder(); + String[] values = (String[]) arg.getDefaultValue(); + for (String value : values) { + if (value.equals(extra)) { + arg.setCurrentValue(extra); + return null; + } + + if (desc.length() != 0) { + desc.append(", "); + } + desc.append(value); + } + + return String.format("'%1$s' is not one of %2$s", extra, desc.toString()); + } + }, + + /** Argument value is a String. Default value is a null. */ + STRING { + @Override + public boolean needsExtra() { + return true; + } + @Override + public String process(Arg arg, String extra) { + arg.setCurrentValue(extra); + return null; + } + }; + + /** + * Returns true if this mode requires an extra parameter. + */ + public abstract boolean needsExtra(); + + /** + * Processes the flag for this argument. + * + * @param arg The argument being processed. + * @param extra The extra parameter. Null if {@link #needsExtra()} returned false. + * @return An error string or null if there's no error. + */ + public abstract String process(Arg arg, String extra); + } + + /** + * An argument accepted by the command-line, also called "a flag". + * Arguments must have a short version (one letter), a long version name and a description. + * They can have a default value, or it can be null. + * Depending on the {@link MODE}, the default value can be a Boolean, an Integer, a String + * or a String array (in which case the first item is the current by default.) + */ + static class Arg { + private final String mAction; + private final String mShortName; + private final String mLongName; + private final String mDescription; + private final Object mDefaultValue; + private Object mCurrentValue; + private final MODE mMode; + private final boolean mMandatory; + + /** + * Creates a new argument flag description. + * + * @param mode The {@link MODE} for the argument. + * @param mandatory True if this argument is mandatory for this action. + * @param action The action name. Can be #GLOBAL_FLAG or #INTERNAL_FLAG. + * @param shortName The one-letter short argument name. Cannot be empty nor null. + * @param longName The long argument name. Cannot be empty nor null. + * @param description The description. Cannot be null. + * @param defaultValue The default value (or values), which depends on the selected {@link MODE}. + */ + public Arg(MODE mode, + boolean mandatory, + String action, + String shortName, + String longName, + String description, + Object defaultValue) { + mMode = mode; + mMandatory = mandatory; + mAction = action; + mShortName = shortName; + mLongName = longName; + mDescription = description; + mDefaultValue = defaultValue; + if (defaultValue instanceof String[]) { + mCurrentValue = ((String[])defaultValue)[0]; + } else { + mCurrentValue = mDefaultValue; + } + } + + public boolean isMandatory() { + return mMandatory; + } + + public String getShortArg() { + return mShortName; + } + + public String getLongArg() { + return mLongName; + } + + public String getDescription() { + return mDescription; + } + + public String getAction() { + return mAction; + } + + public Object getDefaultValue() { + return mDefaultValue; + } + + public Object getCurrentValue() { + return mCurrentValue; + } + + public void setCurrentValue(Object currentValue) { + mCurrentValue = currentValue; + } + + public MODE getMode() { + return mMode; + } + } + + /** + * Internal helper to define a new argument for a give action. + * + * @param mode The {@link MODE} for the argument. + * @param action The action name. Can be #GLOBAL_FLAG or #INTERNAL_FLAG. + * @param shortName The one-letter short argument name. Cannot be empty nor null. + * @param longName The long argument name. Cannot be empty nor null. + * @param description The description. Cannot be null. + * @param defaultValue The default value (or values), which depends on the selected {@link MODE}. + */ + protected void define(MODE mode, + boolean mandatory, + String action, + String shortName, String longName, + String description, Object defaultValue) { + assert(mandatory || mode == MODE.BOOLEAN); // a boolean mode cannot be mandatory + + String key = action + "/" + longName; + mArguments.put(key, new Arg(mode, mandatory, + action, shortName, longName, description, defaultValue)); + } + + /** + * Exits in case of error. + * This is protected so that it can be overridden in unit tests. + */ + protected void exit() { + System.exit(1); + } + + /** + * Prints a line to stdout. + * This is protected so that it can be overridden in unit tests. + * + * @param format The string to be formatted. Cannot be null. + * @param args Format arguments. + */ + protected void stdout(String format, Object...args) { + System.out.println(String.format(format, args)); + } + + /** + * Prints a line to stderr. + * This is protected so that it can be overridden in unit tests. + * + * @param format The string to be formatted. Cannot be null. + * @param args Format arguments. + */ + protected void stderr(String format, Object...args) { + System.err.println(String.format(format, args)); + } +} diff --git a/sdkmanager/app/src/com/android/sdkmanager/Main.java b/sdkmanager/app/src/com/android/sdkmanager/Main.java index 72bd2aa..3bcb9a3 100644 --- a/sdkmanager/app/src/com/android/sdkmanager/Main.java +++ b/sdkmanager/app/src/com/android/sdkmanager/Main.java @@ -23,6 +23,8 @@ import com.android.sdklib.ISdkLog; import com.android.sdklib.SdkConstants; import com.android.sdklib.SdkManager; import com.android.sdklib.IAndroidTarget.IOptionalLibrary; +import com.android.sdklib.project.ProjectCreator; +import com.android.sdklib.project.ProjectCreator.OutputLevel; import com.android.sdklib.vm.HardwareProperties; import com.android.sdklib.vm.VmManager; import com.android.sdklib.vm.HardwareProperties.HardwareProperty; @@ -35,31 +37,20 @@ import java.util.List; import java.util.Map; /** - * Main class for the 'android' application - * + * Main class for the 'android' application. */ class Main { private final static String TOOLSDIR = "com.android.sdkmanager.toolsdir"; - private final static String ARG_LIST_TARGET = "target"; - private final static String ARG_LIST_VM = "vm"; - private final static String[] BOOLEAN_YES_REPLIES = new String[] { "yes", "y" }; private final static String[] BOOLEAN_NO_REPLIES = new String[] { "no", "n" }; private String mSdkFolder; + private ISdkLog mSdkLog; private SdkManager mSdkManager; private VmManager mVmManager; - - /* --list parameters */ - private String mListObject; - - /* --create parameters */ - private boolean mCreateVm; - private int mCreateTargetId; - private IAndroidTarget mCreateTarget; - private String mCreateName; + private SdkCommandLine mSdkCommandLine; public static void main(String[] args) { new Main().run(args); @@ -71,7 +62,7 @@ class Main { */ private void run(String[] args) { init(); - parseArgs(args); + mSdkCommandLine.parseArgs(args); parseSdk(); doAction(); } @@ -81,70 +72,41 @@ class Main { * doing basic parsing of the SDK. */ private void init() { + mSdkCommandLine = new SdkCommandLine(); + /* We get passed a property for the tools dir */ String toolsDirProp = System.getProperty(TOOLSDIR); if (toolsDirProp == null) { // for debugging, it's easier to override using the process environment toolsDirProp = System.getenv(TOOLSDIR); } - if (toolsDirProp == null) { - printHelpAndExit("ERROR: The tools directory property is not set, please make sure you are executing android or android.bat"); - } - - // got back a level for the SDK folder - File tools = new File(toolsDirProp); - mSdkFolder = tools.getParent(); - - } - /** - * Parses command-line arguments, or prints help/usage and exits if error. - * @param args arguments passed to the program - */ - private void parseArgs(String[] args) { - final int numArgs = args.length; - - try { - int argPos = 0; - for (; argPos < numArgs; argPos++) { - final String arg = args[argPos]; - if (arg.equals("-l") || arg.equals("--list")) { - mListObject = args[++argPos]; - } else if (arg.equals("-c") || arg.equals("--create")) { - mCreateVm = true; - parseCreateArgs(args, ++argPos); + if (toolsDirProp != null) { + // got back a level for the SDK folder + File tools; + if (toolsDirProp.length() > 0) { + tools = new File(toolsDirProp); + mSdkFolder = tools.getParent(); + } else { + try { + tools = new File(".").getCanonicalFile(); + mSdkFolder = tools.getParent(); + } catch (IOException e) { + // Will print an error below since mSdkFolder is not defined } } - } catch (ArrayIndexOutOfBoundsException e) { - /* Any OOB triggers help */ - printHelpAndExit("ERROR: Not enough arguments."); } - } - private void parseCreateArgs(String[] args, int argPos) { - final int numArgs = args.length; - - try { - for (; argPos < numArgs; argPos++) { - final String arg = args[argPos]; - if (arg.equals("-t") || arg.equals("--target")) { - String targetId = args[++argPos]; - try { - // get the target id - mCreateTargetId = Integer.parseInt(targetId); - } catch (NumberFormatException e) { - printHelpAndExit("ERROR: Target Id is not a number"); - } - } else if (arg.equals("-n") || arg.equals("--name")) { - mCreateName = args[++argPos]; - } else { - printHelpAndExit("ERROR: '%s' unknown argument for --create mode", - args[argPos]); - } + if (mSdkFolder == null) { + String os = System.getProperty("os.name"); + String cmd = "android"; + if (os.startsWith("Windows")) { + cmd += ".bat"; } - } catch (ArrayIndexOutOfBoundsException e) { - /* Any OOB triggers help */ - printHelpAndExit("ERROR: Not enough arguments for --create"); + + mSdkCommandLine.printHelpAndExit( + "ERROR: The tools directory property is not set, please make sure you are executing %1$s", + cmd); } } @@ -152,10 +114,15 @@ class Main { * Does the basic SDK parsing required for all actions */ private void parseSdk() { - mSdkManager = SdkManager.createManager(mSdkFolder, new ISdkLog() { - public void error(String errorFormat, Object... args) { - System.err.printf("Error: " + errorFormat, args); - System.err.println(""); + mSdkLog = new ISdkLog() { + public void error(Throwable t, String errorFormat, Object... args) { + if (errorFormat != null) { + System.err.printf("Error: " + errorFormat, args); + System.err.println(""); + } + if (t != null) { + System.err.print("Error: " + t.getMessage()); + } } public void warning(String warningFormat, Object... args) { @@ -165,10 +132,15 @@ class Main { System.out.println(""); } } - }); + + public void printf(String msgFormat, Object... args) { + System.out.printf(msgFormat, args); + } + }; + mSdkManager = SdkManager.createManager(mSdkFolder, mSdkLog); if (mSdkManager == null) { - printHelpAndExit("ERROR: Unable to parse SDK content."); + mSdkCommandLine.printHelpAndExit("ERROR: Unable to parse SDK content."); } } @@ -176,19 +148,37 @@ class Main { * Actually do an action... */ private void doAction() { - if (mListObject != null) { + String action = mSdkCommandLine.getActionRequested(); + + if (SdkCommandLine.ACTION_LIST.equals(action)) { // list action. - if (ARG_LIST_TARGET.equals(mListObject)) { + if (SdkCommandLine.ARG_TARGET.equals(mSdkCommandLine.getListFilter())) { displayTargetList(); - } else if (ARG_LIST_VM.equals(mListObject)) { + } else if (SdkCommandLine.ARG_VM.equals(mSdkCommandLine.getListFilter())) { displayVmList(); } else { - printHelpAndExit("'%s' is not a valid --list option", mListObject); + displayTargetList(); + displayVmList(); } - } else if (mCreateVm) { + } else if (SdkCommandLine.ACTION_NEW_VM.equals(action)) { createVm(); + } else if (SdkCommandLine.ACTION_NEW_PROJECT.equals(action)) { + // get the target and try to resolve it. + int targetId = mSdkCommandLine.getNewProjectTargetId(); + IAndroidTarget[] targets = mSdkManager.getTargets(); + if (targetId < 1 || targetId > targets.length) { + mSdkCommandLine.printHelpAndExit("ERROR: Wrong target id."); + } + IAndroidTarget target = targets[targetId - 1]; + + ProjectCreator creator = new ProjectCreator(mSdkFolder, + OutputLevel.NORMAL, mSdkLog); + + creator.createProject(mSdkCommandLine.getNewProjectLocation(), + mSdkCommandLine.getNewProjectName(), mSdkCommandLine.getNewProjectPackage(), + mSdkCommandLine.getNewProjectActivity(), target, true); } else { - printHelpAndExit(null); + mSdkCommandLine.printHelpAndExit(null); } } @@ -274,7 +264,7 @@ class Main { index++; } } catch (AndroidLocationException e) { - printHelpAndExit(e.getMessage()); + mSdkCommandLine.printHelpAndExit(e.getMessage()); } } @@ -283,11 +273,14 @@ class Main { */ private void createVm() { // find a matching target - if (mCreateTargetId >= 1 && mCreateTargetId <= mSdkManager.getTargets().length) { - mCreateTarget = mSdkManager.getTargets()[mCreateTargetId-1]; // target it is 1-based + int targetId = mSdkCommandLine.getNewVmTargetId(); + IAndroidTarget target = null; + + if (targetId >= 1 && targetId <= mSdkManager.getTargets().length) { + target = mSdkManager.getTargets()[targetId-1]; // target it is 1-based } else { - printHelpAndExit( - "ERROR: Target Id is not a valid Id. Check android --list target for the list of targets."); + mSdkCommandLine.printHelpAndExit( + "ERROR: Target Id is not a valid Id. Check 'android list target' for the list of targets."); } try { @@ -295,19 +288,24 @@ class Main { String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS; Map<String, String> hardwareConfig = null; - if (mCreateTarget.isPlatform()) { + if (target.isPlatform()) { try { - hardwareConfig = promptForHardware(mCreateTarget); + hardwareConfig = promptForHardware(target); } catch (IOException e) { - printHelpAndExit(e.getMessage()); + mSdkCommandLine.printHelpAndExit(e.getMessage()); } } - VmManager.createVm(vmRoot, mCreateName, mCreateTarget, null /*skinName*/, - null /*sdcardPath*/, 0 /*sdcardSize*/, hardwareConfig, + VmManager.createVm(vmRoot, + mSdkCommandLine.getNewVmName(), + target, + null /*skinName*/, + null /*sdcardPath*/, + 0 /*sdcardSize*/, + hardwareConfig, null /* sdklog */); } catch (AndroidLocationException e) { - printHelpAndExit(e.getMessage()); + mSdkCommandLine.printHelpAndExit(e.getMessage()); } } @@ -325,7 +323,7 @@ class Main { System.out.print(String.format("Do you which to create a custom hardware profile [%s]", defaultAnswer)); - result = readLine(readLineBuffer); + result = readLine(readLineBuffer).trim(); // handle default: if (result.length() == 0) { result = defaultAnswer; @@ -391,8 +389,7 @@ class Main { break; case INTEGER: try { - @SuppressWarnings("unused") - int value = Integer.parseInt(result); + Integer.parseInt(result); map.put(property.getName(), result); i++; // valid reply, move to next property } catch (NumberFormatException e) { @@ -414,9 +411,8 @@ class Main { } /** - * Read the line from the input stream. + * Reads the line from the input stream. * @param buffer - * @return * @throws IOException */ private String readLine(byte[] buffer) throws IOException { @@ -434,7 +430,12 @@ class Main { return new String(buffer, 0, count) + secondHalf; } - return new String(buffer, 0, count - 1); // -1 to not include the carriage return + // ignore end whitespace + while (count > 0 && (buffer[count-1] == '\r' || buffer[count-1] == '\n')) { + count--; + } + + return new String(buffer, 0, count); } /** @@ -442,6 +443,7 @@ class Main { * @throws IOException If the value is not a boolean string. */ private boolean getBooleanReply(String reply) throws IOException { + for (String valid : BOOLEAN_YES_REPLIES) { if (valid.equalsIgnoreCase(reply)) { return true; @@ -456,32 +458,4 @@ class Main { throw new IOException(String.format("%s is not a valid reply", reply)); } - - /** - * Prints the help/usage and exits. - * @param errorFormat Optional error message to print prior to usage using String.format - * @param args Arguments for String.format - */ - private void printHelpAndExit(String errorFormat, Object... args) { - if (errorFormat != null) { - System.err.println(String.format(errorFormat, args)); - } - - /* - * usage should fit in 80 columns - * 12345678901234567890123456789012345678901234567890123456789012345678901234567890 - */ - final String usage = "\n" + - "Usage:\n" + - " android --list [target|vm]\n" + - " android --create --target <target id> --name <name>\n" + - "\n" + - "Options:\n" + - " -l [target|vm], --list [target|vm]\n" + - " Outputs the available targets or Virtual Machines and their Ids.\n" + - "\n"; - - System.out.println(usage); - System.exit(1); - } }
\ No newline at end of file diff --git a/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java b/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java new file mode 100644 index 0000000..918c534 --- /dev/null +++ b/sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2008 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.android.sdkmanager; + +import com.android.sdklib.SdkManager; + + +/** + * Specific command-line flags for the {@link SdkManager}. + */ +public class SdkCommandLine extends CommandLineProcessor { + + public static final String ARG_ALIAS = "alias"; + public static final String ARG_ACTIVITY = "activity"; + public static final String ARG_VM = "vm"; + public static final String ARG_TARGET = "target"; + public static final String ARG_ALL = "all"; + + public static final String KEY_IN = "in"; + public static final String KEY_ACTIVITY = ARG_ACTIVITY; + public static final String KEY_PACKAGE = "package"; + public static final String KEY_MODE = "mode"; + public static final String KEY_TARGET_ID = ARG_TARGET; + public static final String KEY_NAME = "name"; + public static final String KEY_OUT = "out"; + public static final String KEY_FILTER = "filter"; + + public final static String ACTION_LIST = "list"; + public final static String ACTION_NEW_VM = ARG_VM; + public final static String ACTION_NEW_PROJECT = "project"; + public final static String ACTION_UPDATE_PROJECT = "update"; + + private final static String[][] ACTIONS = { + { ACTION_LIST, + "Lists existing targets or VMs." }, + { ACTION_NEW_VM, + "Creates a new VM." }, + { ACTION_NEW_PROJECT, + "Creates a new project using a template." }, + { ACTION_UPDATE_PROJECT, + "Updates a new project from existing source (must have an AndroidManifest.xml)." }, + }; + + public SdkCommandLine() { + super(ACTIONS); + + define(MODE.ENUM, false, ACTION_LIST, "f", KEY_FILTER, + "List filter", new String[] { ARG_ALL, ARG_TARGET, ARG_VM }); + + define(MODE.STRING, false, ACTION_NEW_VM, "o", KEY_OUT, + "Location path of new VM", null); + define(MODE.STRING, true, ACTION_NEW_VM, "n", KEY_NAME, + "Name of the new VM", null); + define(MODE.INTEGER, true, ACTION_NEW_VM, "t", KEY_TARGET_ID, + "Target id of the new VM", null); + + define(MODE.ENUM, true, ACTION_NEW_PROJECT, "m", KEY_MODE, + "Project mode", new String[] { ARG_ACTIVITY, ARG_ALIAS }); + define(MODE.STRING, false, ACTION_NEW_PROJECT, "o", KEY_OUT, + "Location path of new project", null); + define(MODE.STRING, true, ACTION_NEW_PROJECT, "n", KEY_NAME, + "Name of the new project", null); + define(MODE.INTEGER, true, ACTION_NEW_PROJECT, "t", KEY_TARGET_ID, + "Target id of the new project", null); + define(MODE.STRING, true, ACTION_NEW_PROJECT, "p", KEY_PACKAGE, + "Package name", null); + define(MODE.STRING, true, ACTION_NEW_PROJECT, "a", KEY_ACTIVITY, + "Activity name", null); + + define(MODE.STRING, false, ACTION_UPDATE_PROJECT, "i", KEY_IN, + "Directory location of the project", null); + define(MODE.STRING, true, ACTION_UPDATE_PROJECT, "t", KEY_TARGET_ID, + "Target id to set for the project", null); + } + + // -- some helpers for list action flags + + /** Helper to retrieve the --filter for the list action. */ + public String getListFilter() { + return ((String) getValue(ACTION_LIST, KEY_FILTER)); + } + + // -- some helpers for vm action flags + + /** Helper to retrieve the --out location for the new vm action. */ + public String getNewVmLocation() { + return ((String) getValue(ACTION_NEW_VM, KEY_OUT)); + } + + /** Helper to retrieve the --target id for the new vm action. */ + public int getNewVmTargetId() { + return ((Integer) getValue(ACTION_NEW_VM, KEY_TARGET_ID)).intValue(); + } + + /** Helper to retrieve the --name for the new vm action. */ + public String getNewVmName() { + return ((String) getValue(ACTION_NEW_VM, KEY_NAME)); + } + + // -- some helpers for project action flags + + /** Helper to retrieve the --out location for the new project action. */ + public String getNewProjectLocation() { + return ((String) getValue(ACTION_NEW_PROJECT, KEY_OUT)); + } + + /** Helper to retrieve the --target id for the new project action. */ + public int getNewProjectTargetId() { + return ((Integer) getValue(ACTION_NEW_PROJECT, KEY_TARGET_ID)).intValue(); + } + + /** Helper to retrieve the --name for the new project action. */ + public String getNewProjectName() { + return ((String) getValue(ACTION_NEW_PROJECT, KEY_NAME)); + } + + /** Helper to retrieve the --package for the new project action. */ + public String getNewProjectPackage() { + return ((String) getValue(ACTION_NEW_PROJECT, KEY_PACKAGE)); + } + + /** Helper to retrieve the --activity for the new project action. */ + public String getNewProjectActivity() { + return ((String) getValue(ACTION_NEW_PROJECT, KEY_ACTIVITY)); + } + + // -- some helpers for update action flags + + /** Helper to retrieve the --out location for the update project action. */ + public String getUpdateProjectLocation() { + return ((String) getValue(ACTION_UPDATE_PROJECT, KEY_OUT)); + } + + /** Helper to retrieve the --target id for the update project action. */ + public int getUpdateProjectTargetId() { + return ((Integer) getValue(ACTION_UPDATE_PROJECT, KEY_TARGET_ID)).intValue(); + } +} |