auto import from //depot/cupcake/@135843

This commit is contained in:
The Android Open Source Project
2009-03-03 19:29:09 -08:00
parent d4aee0c0ca
commit 52d4c30ca5
2386 changed files with 299112 additions and 0 deletions

View File

@@ -0,0 +1,16 @@
# Copyright 2007 The Android Open Source Project
#
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_JAR_MANIFEST := ../etc/manifest.txt
LOCAL_JAVA_LIBRARIES := \
androidprefs \
sdklib \
sdkuilib
LOCAL_MODULE := sdkmanager
include $(BUILD_HOST_JAVA_LIBRARY)

View File

@@ -0,0 +1,791 @@
/*
* 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.ISdkLog;
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, String)}.
*/
public class CommandLineProcessor {
/** Internal verb name for internally hidden flags. */
public final static String GLOBAL_FLAG_VERB = "@@internal@@";
/** String to use when the verb doesn't need any object. */
public final static String NO_VERB_OBJECT = "";
/** The global help flag. */
public static final String KEY_HELP = "help";
/** The global verbose flag. */
public static final String KEY_VERBOSE = "verbose";
/** The global silent flag. */
public static final String KEY_SILENT = "silent";
/** Verb requested by the user. Null if none specified, which will be an error. */
private String mVerbRequested;
/** Direct object requested by the user. Can be null. */
private String mDirectObjectRequested;
/**
* Action definitions.
* <p/>
* Each entry is a string array with:
* <ul>
* <li> the verb.
* <li> a direct object (use #NO_VERB_OBJECT if there's no object).
* <li> a description.
* <li> an alternate form for the object (e.g. plural).
* </ul>
*/
private final String[][] mActions;
private static final int ACTION_VERB_INDEX = 0;
private static final int ACTION_OBJECT_INDEX = 1;
private static final int ACTION_DESC_INDEX = 2;
private static final int ACTION_ALT_OBJECT_INDEX = 3;
/**
* The map of all defined arguments.
* <p/>
* The key is a string "verb/directObject/longName".
*/
private final HashMap<String, Arg> mArguments = new HashMap<String, Arg>();
/** Logger */
private final ISdkLog mLog;
public CommandLineProcessor(ISdkLog logger, String[][] actions) {
mLog = logger;
mActions = actions;
define(MODE.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "v", KEY_VERBOSE,
"Verbose mode: errors, warnings and informational messages are printed.",
false);
define(MODE.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "s", KEY_SILENT,
"Silent mode: only errors are printed out.",
false);
define(MODE.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "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_VERB, NO_VERB_OBJECT, KEY_VERBOSE)).booleanValue();
}
/** Helper that returns true if --silent was requested. */
public boolean isSilent() {
return ((Boolean) getValue(GLOBAL_FLAG_VERB, NO_VERB_OBJECT, KEY_SILENT)).booleanValue();
}
/** Helper that returns true if --help was requested. */
public boolean isHelpRequested() {
return ((Boolean) getValue(GLOBAL_FLAG_VERB, NO_VERB_OBJECT, KEY_HELP)).booleanValue();
}
/** Returns the verb name from the command-line. Can be null. */
public String getVerb() {
return mVerbRequested;
}
/** Returns the direct object name from the command-line. Can be null. */
public String getDirectObject() {
return mDirectObjectRequested;
}
//------------------
/**
* Raw access to parsed parameter values.
* <p/>
* The default is to scan all parameters. Parameters that have been explicitly set on the
* command line are returned first. Otherwise one with a non-null value is returned.
* <p/>
* Both a verb and a direct object filter can be specified. When they are non-null they limit
* the scope of the search.
* <p/>
* If nothing has been found, return the last default value seen matching the filter.
*
* @param verb The verb name, including {@link #GLOBAL_FLAG_VERB}. If null, all possible
* verbs that match the direct object condition will be examined and the first
* value set will be used.
* @param directObject The direct object name, including {@link #NO_VERB_OBJECT}. If null,
* all possible direct objects that match the verb condition will be examined and
* the first value set will be used.
* @param longFlagName The long flag name for the given action. Mandatory. Cannot be null.
* @return The current value object stored in the parameter, which depends on the argument mode.
*/
public Object getValue(String verb, String directObject, String longFlagName) {
if (verb != null && directObject != null) {
String key = verb + "/" + directObject + "/" + longFlagName;
Arg arg = mArguments.get(key);
return arg.getCurrentValue();
}
Object lastDefault = null;
for (Arg arg : mArguments.values()) {
if (arg.getLongArg().equals(longFlagName)) {
if (verb == null || arg.getVerb().equals(verb)) {
if (directObject == null || arg.getDirectObject().equals(directObject)) {
if (arg.isInCommandLine()) {
return arg.getCurrentValue();
}
if (arg.getCurrentValue() != null) {
lastDefault = arg.getCurrentValue();
}
}
}
}
}
return lastDefault;
}
/**
* Internal setter for raw parameter value.
* @param verb The verb name, including {@link #GLOBAL_FLAG_VERB}.
* @param directObject The direct object name, including {@link #NO_VERB_OBJECT}.
* @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 verb, String directObject, String longFlagName, Object value) {
String key = verb + "/" + directObject + "/" + 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 verb = null;
String directObject = null;
try {
int n = args.length;
for (int i = 0; i < n; i++) {
Arg arg = null;
String a = args[i];
if (a.startsWith("--")) {
arg = findLongArg(verb, directObject, a.substring(2));
} else if (a.startsWith("-")) {
arg = findShortArg(verb, directObject, a.substring(1));
}
// No matching argument name found
if (arg == null) {
// Does it looks like a dashed parameter?
if (a.startsWith("-")) {
if (verb == null || directObject == null) {
// It looks like a dashed parameter and we don't have a a verb/object
// set yet, the parameter was just given too early.
needsHelp = String.format(
"Flag '%1$s' is not a valid global flag. Did you mean to specify it after the verb/object name?",
a);
return;
} else {
// It looks like a dashed parameter and but it is unknown by this
// verb-object combination
needsHelp = String.format(
"Flag '%1$s' is not valid for '%2$s %3$s'.",
a, verb, directObject);
return;
}
}
if (verb == null) {
// Fill verb first. Find it.
for (String[] actionDesc : mActions) {
if (actionDesc[ACTION_VERB_INDEX].equals(a)) {
verb = a;
break;
}
}
// Error if it was not a valid verb
if (verb == null) {
needsHelp = String.format(
"Expected verb after global parameters but found '%1$s' instead.",
a);
return;
}
} else if (directObject == null) {
// Then fill the direct object. Find it.
for (String[] actionDesc : mActions) {
if (actionDesc[ACTION_VERB_INDEX].equals(verb)) {
if (actionDesc[ACTION_OBJECT_INDEX].equals(a)) {
directObject = a;
break;
} else if (actionDesc.length > ACTION_ALT_OBJECT_INDEX &&
actionDesc[ACTION_ALT_OBJECT_INDEX].equals(a)) {
// if the alternate form exist and is used, we internally
// only memorize the default direct object form.
directObject = actionDesc[ACTION_OBJECT_INDEX];
break;
}
}
}
// Error if it was not a valid object for that verb
if (directObject == null) {
needsHelp = String.format(
"Expected verb after global parameters but found '%1$s' instead.",
a);
return;
}
}
} else if (arg != null) {
// This argument was present on the command line
arg.setInCommandLine(true);
// Process keyword
String error = null;
if (arg.getMode().needsExtra()) {
if (++i >= n) {
needsHelp = String.format("Missing argument for flag %1$s.", a);
return;
}
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);
return;
}
}
}
if (needsHelp == null) {
if (verb == null) {
needsHelp = "Missing verb name.";
} else {
if (directObject == null) {
// Make sure this verb has an optional direct object
for (String[] actionDesc : mActions) {
if (actionDesc[ACTION_VERB_INDEX].equals(verb) &&
actionDesc[ACTION_OBJECT_INDEX].equals(NO_VERB_OBJECT)) {
directObject = NO_VERB_OBJECT;
break;
}
}
if (directObject == null) {
needsHelp = String.format("Missing object name for verb '%1$s'.", verb);
return;
}
}
// Validate that all mandatory arguments are non-null for this action
String missing = null;
boolean plural = false;
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getVerb().equals(verb) &&
arg.getDirectObject().equals(directObject)) {
if (arg.isMandatory() && arg.getCurrentValue() == null) {
if (missing == null) {
missing = "--" + arg.getLongArg();
} else {
missing += ", --" + arg.getLongArg();
plural = true;
}
}
}
}
if (missing != null) {
needsHelp = String.format(
"The %1$s %2$s must be defined for action '%3$s %4$s'",
plural ? "parameters" : "parameter",
missing,
verb,
directObject);
}
mVerbRequested = verb;
mDirectObjectRequested = directObject;
}
}
} finally {
if (needsHelp != null) {
printHelpAndExitForAction(verb, directObject, 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 verb, String directObject, String longName) {
if (verb == null) {
verb = GLOBAL_FLAG_VERB;
}
if (directObject == null) {
directObject = NO_VERB_OBJECT;
}
String key = verb + "/" + directObject + "/" + 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 verb, String directObject, String shortName) {
if (verb == null) {
verb = GLOBAL_FLAG_VERB;
}
if (directObject == null) {
directObject = NO_VERB_OBJECT;
}
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) {
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 /*verb*/, null /*directObject*/, errorFormat, args);
}
/**
* Prints the help/usage and exits.
*
* @param verb If null, displays help for all verbs. If not null, display help only
* for that specific verb. In all cases also displays general usage and action list.
* @param directObject If null, displays help for all verb objects.
* If not null, displays 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 verb, String directObject,
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_VERB, NO_VERB_OBJECT);
if (verb == null || directObject == null) {
stdout("\nValid actions are composed of a verb and an optional direct object:");
for (String[] action : mActions) {
stdout("- %1$6s %2$-7s: %3$s",
action[ACTION_VERB_INDEX],
action[ACTION_OBJECT_INDEX],
action[ACTION_DESC_INDEX]);
}
}
for (String[] action : mActions) {
if (verb == null || verb.equals(action[ACTION_VERB_INDEX])) {
if (directObject == null || directObject.equals(action[ACTION_OBJECT_INDEX])) {
stdout("\nAction \"%1$s %2$s\":",
action[ACTION_VERB_INDEX],
action[ACTION_OBJECT_INDEX]);
stdout(" %1$s", action[ACTION_DESC_INDEX]);
stdout("Options:");
listOptions(action[ACTION_VERB_INDEX], action[ACTION_OBJECT_INDEX]);
}
}
}
exit();
}
/**
* Internal helper to print all the option flags for a given action name.
*/
protected void listOptions(String verb, String directObject) {
int numOptions = 0;
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) {
String value = "";
if (arg.getDefaultValue() instanceof String[]) {
for (String v : (String[]) arg.getDefaultValue()) {
if (value.length() > 0) {
value += ", ";
}
value += v;
}
} else if (arg.getDefaultValue() != null) {
value = arg.getDefaultValue().toString();
}
if (value.length() > 0) {
value = " (" + value + ")";
}
String required = arg.isMandatory() ? " [required]" : "";
stdout(" -%1$s %2$-10s %3$s%4$s%5$s",
arg.getShortArg(),
"--" + arg.getLongArg(),
arg.getDescription(),
value,
required);
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 {
/** Verb for that argument. Never null. */
private final String mVerb;
/** Direct Object for that argument. Never null, but can be empty string. */
private final String mDirectObject;
/** The 1-letter short name of the argument, e.g. -v. */
private final String mShortName;
/** The long name of the argument, e.g. --verbose. */
private final String mLongName;
/** A description. Never null. */
private final String mDescription;
/** A default value. Can be null. */
private final Object mDefaultValue;
/** The argument mode (type + process method). Never null. */
private final MODE mMode;
/** True if this argument is mandatory for this verb/directobject. */
private final boolean mMandatory;
/** Current value. Initially set to the default value. */
private Object mCurrentValue;
/** True if the argument has been used on the command line. */
private boolean mInCommandLine;
/**
* 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 directObject The action name. Can be #NO_VERB_OBJECT 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 verb,
String directObject,
String shortName,
String longName,
String description,
Object defaultValue) {
mMode = mode;
mMandatory = mandatory;
mVerb = verb;
mDirectObject = directObject;
mShortName = shortName;
mLongName = longName;
mDescription = description;
mDefaultValue = defaultValue;
mInCommandLine = false;
if (defaultValue instanceof String[]) {
mCurrentValue = ((String[])defaultValue)[0];
} else {
mCurrentValue = mDefaultValue;
}
}
/** Return true if this argument is mandatory for this verb/directobject. */
public boolean isMandatory() {
return mMandatory;
}
/** Returns the 1-letter short name of the argument, e.g. -v. */
public String getShortArg() {
return mShortName;
}
/** Returns the long name of the argument, e.g. --verbose. */
public String getLongArg() {
return mLongName;
}
/** Returns the description. Never null. */
public String getDescription() {
return mDescription;
}
/** Returns the verb for that argument. Never null. */
public String getVerb() {
return mVerb;
}
/** Returns the direct Object for that argument. Never null, but can be empty string. */
public String getDirectObject() {
return mDirectObject;
}
/** Returns the default value. Can be null. */
public Object getDefaultValue() {
return mDefaultValue;
}
/** Returns the current value. Initially set to the default value. Can be null. */
public Object getCurrentValue() {
return mCurrentValue;
}
/** Sets the current value. Can be null. */
public void setCurrentValue(Object currentValue) {
mCurrentValue = currentValue;
}
/** Returns the argument mode (type + process method). Never null. */
public MODE getMode() {
return mMode;
}
/** Returns true if the argument has been used on the command line. */
public boolean isInCommandLine() {
return mInCommandLine;
}
/** Sets if the argument has been used on the command line. */
public void setInCommandLine(boolean inCommandLine) {
mInCommandLine = inCommandLine;
}
}
/**
* Internal helper to define a new argument for a give action.
*
* @param mode The {@link MODE} for the argument.
* @param verb The verb name. Can be #INTERNAL_VERB.
* @param directObject The action name. Can be #NO_VERB_OBJECT 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 verb,
String directObject,
String shortName, String longName,
String description, Object defaultValue) {
assert(mandatory || mode == MODE.BOOLEAN); // a boolean mode cannot be mandatory
if (directObject == null) {
directObject = NO_VERB_OBJECT;
}
String key = verb + "/" + directObject + "/" + longName;
mArguments.put(key, new Arg(mode, mandatory,
verb, directObject, 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) {
mLog.printf(format + "\n", 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) {
mLog.error(null, format, args);
}
}

View File

@@ -0,0 +1,813 @@
/*
* 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.prefs.AndroidLocation;
import com.android.prefs.AndroidLocation.AndroidLocationException;
import com.android.sdklib.IAndroidTarget;
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.avd.AvdManager;
import com.android.sdklib.avd.HardwareProperties;
import com.android.sdklib.avd.AvdManager.AvdInfo;
import com.android.sdklib.avd.HardwareProperties.HardwareProperty;
import com.android.sdklib.project.ProjectCreator;
import com.android.sdklib.project.ProjectCreator.OutputLevel;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Main class for the 'android' application.
*/
class Main {
/** Java property that defines the location of the sdk/tools directory. */
private final static String TOOLSDIR = "com.android.sdkmanager.toolsdir";
/** Java property that defines the working directory. On Windows the current working directory
* is actually the tools dir, in which case this is used to get the original CWD. */
private final static String WORKDIR = "com.android.sdkmanager.workdir";
private final static String[] BOOLEAN_YES_REPLIES = new String[] { "yes", "y" };
private final static String[] BOOLEAN_NO_REPLIES = new String[] { "no", "n" };
/** Path to the SDK folder. This is the parent of {@link #TOOLSDIR}. */
private String mSdkFolder;
/** Logger object. Use this to print normal output, warnings or errors. */
private ISdkLog mSdkLog;
/** The SDK manager parses the SDK folder and gives access to the content. */
private SdkManager mSdkManager;
/** Command-line processor with options specific to SdkManager. */
private SdkCommandLine mSdkCommandLine;
/** The working directory, either null or set to an existing absolute canonical directory. */
private File mWorkDir;
public static void main(String[] args) {
new Main().run(args);
}
/**
* Runs the sdk manager app
*/
private void run(String[] args) {
createLogger();
init();
mSdkCommandLine.parseArgs(args);
parseSdk();
doAction();
}
/**
* Creates the {@link #mSdkLog} object.
* <p/>
* This must be done before {@link #init()} as it will be used to report errors.
*/
private void createLogger() {
mSdkLog = new ISdkLog() {
public void error(Throwable t, String errorFormat, Object... args) {
if (errorFormat != null) {
System.err.printf("Error: " + errorFormat, args);
if (!errorFormat.endsWith("\n")) {
System.err.printf("\n");
}
}
if (t != null) {
System.err.printf("Error: %s\n", t.getMessage());
}
}
public void warning(String warningFormat, Object... args) {
if (mSdkCommandLine.isVerbose()) {
System.out.printf("Warning: " + warningFormat, args);
if (!warningFormat.endsWith("\n")) {
System.out.printf("\n");
}
}
}
public void printf(String msgFormat, Object... args) {
System.out.printf(msgFormat, args);
}
};
}
/**
* Init the application by making sure the SDK path is available and
* doing basic parsing of the SDK.
*/
private void init() {
mSdkCommandLine = new SdkCommandLine(mSdkLog);
// 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) {
// 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
}
}
}
if (mSdkFolder == null) {
errorAndExit("The tools directory property is not set, please make sure you are executing %1$s",
SdkConstants.androidCmdName());
}
// We might get passed a property for the working directory
// Either it is a valid directory and mWorkDir is set to it's absolute canonical value
// or mWorkDir remains null.
String workDirProp = System.getProperty(WORKDIR);
if (workDirProp == null) {
workDirProp = System.getenv(WORKDIR);
}
if (workDirProp != null) {
// This should be a valid directory
mWorkDir = new File(workDirProp);
try {
mWorkDir = mWorkDir.getCanonicalFile().getAbsoluteFile();
} catch (IOException e) {
mWorkDir = null;
}
if (mWorkDir == null || !mWorkDir.isDirectory()) {
errorAndExit("The working directory does not seem to be valid: '%1$s", workDirProp);
}
}
}
/**
* Does the basic SDK parsing required for all actions
*/
private void parseSdk() {
mSdkManager = SdkManager.createManager(mSdkFolder, mSdkLog);
if (mSdkManager == null) {
errorAndExit("Unable to parse SDK content.");
}
}
/**
* Actually do an action...
*/
private void doAction() {
String verb = mSdkCommandLine.getVerb();
String directObject = mSdkCommandLine.getDirectObject();
if (SdkCommandLine.VERB_LIST.equals(verb)) {
// list action.
if (SdkCommandLine.OBJECT_TARGET.equals(directObject)) {
displayTargetList();
} else if (SdkCommandLine.OBJECT_AVD.equals(directObject)) {
displayAvdList();
} else {
displayTargetList();
displayAvdList();
}
} else if (SdkCommandLine.VERB_CREATE.equals(verb) &&
SdkCommandLine.OBJECT_AVD.equals(directObject)) {
createAvd();
} else if (SdkCommandLine.VERB_DELETE.equals(verb) &&
SdkCommandLine.OBJECT_AVD.equals(directObject)) {
deleteAvd();
} else if (SdkCommandLine.VERB_MOVE.equals(verb) &&
SdkCommandLine.OBJECT_AVD.equals(directObject)) {
moveAvd();
} else if (SdkCommandLine.VERB_CREATE.equals(verb) &&
SdkCommandLine.OBJECT_PROJECT.equals(directObject)) {
createProject();
} else if (SdkCommandLine.VERB_UPDATE.equals(verb) &&
SdkCommandLine.OBJECT_PROJECT.equals(directObject)) {
updateProject();
} else {
mSdkCommandLine.printHelpAndExit(null);
}
}
/**
* Creates a new Android project based on command-line parameters
*/
private void createProject() {
// get the target and try to resolve it.
int targetId = mSdkCommandLine.getParamTargetId();
IAndroidTarget[] targets = mSdkManager.getTargets();
if (targetId < 1 || targetId > targets.length) {
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
SdkConstants.androidCmdName());
}
IAndroidTarget target = targets[targetId - 1];
ProjectCreator creator = new ProjectCreator(mSdkFolder,
mSdkCommandLine.isVerbose() ? OutputLevel.VERBOSE :
mSdkCommandLine.isSilent() ? OutputLevel.SILENT :
OutputLevel.NORMAL,
mSdkLog);
String projectDir = getProjectLocation(mSdkCommandLine.getParamLocationPath());
creator.createProject(projectDir,
mSdkCommandLine.getParamName(),
mSdkCommandLine.getParamProjectPackage(),
mSdkCommandLine.getParamProjectActivity(),
target,
false /* isTestProject*/);
}
/**
* Updates an existing Android project based on command-line parameters
*/
private void updateProject() {
// get the target and try to resolve it.
IAndroidTarget target = null;
int targetId = mSdkCommandLine.getParamTargetId();
if (targetId >= 0) {
IAndroidTarget[] targets = mSdkManager.getTargets();
if (targetId < 1 || targetId > targets.length) {
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
SdkConstants.androidCmdName());
}
target = targets[targetId - 1];
}
ProjectCreator creator = new ProjectCreator(mSdkFolder,
mSdkCommandLine.isVerbose() ? OutputLevel.VERBOSE :
mSdkCommandLine.isSilent() ? OutputLevel.SILENT :
OutputLevel.NORMAL,
mSdkLog);
String projectDir = getProjectLocation(mSdkCommandLine.getParamLocationPath());
creator.updateProject(projectDir,
target,
mSdkCommandLine.getParamName());
}
/**
* Adjusts the project location to make it absolute & canonical relative to the
* working directory, if any.
*
* @return The project absolute path relative to {@link #mWorkDir} or the original
* newProjectLocation otherwise.
*/
private String getProjectLocation(String newProjectLocation) {
// If the new project location is absolute, use it as-is
File projectDir = new File(newProjectLocation);
if (projectDir.isAbsolute()) {
return newProjectLocation;
}
// if there's no working directory, just use the project location as-is.
if (mWorkDir == null) {
return newProjectLocation;
}
// Combine then and get an absolute canonical directory
try {
projectDir = new File(mWorkDir, newProjectLocation).getCanonicalFile();
return projectDir.getPath();
} catch (IOException e) {
errorAndExit("Failed to combine working directory '%1$s' with project location '%2$s': %3$s",
mWorkDir.getPath(),
newProjectLocation,
e.getMessage());
return null;
}
}
/**
* Displays the list of available Targets (Platforms and Add-ons)
*/
private void displayTargetList() {
mSdkLog.printf("Available Android targets:\n");
int index = 1;
for (IAndroidTarget target : mSdkManager.getTargets()) {
if (target.isPlatform()) {
mSdkLog.printf("[%d] %s\n", index, target.getName());
mSdkLog.printf(" API level: %d\n", target.getApiVersionNumber());
} else {
mSdkLog.printf("[%d] Add-on: %s\n", index, target.getName());
mSdkLog.printf(" Vendor: %s\n", target.getVendor());
if (target.getDescription() != null) {
mSdkLog.printf(" Description: %s\n", target.getDescription());
}
mSdkLog.printf(" Based on Android %s (API level %d)\n",
target.getApiVersionName(), target.getApiVersionNumber());
// display the optional libraries.
IOptionalLibrary[] libraries = target.getOptionalLibraries();
if (libraries != null) {
mSdkLog.printf(" Libraries:\n");
for (IOptionalLibrary library : libraries) {
mSdkLog.printf(" * %1$s (%2$s)\n",
library.getName(), library.getJarName());
mSdkLog.printf(String.format(
" %1$s\n", library.getDescription()));
}
}
}
// get the target skins
displaySkinList(target, " Skins: ");
index++;
}
}
/**
* Displays the skins valid for the given target.
*/
private void displaySkinList(IAndroidTarget target, String message) {
String[] skins = target.getSkins();
String defaultSkin = target.getDefaultSkin();
mSdkLog.printf(message);
if (skins != null) {
boolean first = true;
for (String skin : skins) {
if (first == false) {
mSdkLog.printf(", ");
} else {
first = false;
}
mSdkLog.printf(skin);
if (skin.equals(defaultSkin)) {
mSdkLog.printf(" (default)");
}
}
mSdkLog.printf("\n");
} else {
mSdkLog.printf("no skins.\n");
}
}
/**
* Displays the list of available AVDs.
*/
private void displayAvdList() {
try {
AvdManager avdManager = new AvdManager(mSdkManager, mSdkLog);
mSdkLog.printf("Available Android Virtual Devices:\n");
AvdInfo[] avds = avdManager.getAvds();
for (int index = 0 ; index < avds.length ; index++) {
AvdInfo info = avds[index];
if (index > 0) {
mSdkLog.printf("---------\n");
}
mSdkLog.printf(" Name: %s\n", info.getName());
mSdkLog.printf(" Path: %s\n", info.getPath());
// get the target of the AVD
IAndroidTarget target = info.getTarget();
if (target.isPlatform()) {
mSdkLog.printf(" Target: %s (API level %d)\n", target.getName(),
target.getApiVersionNumber());
} else {
mSdkLog.printf(" Target: %s (%s)\n", target.getName(), target
.getVendor());
mSdkLog.printf(" Based on Android %s (API level %d)\n", target
.getApiVersionName(), target.getApiVersionNumber());
}
// display some extra values.
Map<String, String> properties = info.getProperties();
String skin = properties.get(AvdManager.AVD_INI_SKIN_NAME);
if (skin != null) {
mSdkLog.printf(" Skin: %s\n", skin);
}
String sdcard = properties.get(AvdManager.AVD_INI_SDCARD_SIZE);
if (sdcard == null) {
sdcard = properties.get(AvdManager.AVD_INI_SDCARD_PATH);
}
if (sdcard != null) {
mSdkLog.printf(" Sdcard: %s\n", sdcard);
}
}
} catch (AndroidLocationException e) {
errorAndExit(e.getMessage());
}
}
/**
* Creates a new AVD. This is a text based creation with command line prompt.
*/
private void createAvd() {
// find a matching target
int targetId = mSdkCommandLine.getParamTargetId();
IAndroidTarget target = null;
if (targetId >= 1 && targetId <= mSdkManager.getTargets().length) {
target = mSdkManager.getTargets()[targetId-1]; // target it is 1-based
} else {
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
SdkConstants.androidCmdName());
}
try {
boolean removePrevious = false;
AvdManager avdManager = new AvdManager(mSdkManager, mSdkLog);
String avdName = mSdkCommandLine.getParamName();
AvdInfo info = avdManager.getAvd(avdName);
if (info != null) {
if (mSdkCommandLine.getFlagForce()) {
removePrevious = true;
mSdkLog.warning(
"Android Virtual Device '%s' already exists and will be replaced.",
avdName);
} else {
errorAndExit("Android Virtual Device '%s' already exists.", avdName);
return;
}
}
String paramFolderPath = mSdkCommandLine.getParamLocationPath();
File avdFolder = null;
if (paramFolderPath != null) {
avdFolder = new File(paramFolderPath);
} else {
avdFolder = new File(AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD,
avdName + AvdManager.AVD_FOLDER_EXTENSION);
}
Map<String, String> hardwareConfig = null;
if (target.isPlatform()) {
try {
hardwareConfig = promptForHardware(target);
} catch (IOException e) {
errorAndExit(e.getMessage());
}
}
AvdInfo oldAvdInfo = null;
if (removePrevious) {
oldAvdInfo = avdManager.getAvd(avdName);
}
// Validate skin is either default (empty) or NNNxMMM or a valid skin name.
String skin = mSdkCommandLine.getParamSkin();
if (skin != null && skin.length() == 0) {
skin = null;
}
if (skin != null) {
boolean valid = false;
// Is it a know skin name for this target?
for (String s : target.getSkins()) {
if (skin.equalsIgnoreCase(s)) {
skin = s; // Make skin names case-insensitive.
valid = true;
break;
}
}
// Is it NNNxMMM?
if (!valid) {
valid = AvdManager.NUMERIC_SKIN_SIZE.matcher(skin).matches();
}
if (!valid) {
displaySkinList(target, "Valid skins: ");
errorAndExit("'%s' is not a valid skin name or size (NNNxMMM)", skin);
return;
}
}
AvdInfo newAvdInfo = avdManager.createAvd(avdFolder,
avdName,
target,
skin,
mSdkCommandLine.getParamSdCard(),
hardwareConfig,
removePrevious,
mSdkLog);
if (newAvdInfo != null &&
oldAvdInfo != null &&
!oldAvdInfo.getPath().equals(newAvdInfo.getPath())) {
mSdkLog.warning("Removing previous AVD directory at %s", oldAvdInfo.getPath());
// Remove the old data directory
File dir = new File(oldAvdInfo.getPath());
avdManager.recursiveDelete(dir);
dir.delete();
// Remove old avd info from manager
avdManager.removeAvd(oldAvdInfo);
}
} catch (AndroidLocationException e) {
errorAndExit(e.getMessage());
}
}
/**
* Delete an AVD.
*/
private void deleteAvd() {
try {
String avdName = mSdkCommandLine.getParamName();
AvdManager avdManager = new AvdManager(mSdkManager, mSdkLog);
AvdInfo info = avdManager.getAvd(avdName);
if (info == null) {
errorAndExit("There is no Android Virtual Device named '%s'.", avdName);
return;
}
avdManager.deleteAvd(info, mSdkLog);
} catch (AndroidLocationException e) {
errorAndExit(e.getMessage());
}
}
/**
* Move an AVD.
*/
private void moveAvd() {
try {
String avdName = mSdkCommandLine.getParamName();
AvdManager avdManager = new AvdManager(mSdkManager, mSdkLog);
AvdInfo info = avdManager.getAvd(avdName);
if (info == null) {
errorAndExit("There is no Android Virtual Device named '%s'.", avdName);
return;
}
// This is a rename if there's a new name for the AVD
String newName = mSdkCommandLine.getParamMoveNewName();
if (newName != null && newName.equals(info.getName())) {
// same name, not actually a rename operation
newName = null;
}
// This is a move (of the data files) if there's a new location path
String paramFolderPath = mSdkCommandLine.getParamLocationPath();
if (paramFolderPath != null) {
// check if paths are the same. Use File methods to account for OS idiosyncrasies.
try {
File f1 = new File(paramFolderPath).getCanonicalFile();
File f2 = new File(info.getPath()).getCanonicalFile();
if (f1.equals(f2)) {
// same canonical path, so not actually a move
paramFolderPath = null;
}
} catch (IOException e) {
// Fail to resolve canonical path. Fail now since a move operation might fail
// later and be harder to recover from.
errorAndExit(e.getMessage());
return;
}
}
if (newName == null && paramFolderPath == null) {
mSdkLog.warning("Move operation aborted: same AVD name, same canonical data path");
return;
}
// If a rename was requested and no data move was requested, check if the original
// data path is our default constructed from the AVD name. In this case we still want
// to rename that folder too.
if (newName != null && paramFolderPath == null) {
// Compute the original data path
File originalFolder = new File(
AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD,
info.getName() + AvdManager.AVD_FOLDER_EXTENSION);
if (originalFolder.equals(info.getPath())) {
try {
// The AVD is using the default data folder path based on the AVD name.
// That folder needs to be adjusted to use the new name.
File f = new File(AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD,
newName + AvdManager.AVD_FOLDER_EXTENSION);
paramFolderPath = f.getCanonicalPath();
} catch (IOException e) {
// Fail to resolve canonical path. Fail now rather than later.
errorAndExit(e.getMessage());
}
}
}
// Check for conflicts
if (newName != null && avdManager.getAvd(newName) != null) {
errorAndExit("There is already an AVD named '%s'.", newName);
return;
}
if (newName != null) {
if (avdManager.getAvd(newName) != null) {
errorAndExit("There is already an AVD named '%s'.", newName);
return;
}
File ini = info.getIniFile();
if (ini.equals(AvdInfo.getIniFile(newName))) {
errorAndExit("The AVD file '%s' is in the way.", ini.getCanonicalPath());
return;
}
}
if (paramFolderPath != null && new File(paramFolderPath).exists()) {
errorAndExit(
"There is already a file or directory at '%s'.\nUse --path to specify a different data folder.",
paramFolderPath);
}
avdManager.moveAvd(info, newName, paramFolderPath, mSdkLog);
} catch (AndroidLocationException e) {
errorAndExit(e.getMessage());
} catch (IOException e) {
errorAndExit(e.getMessage());
}
}
/**
* Prompts the user to setup a hardware config for a Platform-based AVD.
* @throws IOException
*/
private Map<String, String> promptForHardware(IAndroidTarget createTarget) throws IOException {
byte[] readLineBuffer = new byte[256];
String result;
String defaultAnswer = "no";
mSdkLog.printf("%s is a basic Android platform.\n", createTarget.getName());
mSdkLog.printf("Do you wish to create a custom hardware profile [%s]",
defaultAnswer);
result = readLine(readLineBuffer).trim();
// handle default:
if (result.length() == 0) {
result = defaultAnswer;
}
if (getBooleanReply(result) == false) {
// no custom config.
return null;
}
mSdkLog.printf("\n"); // empty line
// get the list of possible hardware properties
File hardwareDefs = new File (mSdkFolder + File.separator +
SdkConstants.OS_SDK_TOOLS_LIB_FOLDER, SdkConstants.FN_HARDWARE_INI);
List<HardwareProperty> list = HardwareProperties.parseHardwareDefinitions(hardwareDefs,
null /*sdkLog*/);
HashMap<String, String> map = new HashMap<String, String>();
for (int i = 0 ; i < list.size() ;) {
HardwareProperty property = list.get(i);
String description = property.getDescription();
if (description != null) {
mSdkLog.printf("%s: %s\n", property.getAbstract(), description);
} else {
mSdkLog.printf("%s\n", property.getAbstract());
}
String defaultValue = property.getDefault();
if (defaultValue != null) {
mSdkLog.printf("%s [%s]:", property.getName(), defaultValue);
} else {
mSdkLog.printf("%s (%s):", property.getName(), property.getType());
}
result = readLine(readLineBuffer);
if (result.length() == 0) {
if (defaultValue != null) {
mSdkLog.printf("\n"); // empty line
i++; // go to the next property if we have a valid default value.
// if there's no default, we'll redo this property
}
continue;
}
switch (property.getType()) {
case BOOLEAN:
try {
if (getBooleanReply(result)) {
map.put(property.getName(), "yes");
i++; // valid reply, move to next property
} else {
map.put(property.getName(), "no");
i++; // valid reply, move to next property
}
} catch (IOException e) {
// display error, and do not increment i to redo this property
mSdkLog.printf("\n%s\n", e.getMessage());
}
break;
case INTEGER:
try {
Integer.parseInt(result);
map.put(property.getName(), result);
i++; // valid reply, move to next property
} catch (NumberFormatException e) {
// display error, and do not increment i to redo this property
mSdkLog.printf("\n%s\n", e.getMessage());
}
break;
case DISKSIZE:
// TODO check validity
map.put(property.getName(), result);
i++; // valid reply, move to next property
break;
}
mSdkLog.printf("\n"); // empty line
}
return map;
}
/**
* Reads the line from the input stream.
* @param buffer
* @throws IOException
*/
private String readLine(byte[] buffer) throws IOException {
int count = System.in.read(buffer);
// is the input longer than the buffer?
if (count == buffer.length && buffer[count-1] != 10) {
// create a new temp buffer
byte[] tempBuffer = new byte[256];
// and read the rest
String secondHalf = readLine(tempBuffer);
// return a concat of both
return new String(buffer, 0, count) + secondHalf;
}
// ignore end whitespace
while (count > 0 && (buffer[count-1] == '\r' || buffer[count-1] == '\n')) {
count--;
}
return new String(buffer, 0, count);
}
/**
* Returns the boolean value represented by the string.
* @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;
}
}
for (String valid : BOOLEAN_NO_REPLIES) {
if (valid.equalsIgnoreCase(reply)) {
return false;
}
}
throw new IOException(String.format("%s is not a valid reply", reply));
}
private void errorAndExit(String format, Object...args) {
mSdkLog.error(null, format, args);
System.exit(1);
}
}

View File

@@ -0,0 +1,220 @@
/*
* 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.ISdkLog;
import com.android.sdklib.SdkManager;
/**
* Specific command-line flags for the {@link SdkManager}.
*/
public class SdkCommandLine extends CommandLineProcessor {
public final static String VERB_LIST = "list";
public final static String VERB_CREATE = "create";
public final static String VERB_MOVE = "move";
public final static String VERB_DELETE = "delete";
public final static String VERB_UPDATE = "update";
public static final String OBJECT_AVD = "avd";
public static final String OBJECT_AVDS = "avds";
public static final String OBJECT_TARGET = "target";
public static final String OBJECT_TARGETS = "targets";
public static final String OBJECT_PROJECT = "project";
public static final String ARG_ALIAS = "alias";
public static final String ARG_ACTIVITY = "activity";
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 = OBJECT_TARGET;
public static final String KEY_NAME = "name";
public static final String KEY_PATH = "path";
public static final String KEY_FILTER = "filter";
public static final String KEY_SKIN = "skin";
public static final String KEY_SDCARD = "sdcard";
public static final String KEY_FORCE = "force";
public static final String KEY_RENAME = "rename";
/**
* Action definitions for SdkManager command line.
* <p/>
* Each entry is a string array with:
* <ul>
* <li> the verb.
* <li> an object (use #NO_VERB_OBJECT if there's no object).
* <li> a description.
* <li> an alternate form for the object (e.g. plural).
* </ul>
*/
private final static String[][] ACTIONS = {
{ VERB_LIST, NO_VERB_OBJECT,
"Lists existing targets or virtual devices." },
{ VERB_LIST, OBJECT_AVD,
"Lists existing Android Virtual Devices.",
OBJECT_AVDS },
{ VERB_LIST, OBJECT_TARGET,
"Lists existing targets.",
OBJECT_TARGETS },
{ VERB_CREATE, OBJECT_AVD,
"Creates a new Android Virtual Device." },
{ VERB_MOVE, OBJECT_AVD,
"Moves or renames an Android Virtual Device." },
{ VERB_DELETE, OBJECT_AVD,
"Deletes an Android Virtual Device." },
{ VERB_CREATE, OBJECT_PROJECT,
"Creates a new Android Project." },
{ VERB_UPDATE, OBJECT_PROJECT,
"Updates an Android Project (must have an AndroidManifest.xml)." },
};
public SdkCommandLine(ISdkLog logger) {
super(logger, ACTIONS);
// --- create avd ---
define(MODE.STRING, false,
VERB_CREATE, OBJECT_AVD, "p", KEY_PATH,
"Location path of the directory where the new AVD will be created", null);
define(MODE.STRING, true,
VERB_CREATE, OBJECT_AVD, "n", KEY_NAME,
"Name of the new AVD", null);
define(MODE.INTEGER, true,
VERB_CREATE, OBJECT_AVD, "t", KEY_TARGET_ID,
"Target id of the new AVD", null);
define(MODE.STRING, false,
VERB_CREATE, OBJECT_AVD, "s", KEY_SKIN,
"Skin of the new AVD", null);
define(MODE.STRING, false,
VERB_CREATE, OBJECT_AVD, "c", KEY_SDCARD,
"Path to a shared SD card image, or size of a new sdcard for the new AVD", null);
define(MODE.BOOLEAN, false,
VERB_CREATE, OBJECT_AVD, "f", KEY_FORCE,
"Force creation (override an existing AVD)", false);
// --- delete avd ---
define(MODE.STRING, true,
VERB_DELETE, OBJECT_AVD, "n", KEY_NAME,
"Name of the AVD to delete", null);
// --- move avd ---
define(MODE.STRING, true,
VERB_MOVE, OBJECT_AVD, "n", KEY_NAME,
"Name of the AVD to move or rename", null);
define(MODE.STRING, false,
VERB_MOVE, OBJECT_AVD, "r", KEY_RENAME,
"New name of the AVD to rename", null);
define(MODE.STRING, false,
VERB_MOVE, OBJECT_AVD, "p", KEY_PATH,
"New location path of the directory where to move the AVD", null);
// --- create project ---
define(MODE.ENUM, true,
VERB_CREATE, OBJECT_PROJECT, "m", KEY_MODE,
"Project mode", new String[] { ARG_ACTIVITY, ARG_ALIAS });
define(MODE.STRING, true,
VERB_CREATE, OBJECT_PROJECT,
"p", KEY_PATH,
"Location path of new project", null);
define(MODE.INTEGER, true,
VERB_CREATE, OBJECT_PROJECT, "t", KEY_TARGET_ID,
"Target id of the new project", null);
define(MODE.STRING, true,
VERB_CREATE, OBJECT_PROJECT, "k", KEY_PACKAGE,
"Package name", null);
define(MODE.STRING, true,
VERB_CREATE, OBJECT_PROJECT, "a", KEY_ACTIVITY,
"Activity name", null);
define(MODE.STRING, false,
VERB_CREATE, OBJECT_PROJECT, "n", KEY_NAME,
"Project name", null);
// --- update project ---
define(MODE.STRING, true,
VERB_UPDATE, OBJECT_PROJECT,
"p", KEY_PATH,
"Location path of the project", null);
define(MODE.INTEGER, true,
VERB_UPDATE, OBJECT_PROJECT,
"t", KEY_TARGET_ID,
"Target id to set for the project", -1);
define(MODE.STRING, false,
VERB_UPDATE, OBJECT_PROJECT,
"n", KEY_NAME,
"Project name", null);
}
// -- some helpers for generic action flags
/** Helper to retrieve the --path value. */
public String getParamLocationPath() {
return ((String) getValue(null, null, KEY_PATH));
}
/** Helper to retrieve the --target id value. */
public int getParamTargetId() {
return ((Integer) getValue(null, null, KEY_TARGET_ID)).intValue();
}
/** Helper to retrieve the --name value. */
public String getParamName() {
return ((String) getValue(null, null, KEY_NAME));
}
/** Helper to retrieve the --skin value. */
public String getParamSkin() {
return ((String) getValue(null, null, KEY_SKIN));
}
/** Helper to retrieve the --sdcard value. */
public String getParamSdCard() {
return ((String) getValue(null, null, KEY_SDCARD));
}
/** Helper to retrieve the --force flag. */
public boolean getFlagForce() {
return ((Boolean) getValue(null, null, KEY_FORCE)).booleanValue();
}
// -- some helpers for avd action flags
/** Helper to retrieve the --rename value for a move verb. */
public String getParamMoveNewName() {
return ((String) getValue(VERB_MOVE, null, KEY_RENAME));
}
// -- some helpers for project action flags
/** Helper to retrieve the --package value. */
public String getParamProjectPackage() {
return ((String) getValue(null, OBJECT_PROJECT, KEY_PACKAGE));
}
/** Helper to retrieve the --activity for the new project action. */
public String getParamProjectActivity() {
return ((String) getValue(null, OBJECT_PROJECT, KEY_ACTIVITY));
}
}