aboutsummaryrefslogtreecommitdiffstats
path: root/sdkmanager/app/src
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:19 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-01-09 17:51:19 -0800
commita1514dae8668c48feae5436285e3db0ba2133ec3 (patch)
tree115c685f5c4c810cd317e8a6903e8d2d96749051 /sdkmanager/app/src
parent9ca1c0b33cc3fc28c21a915730797ec01e71a152 (diff)
downloadsdk-a1514dae8668c48feae5436285e3db0ba2133ec3.zip
sdk-a1514dae8668c48feae5436285e3db0ba2133ec3.tar.gz
sdk-a1514dae8668c48feae5436285e3db0ba2133ec3.tar.bz2
auto import from //branches/cupcake/...@125939
Diffstat (limited to 'sdkmanager/app/src')
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/CommandLineProcessor.java580
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/Main.java222
-rw-r--r--sdkmanager/app/src/com/android/sdkmanager/SdkCommandLine.java152
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();
+ }
+}