auto import from //branches/cupcake/...@130745
This commit is contained in:
@@ -31,52 +31,67 @@ import java.util.Map.Entry;
|
||||
* <li>define flags for your actions.
|
||||
* </ul>
|
||||
* <p/>
|
||||
* To use, call {@link #parseArgs(String[])} and then call {@link #getValue(String, String)}.
|
||||
* To use, call {@link #parseArgs(String[])} and then
|
||||
* call {@link #getValue(String, 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";
|
||||
|
||||
/** 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";
|
||||
/** The internal action flag. */
|
||||
public static final String KEY_ACTION = "action";
|
||||
|
||||
/** 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;
|
||||
|
||||
/** List of available actions.
|
||||
/**
|
||||
* Action definitions.
|
||||
* <p/>
|
||||
* Each entry must be a 2-string array with first the action name and then
|
||||
* a description.
|
||||
* 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;
|
||||
/** The hash of all defined arguments.
|
||||
|
||||
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 "action/longName".
|
||||
* 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.STRING, false, INTERNAL_FLAG, null, KEY_ACTION,
|
||||
"Selected Action", null);
|
||||
|
||||
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "v", KEY_VERBOSE,
|
||||
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, "s", KEY_SILENT,
|
||||
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, "h", KEY_HELP,
|
||||
define(MODE.BOOLEAN, false, GLOBAL_FLAG_VERB, NO_VERB_OBJECT, "h", KEY_HELP,
|
||||
"This help.",
|
||||
false);
|
||||
}
|
||||
@@ -86,47 +101,54 @@ public class CommandLineProcessor {
|
||||
|
||||
/** Helper that returns true if --verbose was requested. */
|
||||
public boolean isVerbose() {
|
||||
return ((Boolean) getValue(GLOBAL_FLAG, KEY_VERBOSE)).booleanValue();
|
||||
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, KEY_SILENT)).booleanValue();
|
||||
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, KEY_HELP)).booleanValue();
|
||||
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;
|
||||
}
|
||||
|
||||
/** Helper that returns the requested action name. */
|
||||
public String getActionRequested() {
|
||||
return (String) getValue(INTERNAL_FLAG, KEY_ACTION);
|
||||
/** Returns the direct object name from the command-line. Can be null. */
|
||||
public String getDirectObject() {
|
||||
return mDirectObjectRequested;
|
||||
}
|
||||
|
||||
//------------------
|
||||
|
||||
/**
|
||||
* Raw access to parsed parameter values.
|
||||
* @param action The action name, including {@link #GLOBAL_FLAG} and {@link #INTERNAL_FLAG}
|
||||
* @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.
|
||||
* @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;
|
||||
public Object getValue(String verb, String directObject, String longFlagName) {
|
||||
String key = verb + "/" + directObject + "/" + 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 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 action, String longFlagName, Object value) {
|
||||
String key = action + "/" + longFlagName;
|
||||
protected void setValue(String verb, String directObject, String longFlagName, Object value) {
|
||||
String key = verb + "/" + directObject + "/" + longFlagName;
|
||||
Arg arg = mArguments.get(key);
|
||||
arg.setCurrentValue(value);
|
||||
}
|
||||
@@ -140,114 +162,172 @@ public class CommandLineProcessor {
|
||||
*/
|
||||
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) {
|
||||
String verb = null;
|
||||
String directObject = 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;
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
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;
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
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.
|
||||
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) {
|
||||
// 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 (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
|
||||
String missing = null;
|
||||
boolean plural = false;
|
||||
for (Entry<String, Arg> entry : mArguments.entrySet()) {
|
||||
Arg arg = entry.getValue();
|
||||
if (arg.getAction().equals(action)) {
|
||||
if (arg.isMandatory() && arg.getCurrentValue() == null) {
|
||||
if (missing == null) {
|
||||
missing = "--" + arg.getLongArg();
|
||||
} else {
|
||||
missing += ", --" + arg.getLongArg();
|
||||
plural = true;
|
||||
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);
|
||||
}
|
||||
|
||||
if (missing != null) {
|
||||
needsHelp = String.format("The %1$s %2$s must be defined for action '%3$s'",
|
||||
plural ? "parameters" : "parameter",
|
||||
missing,
|
||||
action);
|
||||
mVerbRequested = verb;
|
||||
mDirectObjectRequested = directObject;
|
||||
}
|
||||
|
||||
setValue(INTERNAL_FLAG, KEY_ACTION, action);
|
||||
}
|
||||
}
|
||||
|
||||
if (needsHelp != null) {
|
||||
printHelpAndExitForAction(action, needsHelp);
|
||||
} finally {
|
||||
if (needsHelp != null) {
|
||||
printHelpAndExitForAction(verb, directObject, needsHelp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,11 +335,14 @@ public class CommandLineProcessor {
|
||||
* 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;
|
||||
protected Arg findLongArg(String verb, String directObject, String longName) {
|
||||
if (verb == null) {
|
||||
verb = GLOBAL_FLAG_VERB;
|
||||
}
|
||||
String key = action + "/" + longName;
|
||||
if (directObject == null) {
|
||||
directObject = NO_VERB_OBJECT;
|
||||
}
|
||||
String key = verb + "/" + directObject + "/" + longName;
|
||||
return mArguments.get(key);
|
||||
}
|
||||
|
||||
@@ -267,14 +350,17 @@ public class CommandLineProcessor {
|
||||
* 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;
|
||||
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.getAction().equals(action)) {
|
||||
if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) {
|
||||
if (shortName.equals(arg.getShortArg())) {
|
||||
return arg;
|
||||
}
|
||||
@@ -291,18 +377,22 @@ public class CommandLineProcessor {
|
||||
* @param args Arguments for String.format
|
||||
*/
|
||||
public void printHelpAndExit(String errorFormat, Object... args) {
|
||||
printHelpAndExitForAction(null /*actionFilter*/, errorFormat, args);
|
||||
printHelpAndExitForAction(null /*verb*/, null /*directObject*/, 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 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 actionFilter, String errorFormat, Object... args) {
|
||||
public void printHelpAndExitForAction(String verb, String directObject,
|
||||
String errorFormat, Object... args) {
|
||||
if (errorFormat != null) {
|
||||
stderr(errorFormat, args);
|
||||
}
|
||||
@@ -316,25 +406,27 @@ public class CommandLineProcessor {
|
||||
" android [global options] action [action options]\n" +
|
||||
"\n" +
|
||||
"Global options:");
|
||||
listOptions(GLOBAL_FLAG);
|
||||
listOptions(GLOBAL_FLAG_VERB, NO_VERB_OBJECT);
|
||||
|
||||
stdout("\nValid actions:");
|
||||
stdout("\nValid actions are composed of a verb and an optional direct object:");
|
||||
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]);
|
||||
stdout("- %1$6s %2$-7s: %3$s",
|
||||
action[ACTION_VERB_INDEX],
|
||||
action[ACTION_OBJECT_INDEX],
|
||||
action[ACTION_DESC_INDEX]);
|
||||
}
|
||||
|
||||
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]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -344,11 +436,11 @@ public class CommandLineProcessor {
|
||||
/**
|
||||
* Internal helper to print all the option flags for a given action name.
|
||||
*/
|
||||
protected void listOptions(String action) {
|
||||
protected void listOptions(String verb, String directObject) {
|
||||
int numOptions = 0;
|
||||
for (Entry<String, Arg> entry : mArguments.entrySet()) {
|
||||
Arg arg = entry.getValue();
|
||||
if (arg.getAction().equals(action)) {
|
||||
if (arg.getVerb().equals(verb) && arg.getDirectObject().equals(directObject)) {
|
||||
|
||||
String value = "";
|
||||
if (arg.getDefaultValue() instanceof String[]) {
|
||||
@@ -483,21 +575,22 @@ public class CommandLineProcessor {
|
||||
* 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 mVerb;
|
||||
private final String mDirectObject;
|
||||
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;
|
||||
private Object mCurrentValue;
|
||||
|
||||
/**
|
||||
* 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 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.
|
||||
@@ -505,14 +598,16 @@ public class CommandLineProcessor {
|
||||
*/
|
||||
public Arg(MODE mode,
|
||||
boolean mandatory,
|
||||
String action,
|
||||
String verb,
|
||||
String directObject,
|
||||
String shortName,
|
||||
String longName,
|
||||
String description,
|
||||
Object defaultValue) {
|
||||
mMode = mode;
|
||||
mMandatory = mandatory;
|
||||
mAction = action;
|
||||
mVerb = verb;
|
||||
mDirectObject = directObject;
|
||||
mShortName = shortName;
|
||||
mLongName = longName;
|
||||
mDescription = description;
|
||||
@@ -540,8 +635,12 @@ public class CommandLineProcessor {
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return mAction;
|
||||
public String getVerb() {
|
||||
return mVerb;
|
||||
}
|
||||
|
||||
public String getDirectObject() {
|
||||
return mDirectObject;
|
||||
}
|
||||
|
||||
public Object getDefaultValue() {
|
||||
@@ -565,7 +664,8 @@ public class CommandLineProcessor {
|
||||
* 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 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.
|
||||
@@ -573,14 +673,19 @@ public class CommandLineProcessor {
|
||||
*/
|
||||
protected void define(MODE mode,
|
||||
boolean mandatory,
|
||||
String action,
|
||||
String verb,
|
||||
String directObject,
|
||||
String shortName, String longName,
|
||||
String description, Object defaultValue) {
|
||||
assert(mandatory || mode == MODE.BOOLEAN); // a boolean mode cannot be mandatory
|
||||
|
||||
String key = action + "/" + longName;
|
||||
if (directObject == null) {
|
||||
directObject = NO_VERB_OBJECT;
|
||||
}
|
||||
|
||||
String key = verb + "/" + directObject + "/" + longName;
|
||||
mArguments.put(key, new Arg(mode, mandatory,
|
||||
action, shortName, longName, description, defaultValue));
|
||||
verb, directObject, shortName, longName, description, defaultValue));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,12 +23,12 @@ 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 com.android.sdklib.vm.HardwareProperties;
|
||||
import com.android.sdklib.vm.VmManager;
|
||||
import com.android.sdklib.vm.HardwareProperties.HardwareProperty;
|
||||
import com.android.sdklib.vm.VmManager.VmInfo;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -56,8 +56,8 @@ class Main {
|
||||
private ISdkLog mSdkLog;
|
||||
/** The SDK manager parses the SDK folder and gives access to the content. */
|
||||
private SdkManager mSdkManager;
|
||||
/** Virtual Machine manager to access the list of VMs or create new ones. */
|
||||
private VmManager mVmManager;
|
||||
/** Virtual Machine manager to access the list of AVDs or create new ones. */
|
||||
private AvdManager mAvdManager;
|
||||
/** Command-line processor with options specific to SdkManager. */
|
||||
private SdkCommandLine mSdkCommandLine;
|
||||
/** The working directory, either null or set to an existing absolute canonical directory. */
|
||||
@@ -183,26 +183,31 @@ class Main {
|
||||
* Actually do an action...
|
||||
*/
|
||||
private void doAction() {
|
||||
String action = mSdkCommandLine.getActionRequested();
|
||||
String verb = mSdkCommandLine.getVerb();
|
||||
String directObject = mSdkCommandLine.getDirectObject();
|
||||
|
||||
if (SdkCommandLine.ACTION_LIST.equals(action)) {
|
||||
if (SdkCommandLine.VERB_LIST.equals(verb)) {
|
||||
// list action.
|
||||
if (SdkCommandLine.ARG_TARGET.equals(mSdkCommandLine.getListFilter())) {
|
||||
if (SdkCommandLine.OBJECT_TARGET.equals(directObject)) {
|
||||
displayTargetList();
|
||||
} else if (SdkCommandLine.ARG_VM.equals(mSdkCommandLine.getListFilter())) {
|
||||
displayVmList();
|
||||
} else if (SdkCommandLine.OBJECT_AVD.equals(directObject)) {
|
||||
displayAvdList();
|
||||
} else {
|
||||
displayTargetList();
|
||||
displayVmList();
|
||||
displayAvdList();
|
||||
}
|
||||
} else if (SdkCommandLine.ACTION_NEW_VM.equals(action)) {
|
||||
createVm();
|
||||
} else if (SdkCommandLine.ACTION_NEW_PROJECT.equals(action)) {
|
||||
|
||||
} else if (SdkCommandLine.VERB_CREATE.equals(verb) &&
|
||||
SdkCommandLine.OBJECT_AVD.equals(directObject)) {
|
||||
createAvd();
|
||||
|
||||
} else if (SdkCommandLine.VERB_CREATE.equals(verb) &&
|
||||
SdkCommandLine.OBJECT_PROJECT.equals(directObject)) {
|
||||
// get the target and try to resolve it.
|
||||
int targetId = mSdkCommandLine.getNewProjectTargetId();
|
||||
int targetId = mSdkCommandLine.getCreateProjectTargetId();
|
||||
IAndroidTarget[] targets = mSdkManager.getTargets();
|
||||
if (targetId < 1 || targetId > targets.length) {
|
||||
errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.",
|
||||
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
|
||||
SdkConstants.androidCmdName());
|
||||
}
|
||||
IAndroidTarget target = targets[targetId - 1];
|
||||
@@ -213,22 +218,24 @@ class Main {
|
||||
OutputLevel.NORMAL,
|
||||
mSdkLog);
|
||||
|
||||
String projectDir = getProjectLocation(mSdkCommandLine.getNewProjectLocation());
|
||||
String projectDir = getProjectLocation(mSdkCommandLine.getCreateProjectLocation());
|
||||
|
||||
creator.createProject(projectDir,
|
||||
mSdkCommandLine.getNewProjectName(),
|
||||
mSdkCommandLine.getNewProjectPackage(),
|
||||
mSdkCommandLine.getNewProjectActivity(),
|
||||
mSdkCommandLine.getCreateProjectName(),
|
||||
mSdkCommandLine.getCreateProjectPackage(),
|
||||
mSdkCommandLine.getCreateProjectActivity(),
|
||||
target,
|
||||
false /* isTestProject*/);
|
||||
} else if (SdkCommandLine.ACTION_UPDATE_PROJECT.equals(action)) {
|
||||
|
||||
} else if (SdkCommandLine.VERB_UPDATE.equals(verb) &&
|
||||
SdkCommandLine.OBJECT_PROJECT.equals(directObject)) {
|
||||
// get the target and try to resolve it.
|
||||
IAndroidTarget target = null;
|
||||
int targetId = mSdkCommandLine.getUpdateProjectTargetId();
|
||||
if (targetId >= 0) {
|
||||
IAndroidTarget[] targets = mSdkManager.getTargets();
|
||||
if (targetId < 1 || targetId > targets.length) {
|
||||
errorAndExit("Target id is not valid. Use '%s list -f target' to get the target Ids.",
|
||||
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
|
||||
SdkConstants.androidCmdName());
|
||||
}
|
||||
target = targets[targetId - 1];
|
||||
@@ -340,20 +347,20 @@ class Main {
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the list of available VMs.
|
||||
* Displays the list of available AVDs.
|
||||
*/
|
||||
private void displayVmList() {
|
||||
private void displayAvdList() {
|
||||
try {
|
||||
mVmManager = new VmManager(mSdkManager, null /* sdklog */);
|
||||
mAvdManager = new AvdManager(mSdkManager, null /* sdklog */);
|
||||
|
||||
mSdkLog.printf("Available Android VMs:\n");
|
||||
mSdkLog.printf("Available Android Virtual Devices:\n");
|
||||
|
||||
int index = 1;
|
||||
for (VmInfo info : mVmManager.getVms()) {
|
||||
for (AvdInfo info : mAvdManager.getAvds()) {
|
||||
mSdkLog.printf("[%d] %s\n", index, info.getName());
|
||||
mSdkLog.printf(" Path: %s\n", info.getPath());
|
||||
|
||||
// get the target of the Vm
|
||||
// get the target of the AVD
|
||||
IAndroidTarget target = info.getTarget();
|
||||
if (target.isPlatform()) {
|
||||
mSdkLog.printf(" Target: %s (API level %d)\n", target.getName(),
|
||||
@@ -373,57 +380,85 @@ class Main {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new VM. This is a text based creation with command line prompt.
|
||||
* Creates a new AVD. This is a text based creation with command line prompt.
|
||||
*/
|
||||
private void createVm() {
|
||||
private void createAvd() {
|
||||
// find a matching target
|
||||
int targetId = mSdkCommandLine.getNewVmTargetId();
|
||||
int targetId = mSdkCommandLine.getCreateAvdTargetId();
|
||||
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 -f target' to get the target Ids.",
|
||||
errorAndExit("Target id is not valid. Use '%s list targets' to get the target ids.",
|
||||
SdkConstants.androidCmdName());
|
||||
}
|
||||
|
||||
try {
|
||||
mVmManager = new VmManager(mSdkManager, mSdkLog);
|
||||
boolean removePrevious = false;
|
||||
mAvdManager = new AvdManager(mSdkManager, mSdkLog);
|
||||
|
||||
String vmName = mSdkCommandLine.getNewVmName();
|
||||
VmInfo info = mVmManager.getVm(vmName);
|
||||
String avdName = mSdkCommandLine.getCreateAvdName();
|
||||
AvdInfo info = mAvdManager.getAvd(avdName);
|
||||
if (info != null) {
|
||||
errorAndExit("VM %s already exists.", vmName);
|
||||
} else {
|
||||
String vmParentFolder = mSdkCommandLine.getNewVmLocation();
|
||||
if (vmParentFolder == null) {
|
||||
vmParentFolder = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
|
||||
if (mSdkCommandLine.getCreateAvdForce()) {
|
||||
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;
|
||||
}
|
||||
|
||||
Map<String, String> hardwareConfig = null;
|
||||
if (target.isPlatform()) {
|
||||
try {
|
||||
hardwareConfig = promptForHardware(target);
|
||||
} catch (IOException e) {
|
||||
errorAndExit(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
mVmManager.createVm(vmParentFolder,
|
||||
mSdkCommandLine.getNewVmName(),
|
||||
target,
|
||||
mSdkCommandLine.getNewVmSkin(),
|
||||
mSdkCommandLine.getNewVmSdCard(),
|
||||
hardwareConfig,
|
||||
mSdkLog);
|
||||
}
|
||||
|
||||
String avdParentFolder = mSdkCommandLine.getCreateAvdLocation();
|
||||
if (avdParentFolder == null) {
|
||||
avdParentFolder = AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD;
|
||||
}
|
||||
|
||||
Map<String, String> hardwareConfig = null;
|
||||
if (target.isPlatform()) {
|
||||
try {
|
||||
hardwareConfig = promptForHardware(target);
|
||||
} catch (IOException e) {
|
||||
errorAndExit(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
AvdInfo oldAvdInfo = null;
|
||||
if (removePrevious) {
|
||||
oldAvdInfo = mAvdManager.getAvd(avdName);
|
||||
}
|
||||
|
||||
AvdInfo newAvdInfo = mAvdManager.createAvd(avdParentFolder,
|
||||
avdName,
|
||||
target,
|
||||
mSdkCommandLine.getCreateAvdSkin(),
|
||||
mSdkCommandLine.getCreateAvdSdCard(),
|
||||
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());
|
||||
mAvdManager.recursiveDelete(dir);
|
||||
dir.delete();
|
||||
// Remove old avd info from manager
|
||||
mAvdManager.removeAvd(oldAvdInfo);
|
||||
}
|
||||
|
||||
} catch (AndroidLocationException e) {
|
||||
errorAndExit(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to setup a hardware config for a Platform-based VM.
|
||||
* Prompts the user to setup a hardware config for a Platform-based AVD.
|
||||
* @throws IOException
|
||||
*/
|
||||
private Map<String, String> promptForHardware(IAndroidTarget createTarget) throws IOException {
|
||||
|
||||
@@ -25,152 +25,218 @@ import com.android.sdklib.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_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 static final String KEY_SKIN = "skin";
|
||||
public static final String KEY_SDCARD = "sdcard";
|
||||
public final static String VERB_LIST = "list";
|
||||
public final static String VERB_CREATE = "create";
|
||||
public final static String VERB_RENAME = "rename";
|
||||
public final static String VERB_MOVE = "move";
|
||||
public final static String VERB_DELETE = "delete";
|
||||
public final static String VERB_UPDATE = "update";
|
||||
|
||||
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";
|
||||
|
||||
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";
|
||||
|
||||
/**
|
||||
* 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 = {
|
||||
{ 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 project from existing source (must have an AndroidManifest.xml)." },
|
||||
{ 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_RENAME,
|
||||
OBJECT_AVD,
|
||||
"Renames a new Android Virtual Device." },
|
||||
{ VERB_MOVE,
|
||||
OBJECT_AVD,
|
||||
"Moves a new Android Virtual Device." },
|
||||
{ VERB_DELETE,
|
||||
OBJECT_AVD,
|
||||
"Deletes a new 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);
|
||||
|
||||
define(MODE.ENUM, false, ACTION_LIST, "f", KEY_FILTER,
|
||||
"List filter", new String[] { ARG_ALL, ARG_TARGET, ARG_VM });
|
||||
define(MODE.STRING, false,
|
||||
VERB_CREATE, OBJECT_AVD,
|
||||
"p", KEY_PATH,
|
||||
"Location path of the parent 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, true,
|
||||
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);
|
||||
|
||||
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.STRING, true, ACTION_NEW_VM, "s", KEY_SKIN,
|
||||
"Skin of the new VM", null);
|
||||
define(MODE.STRING, false, ACTION_NEW_VM, "c", KEY_SDCARD,
|
||||
"Path to a shared SD card image, or size of a new sdcard for the new VM", null);
|
||||
|
||||
define(MODE.ENUM, true, ACTION_NEW_PROJECT, "m", KEY_MODE,
|
||||
define(MODE.ENUM, true,
|
||||
VERB_CREATE, OBJECT_PROJECT,
|
||||
"m", KEY_MODE,
|
||||
"Project mode", new String[] { ARG_ACTIVITY, ARG_ALIAS });
|
||||
define(MODE.STRING, true, ACTION_NEW_PROJECT, "o", KEY_OUT,
|
||||
define(MODE.STRING, true,
|
||||
VERB_CREATE, OBJECT_PROJECT,
|
||||
"p", KEY_PATH,
|
||||
"Location path of new project", null);
|
||||
define(MODE.INTEGER, true, ACTION_NEW_PROJECT, "t", KEY_TARGET_ID,
|
||||
define(MODE.INTEGER, true,
|
||||
VERB_CREATE, OBJECT_PROJECT,
|
||||
"t", KEY_TARGET_ID,
|
||||
"Target id of the new project", null);
|
||||
define(MODE.STRING, true, ACTION_NEW_PROJECT, "p", KEY_PACKAGE,
|
||||
define(MODE.STRING, true,
|
||||
VERB_CREATE, OBJECT_PROJECT,
|
||||
"k", KEY_PACKAGE,
|
||||
"Package name", null);
|
||||
define(MODE.STRING, true, ACTION_NEW_PROJECT, "a", KEY_ACTIVITY,
|
||||
define(MODE.STRING, true,
|
||||
VERB_CREATE, OBJECT_PROJECT,
|
||||
"a", KEY_ACTIVITY,
|
||||
"Activity name", null);
|
||||
define(MODE.STRING, false, ACTION_NEW_PROJECT, "n", KEY_NAME,
|
||||
define(MODE.STRING, false,
|
||||
VERB_CREATE, OBJECT_PROJECT,
|
||||
"n", KEY_NAME,
|
||||
"Project name", null);
|
||||
|
||||
define(MODE.STRING, true, ACTION_UPDATE_PROJECT, "o", KEY_OUT,
|
||||
define(MODE.STRING, true,
|
||||
VERB_UPDATE, OBJECT_PROJECT,
|
||||
"p", KEY_PATH,
|
||||
"Location path of the project", null);
|
||||
define(MODE.INTEGER, true, ACTION_UPDATE_PROJECT, "t", KEY_TARGET_ID,
|
||||
define(MODE.INTEGER, true,
|
||||
VERB_UPDATE, OBJECT_PROJECT,
|
||||
"t", KEY_TARGET_ID,
|
||||
"Target id to set for the project", -1);
|
||||
define(MODE.STRING, false, ACTION_UPDATE_PROJECT, "n", KEY_NAME,
|
||||
define(MODE.STRING, false,
|
||||
VERB_UPDATE, OBJECT_PROJECT,
|
||||
"n", KEY_NAME,
|
||||
"Project name", null);
|
||||
}
|
||||
|
||||
// -- some helpers for list action flags
|
||||
// -- some helpers for AVD action flags
|
||||
|
||||
/** Helper to retrieve the --filter for the list action. */
|
||||
public String getListFilter() {
|
||||
return ((String) getValue(ACTION_LIST, KEY_FILTER));
|
||||
/** Helper to retrieve the --out location for the new AVD action. */
|
||||
public String getCreateAvdLocation() {
|
||||
return ((String) getValue(VERB_CREATE, OBJECT_AVD, KEY_PATH));
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --target id for the new AVD action. */
|
||||
public int getCreateAvdTargetId() {
|
||||
return ((Integer) getValue(VERB_CREATE, OBJECT_AVD, KEY_TARGET_ID)).intValue();
|
||||
}
|
||||
|
||||
// -- 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 --name for the new AVD action. */
|
||||
public String getCreateAvdName() {
|
||||
return ((String) getValue(VERB_CREATE, OBJECT_AVD, KEY_NAME));
|
||||
}
|
||||
|
||||
/** 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 --skin name for the new AVD action. */
|
||||
public String getCreateAvdSkin() {
|
||||
return ((String) getValue(VERB_CREATE, OBJECT_AVD, KEY_SKIN));
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --name for the new vm action. */
|
||||
public String getNewVmName() {
|
||||
return ((String) getValue(ACTION_NEW_VM, KEY_NAME));
|
||||
/** Helper to retrieve the --sdcard data for the new AVD action. */
|
||||
public String getCreateAvdSdCard() {
|
||||
return ((String) getValue(VERB_CREATE, OBJECT_AVD, KEY_SDCARD));
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --skin name for the new vm action. */
|
||||
public String getNewVmSkin() {
|
||||
return ((String) getValue(ACTION_NEW_VM, KEY_SKIN));
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --sdcard data for the new vm action. */
|
||||
public String getNewVmSdCard() {
|
||||
return ((String) getValue(ACTION_NEW_VM, KEY_SDCARD));
|
||||
public boolean getCreateAvdForce() {
|
||||
return ((Boolean) getValue(VERB_CREATE, OBJECT_AVD, KEY_FORCE)).booleanValue();
|
||||
}
|
||||
|
||||
|
||||
// -- 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));
|
||||
public String getCreateProjectLocation() {
|
||||
return ((String) getValue(VERB_CREATE, OBJECT_PROJECT, KEY_PATH));
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --target id for the new project action. */
|
||||
public int getNewProjectTargetId() {
|
||||
return ((Integer) getValue(ACTION_NEW_PROJECT, KEY_TARGET_ID)).intValue();
|
||||
public int getCreateProjectTargetId() {
|
||||
return ((Integer) getValue(VERB_CREATE, OBJECT_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));
|
||||
public String getCreateProjectName() {
|
||||
return ((String) getValue(VERB_CREATE, OBJECT_PROJECT, KEY_NAME));
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --package for the new project action. */
|
||||
public String getNewProjectPackage() {
|
||||
return ((String) getValue(ACTION_NEW_PROJECT, KEY_PACKAGE));
|
||||
public String getCreateProjectPackage() {
|
||||
return ((String) getValue(VERB_CREATE, OBJECT_PROJECT, KEY_PACKAGE));
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --activity for the new project action. */
|
||||
public String getNewProjectActivity() {
|
||||
return ((String) getValue(ACTION_NEW_PROJECT, KEY_ACTIVITY));
|
||||
public String getCreateProjectActivity() {
|
||||
return ((String) getValue(VERB_CREATE, OBJECT_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));
|
||||
return ((String) getValue(VERB_UPDATE, OBJECT_PROJECT, KEY_PATH));
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --target id for the update project action. */
|
||||
public int getUpdateProjectTargetId() {
|
||||
return ((Integer) getValue(ACTION_UPDATE_PROJECT, KEY_TARGET_ID)).intValue();
|
||||
return ((Integer) getValue(VERB_UPDATE, OBJECT_PROJECT, KEY_TARGET_ID)).intValue();
|
||||
}
|
||||
|
||||
/** Helper to retrieve the --name for the update project action. */
|
||||
public String getUpdateProjectName() {
|
||||
return ((String) getValue(ACTION_UPDATE_PROJECT, KEY_NAME));
|
||||
return ((String) getValue(VERB_UPDATE, OBJECT_PROJECT, KEY_NAME));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,20 +38,20 @@ public class CommandLineProcessorTest extends TestCase {
|
||||
public MockCommandLineProcessor(ISdkLog logger) {
|
||||
super(logger,
|
||||
new String[][] {
|
||||
{ "action1", "Some action" },
|
||||
{ "action2", "Another action" },
|
||||
{ "verb1", "action1", "Some action" },
|
||||
{ "verb1", "action2", "Another action" },
|
||||
});
|
||||
define(MODE.STRING, false /*mandatory*/,
|
||||
"action1", "1", "first", "non-mandatory flag", null);
|
||||
"verb1", "action1", "1", "first", "non-mandatory flag", null);
|
||||
define(MODE.STRING, true /*mandatory*/,
|
||||
"action1", "2", "second", "mandatory flag", null);
|
||||
"verb1", "action1", "2", "second", "mandatory flag", null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printHelpAndExitForAction(String actionFilter,
|
||||
public void printHelpAndExitForAction(String verb, String directObject,
|
||||
String errorFormat, Object... args) {
|
||||
mHelpCalled = true;
|
||||
super.printHelpAndExitForAction(actionFilter, errorFormat, args);
|
||||
super.printHelpAndExitForAction(verb, directObject, errorFormat, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -132,14 +132,14 @@ public class CommandLineProcessorTest extends TestCase {
|
||||
assertTrue(c.isVerbose());
|
||||
assertTrue(c.wasExitCalled());
|
||||
assertTrue(c.wasHelpCalled());
|
||||
assertTrue(c.getStdErr().indexOf("Missing action name.") != -1);
|
||||
assertTrue(c.getStdErr().indexOf("Missing verb name.") != -1);
|
||||
|
||||
c = new MockCommandLineProcessor(mLog);
|
||||
c.parseArgs(new String[] { "--verbose" });
|
||||
assertTrue(c.isVerbose());
|
||||
assertTrue(c.wasExitCalled());
|
||||
assertTrue(c.wasHelpCalled());
|
||||
assertTrue(c.getStdErr().indexOf("Missing action name.") != -1);
|
||||
assertTrue(c.getStdErr().indexOf("Missing verb name.") != -1);
|
||||
}
|
||||
|
||||
public final void testHelp() {
|
||||
@@ -148,39 +148,39 @@ public class CommandLineProcessorTest extends TestCase {
|
||||
c.parseArgs(new String[] { "-h" });
|
||||
assertTrue(c.wasExitCalled());
|
||||
assertTrue(c.wasHelpCalled());
|
||||
assertTrue(c.getStdErr().indexOf("Missing action name.") == -1);
|
||||
assertTrue(c.getStdErr().indexOf("Missing verb name.") == -1);
|
||||
|
||||
c = new MockCommandLineProcessor(mLog);
|
||||
c.parseArgs(new String[] { "--help" });
|
||||
assertTrue(c.wasExitCalled());
|
||||
assertTrue(c.wasHelpCalled());
|
||||
assertTrue(c.getStdErr().indexOf("Missing action name.") == -1);
|
||||
assertTrue(c.getStdErr().indexOf("Missing verb name.") == -1);
|
||||
}
|
||||
|
||||
public final void testMandatory() {
|
||||
MockCommandLineProcessor c = new MockCommandLineProcessor(mLog);
|
||||
|
||||
c.parseArgs(new String[] { "action1", "-1", "value1", "-2", "value2" });
|
||||
c.parseArgs(new String[] { "verb1", "action1", "-1", "value1", "-2", "value2" });
|
||||
assertFalse(c.wasExitCalled());
|
||||
assertFalse(c.wasHelpCalled());
|
||||
assertEquals("", c.getStdErr());
|
||||
assertEquals("value1", c.getValue("action1", "first"));
|
||||
assertEquals("value2", c.getValue("action1", "second"));
|
||||
assertEquals("value1", c.getValue("verb1", "action1", "first"));
|
||||
assertEquals("value2", c.getValue("verb1", "action1", "second"));
|
||||
|
||||
c = new MockCommandLineProcessor(mLog);
|
||||
c.parseArgs(new String[] { "action1", "-2", "value2" });
|
||||
c.parseArgs(new String[] { "verb1", "action1", "-2", "value2" });
|
||||
assertFalse(c.wasExitCalled());
|
||||
assertFalse(c.wasHelpCalled());
|
||||
assertEquals("", c.getStdErr());
|
||||
assertEquals(null, c.getValue("action1", "first"));
|
||||
assertEquals("value2", c.getValue("action1", "second"));
|
||||
assertEquals(null, c.getValue("verb1", "action1", "first"));
|
||||
assertEquals("value2", c.getValue("verb1", "action1", "second"));
|
||||
|
||||
c = new MockCommandLineProcessor(mLog);
|
||||
c.parseArgs(new String[] { "action1" });
|
||||
c.parseArgs(new String[] { "verb1", "action1" });
|
||||
assertTrue(c.wasExitCalled());
|
||||
assertTrue(c.wasHelpCalled());
|
||||
assertTrue(c.getStdErr().indexOf("must be defined") != -1);
|
||||
assertEquals(null, c.getValue("action1", "first"));
|
||||
assertEquals(null, c.getValue("action1", "second"));
|
||||
assertEquals(null, c.getValue("verb1", "action1", "first"));
|
||||
assertEquals(null, c.getValue("verb1", "action1", "second"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,10 +37,10 @@ public class SdkCommandLineTest extends TestCase {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printHelpAndExitForAction(String actionFilter,
|
||||
public void printHelpAndExitForAction(String verb, String directObject,
|
||||
String errorFormat, Object... args) {
|
||||
mHelpCalled = true;
|
||||
super.printHelpAndExitForAction(actionFilter, errorFormat, args);
|
||||
super.printHelpAndExitForAction(verb, directObject, errorFormat, args);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -78,34 +78,64 @@ public class SdkCommandLineTest extends TestCase {
|
||||
super.tearDown();
|
||||
}
|
||||
|
||||
/** Test list with long name and verbose */
|
||||
public final void testList_Long_Verbose() {
|
||||
/** Test list */
|
||||
public final void testList_Avd_Verbose() {
|
||||
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
|
||||
assertEquals("all", c.getListFilter());
|
||||
c.parseArgs(new String[] { "-v", "list", "--filter", "vm" });
|
||||
c.parseArgs(new String[] { "-v", "list", "avd" });
|
||||
assertFalse(c.wasHelpCalled());
|
||||
assertFalse(c.wasExitCalled());
|
||||
assertEquals("vm", c.getListFilter());
|
||||
assertEquals("list", c.getVerb());
|
||||
assertEquals("avd", c.getDirectObject());
|
||||
assertTrue(c.isVerbose());
|
||||
}
|
||||
|
||||
/** Test list with short name and no verbose */
|
||||
public final void testList_Short() {
|
||||
public final void testList_Target() {
|
||||
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
|
||||
assertEquals("all", c.getListFilter());
|
||||
c.parseArgs(new String[] { "list", "-f", "vm" });
|
||||
c.parseArgs(new String[] { "list", "target" });
|
||||
assertFalse(c.wasHelpCalled());
|
||||
assertFalse(c.wasExitCalled());
|
||||
assertEquals("vm", c.getListFilter());
|
||||
assertEquals("list", c.getVerb());
|
||||
assertEquals("target", c.getDirectObject());
|
||||
assertFalse(c.isVerbose());
|
||||
}
|
||||
|
||||
/** Test list with long name and missing parameter */
|
||||
public final void testList_Long_MissingParam() {
|
||||
|
||||
public final void testList_None() {
|
||||
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
|
||||
assertEquals("all", c.getListFilter());
|
||||
c.parseArgs(new String[] { "list", "--filter" });
|
||||
c.parseArgs(new String[] { "list" });
|
||||
assertFalse(c.wasHelpCalled());
|
||||
assertFalse(c.wasExitCalled());
|
||||
assertEquals("list", c.getVerb());
|
||||
assertEquals("", c.getDirectObject());
|
||||
assertFalse(c.isVerbose());
|
||||
}
|
||||
|
||||
public final void testList_Invalid() {
|
||||
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
|
||||
c.parseArgs(new String[] { "list", "unknown" });
|
||||
assertTrue(c.wasHelpCalled());
|
||||
assertTrue(c.wasExitCalled());
|
||||
assertEquals("all", c.getListFilter());
|
||||
assertEquals(null, c.getVerb());
|
||||
assertEquals(null, c.getDirectObject());
|
||||
assertFalse(c.isVerbose());
|
||||
}
|
||||
|
||||
public final void testList_Plural() {
|
||||
MockSdkCommandLine c = new MockSdkCommandLine(mLog);
|
||||
c.parseArgs(new String[] { "list", "avds" });
|
||||
assertFalse(c.wasHelpCalled());
|
||||
assertFalse(c.wasExitCalled());
|
||||
assertEquals("list", c.getVerb());
|
||||
// we get the non-plural form
|
||||
assertEquals("avd", c.getDirectObject());
|
||||
assertFalse(c.isVerbose());
|
||||
|
||||
c = new MockSdkCommandLine(mLog);
|
||||
c.parseArgs(new String[] { "list", "targets" });
|
||||
assertFalse(c.wasHelpCalled());
|
||||
assertFalse(c.wasExitCalled());
|
||||
assertEquals("list", c.getVerb());
|
||||
// we get the non-plural form
|
||||
assertEquals("target", c.getDirectObject());
|
||||
assertFalse(c.isVerbose());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,48 @@
|
||||
|
||||
package com.android.sdklib;
|
||||
|
||||
import java.util.Formatter;
|
||||
|
||||
/**
|
||||
* Interface used to display warnings/errors while parsing the SDK content.
|
||||
*/
|
||||
public interface ISdkLog {
|
||||
|
||||
/**
|
||||
* Prints a warning message on stdout.
|
||||
* <p/>
|
||||
* Implementations should only display warnings in verbose mode.
|
||||
* The message should be prefixed with "Warning:".
|
||||
*
|
||||
* @param warningFormat is an optional error format. If non-null, it will be printed
|
||||
* using a {@link Formatter} with the provided arguments.
|
||||
* @param args provides the arguments for warningFormat.
|
||||
*/
|
||||
void warning(String warningFormat, Object... args);
|
||||
|
||||
/**
|
||||
* Prints an error message on stderr.
|
||||
* <p/>
|
||||
* Implementation should always display errors, independent of verbose mode.
|
||||
* The message should be prefixed with "Error:".
|
||||
*
|
||||
* @param t is an optional {@link Throwable} or {@link Exception}. If non-null, it's
|
||||
* message will be printed out.
|
||||
* @param errorFormat is an optional error format. If non-null, it will be printed
|
||||
* using a {@link Formatter} with the provided arguments.
|
||||
* @param args provides the arguments for errorFormat.
|
||||
*/
|
||||
void error(Throwable t, String errorFormat, Object... args);
|
||||
|
||||
/**
|
||||
* Prints a message as-is on stdout.
|
||||
* <p/>
|
||||
* Implementation should always display errors, independent of verbose mode.
|
||||
* No prefix is used, the message is printed as-is after formatting.
|
||||
*
|
||||
* @param msgFormat is an optional error format. If non-null, it will be printed
|
||||
* using a {@link Formatter} with the provided arguments.
|
||||
* @param args provides the arguments for msgFormat.
|
||||
*/
|
||||
void printf(String msgFormat, Object... args);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.sdklib.vm;
|
||||
package com.android.sdklib.avd;
|
||||
|
||||
import com.android.prefs.AndroidLocation;
|
||||
import com.android.prefs.AndroidLocation.AndroidLocationException;
|
||||
@@ -39,12 +39,13 @@ import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Virtual Machine manager to access the list of VMs or create new ones.
|
||||
* Virtual Device Manager to access the list of AVDs or create new ones.
|
||||
*/
|
||||
public final class VmManager {
|
||||
public final class AvdManager {
|
||||
|
||||
private final static String VM_INFO_PATH = "path";
|
||||
private final static String VM_INFO_TARGET = "target";
|
||||
private static final String AVD_FOLDER_EXTENSION = ".avd";
|
||||
private final static String AVD_INFO_PATH = "path";
|
||||
private final static String AVD_INFO_TARGET = "target";
|
||||
|
||||
private final static String IMAGE_USERDATA = "userdata.img";
|
||||
private final static String CONFIG_INI = "config.ini";
|
||||
@@ -54,7 +55,7 @@ public final class VmManager {
|
||||
|
||||
private final static Pattern SDCARD_SIZE_PATTERN = Pattern.compile("\\d+[MK]?");
|
||||
|
||||
public static final class VmInfo {
|
||||
public static final class AvdInfo {
|
||||
String name;
|
||||
String path;
|
||||
IAndroidTarget target;
|
||||
@@ -72,30 +73,30 @@ public final class VmManager {
|
||||
}
|
||||
}
|
||||
|
||||
private final ArrayList<VmInfo> mVmList = new ArrayList<VmInfo>();
|
||||
private final ArrayList<AvdInfo> mAvdList = new ArrayList<AvdInfo>();
|
||||
private ISdkLog mSdkLog;
|
||||
private final SdkManager mSdk;
|
||||
|
||||
public VmManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException {
|
||||
public AvdManager(SdkManager sdk, ISdkLog sdkLog) throws AndroidLocationException {
|
||||
mSdk = sdk;
|
||||
mSdkLog = sdkLog;
|
||||
buildVmList();
|
||||
buildAvdList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the existing VMs.
|
||||
* @return a newly allocated arrays containing all the VMs.
|
||||
* Returns the existing AVDs.
|
||||
* @return a newly allocated array containing all the AVDs.
|
||||
*/
|
||||
public VmInfo[] getVms() {
|
||||
return mVmList.toArray(new VmInfo[mVmList.size()]);
|
||||
public AvdInfo[] getAvds() {
|
||||
return mAvdList.toArray(new AvdInfo[mAvdList.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link VmInfo} matching the given <var>name</var>.
|
||||
* @return the matching VmInfo or <code>null</code> if none were found.
|
||||
* Returns the {@link AvdInfo} matching the given <var>name</var>.
|
||||
* @return the matching AvdInfo or <code>null</code> if none were found.
|
||||
*/
|
||||
public VmInfo getVm(String name) {
|
||||
for (VmInfo info : mVmList) {
|
||||
public AvdInfo getAvd(String name) {
|
||||
for (AvdInfo info : mAvdList) {
|
||||
if (info.name.equals(name)) {
|
||||
return info;
|
||||
}
|
||||
@@ -105,19 +106,20 @@ public final class VmManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new VM. It is expected that there is no existing VM with this name already.
|
||||
* @param parentFolder the folder to contain the VM. A new folder will be created in this
|
||||
* folder with the name of the VM
|
||||
* @param name the name of the VM
|
||||
* @param target the target of the VM
|
||||
* Creates a new AVD. It is expected that there is no existing AVD with this name already.
|
||||
* @param parentFolder the folder to contain the AVD. A new folder will be created in this
|
||||
* folder with the name of the AVD
|
||||
* @param name the name of the AVD
|
||||
* @param target the target of the AVD
|
||||
* @param skinName the name of the skin. Can be null.
|
||||
* @param sdcard the parameter value for the sdCard. Can be null. This is either a path to
|
||||
* an existing sdcard image or a sdcard size (\d+, \d+K, \dM).
|
||||
* @param hardwareConfig the hardware setup for the VM
|
||||
* @param hardwareConfig the hardware setup for the AVD
|
||||
* @param removePrevious If true remove any previous files.
|
||||
*/
|
||||
public VmInfo createVm(String parentFolder, String name, IAndroidTarget target,
|
||||
public AvdInfo createAvd(String parentFolder, String name, IAndroidTarget target,
|
||||
String skinName, String sdcard, Map<String,String> hardwareConfig,
|
||||
ISdkLog log) {
|
||||
boolean removePrevious, ISdkLog log) {
|
||||
|
||||
try {
|
||||
File rootDirectory = new File(parentFolder);
|
||||
@@ -128,24 +130,31 @@ public final class VmManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
File vmFolder = new File(parentFolder, name + ".avm");
|
||||
if (vmFolder.exists()) {
|
||||
if (log != null) {
|
||||
log.error(null, "Folder %s is in the way.", vmFolder.getAbsolutePath());
|
||||
File avdFolder = new File(parentFolder, name + AVD_FOLDER_EXTENSION);
|
||||
if (avdFolder.exists()) {
|
||||
if (removePrevious) {
|
||||
// AVD already exists and removePrevious is set, try to remove the
|
||||
// directory's content first (but not the directory itself).
|
||||
recursiveDelete(avdFolder);
|
||||
} else {
|
||||
// AVD shouldn't already exist if removePrevious is false.
|
||||
if (log != null) {
|
||||
log.error(null, "Folder %s is in the way.", avdFolder.getAbsolutePath());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// create the vm folder.
|
||||
vmFolder.mkdir();
|
||||
// create the AVD folder.
|
||||
avdFolder.mkdir();
|
||||
|
||||
HashMap<String, String> values = new HashMap<String, String>();
|
||||
|
||||
// prepare the ini file.
|
||||
String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
|
||||
File iniFile = new File(vmRoot, name + ".ini");
|
||||
values.put(VM_INFO_PATH, vmFolder.getAbsolutePath());
|
||||
values.put(VM_INFO_TARGET, target.hashString());
|
||||
String avdRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD;
|
||||
File iniFile = new File(avdRoot, name + ".ini");
|
||||
values.put(AVD_INFO_PATH, avdFolder.getAbsolutePath());
|
||||
values.put(AVD_INFO_TARGET, target.hashString());
|
||||
createConfigIni(iniFile, values);
|
||||
|
||||
// writes the userdata.img in it.
|
||||
@@ -153,7 +162,7 @@ public final class VmManager {
|
||||
File userdataSrc = new File(imagePath, IMAGE_USERDATA);
|
||||
FileInputStream fis = new FileInputStream(userdataSrc);
|
||||
|
||||
File userdataDest = new File(vmFolder, IMAGE_USERDATA);
|
||||
File userdataDest = new File(avdFolder, IMAGE_USERDATA);
|
||||
FileOutputStream fos = new FileOutputStream(userdataDest);
|
||||
|
||||
byte[] buffer = new byte[4096];
|
||||
@@ -193,7 +202,7 @@ public final class VmManager {
|
||||
Matcher m = SDCARD_SIZE_PATTERN.matcher(sdcard);
|
||||
if (m.matches()) {
|
||||
// create the sdcard.
|
||||
sdcardFile = new File(vmFolder, "sdcard.img");
|
||||
sdcardFile = new File(avdFolder, "sdcard.img");
|
||||
String path = sdcardFile.getAbsolutePath();
|
||||
|
||||
// execute mksdcard with the proper parameters.
|
||||
@@ -224,28 +233,27 @@ public final class VmManager {
|
||||
values.putAll(hardwareConfig);
|
||||
}
|
||||
|
||||
File configIniFile = new File(vmFolder, CONFIG_INI);
|
||||
File configIniFile = new File(avdFolder, CONFIG_INI);
|
||||
createConfigIni(configIniFile, values);
|
||||
|
||||
if (log != null) {
|
||||
if (target.isPlatform()) {
|
||||
log.printf("Created VM '%s' based on %s\n", name, target.getName());
|
||||
log.printf("Created AVD '%s' based on %s\n", name, target.getName());
|
||||
} else {
|
||||
log.printf(
|
||||
"Created VM '%s' based on %s (%s)\n", name, target.getName(),
|
||||
target.getVendor());
|
||||
log.printf("Created AVD '%s' based on %s (%s)\n", name, target.getName(),
|
||||
target.getVendor());
|
||||
}
|
||||
}
|
||||
|
||||
// create the VmInfo object, and add it to the list
|
||||
VmInfo vmInfo = new VmInfo();
|
||||
vmInfo.name = name;
|
||||
vmInfo.path = vmFolder.getAbsolutePath();
|
||||
vmInfo.target = target;
|
||||
// create the AvdInfo object, and add it to the list
|
||||
AvdInfo avdInfo = new AvdInfo();
|
||||
avdInfo.name = name;
|
||||
avdInfo.path = avdFolder.getAbsolutePath();
|
||||
avdInfo.target = target;
|
||||
|
||||
mVmList.add(vmInfo);
|
||||
mAvdList.add(avdInfo);
|
||||
|
||||
return vmInfo;
|
||||
return avdInfo;
|
||||
} catch (AndroidLocationException e) {
|
||||
if (log != null) {
|
||||
log.error(e, null);
|
||||
@@ -259,21 +267,35 @@ public final class VmManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
private void buildVmList() throws AndroidLocationException {
|
||||
/**
|
||||
* Helper method to recursively delete a folder's content (but not the folder itself).
|
||||
*
|
||||
* @throws SecurityException like {@link File#delete()} does if file/folder is not writable.
|
||||
*/
|
||||
public void recursiveDelete(File folder) {
|
||||
for (File f : folder.listFiles()) {
|
||||
if (f.isDirectory()) {
|
||||
recursiveDelete(folder);
|
||||
}
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
|
||||
private void buildAvdList() throws AndroidLocationException {
|
||||
// get the Android prefs location.
|
||||
String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
|
||||
String avdRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_AVD;
|
||||
|
||||
// ensure folder validity.
|
||||
File folder = new File(vmRoot);
|
||||
File folder = new File(avdRoot);
|
||||
if (folder.isFile()) {
|
||||
throw new AndroidLocationException(String.format("%s is not a valid folder.", vmRoot));
|
||||
throw new AndroidLocationException(String.format("%s is not a valid folder.", avdRoot));
|
||||
} else if (folder.exists() == false) {
|
||||
// folder is not there, we create it and return
|
||||
folder.mkdirs();
|
||||
return;
|
||||
}
|
||||
|
||||
File[] vms = folder.listFiles(new FilenameFilter() {
|
||||
File[] avds = folder.listFiles(new FilenameFilter() {
|
||||
public boolean accept(File parent, String name) {
|
||||
if (INI_NAME_PATTERN.matcher(name).matches()) {
|
||||
// check it's a file and not a folder
|
||||
@@ -284,23 +306,23 @@ public final class VmManager {
|
||||
}
|
||||
});
|
||||
|
||||
for (File vm : vms) {
|
||||
VmInfo info = parseVmInfo(vm);
|
||||
for (File avd : avds) {
|
||||
AvdInfo info = parseAvdInfo(avd);
|
||||
if (info != null) {
|
||||
mVmList.add(info);
|
||||
mAvdList.add(info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private VmInfo parseVmInfo(File path) {
|
||||
private AvdInfo parseAvdInfo(File path) {
|
||||
Map<String, String> map = SdkManager.parsePropertyFile(path, mSdkLog);
|
||||
|
||||
String vmPath = map.get(VM_INFO_PATH);
|
||||
if (vmPath == null) {
|
||||
String avdPath = map.get(AVD_INFO_PATH);
|
||||
if (avdPath == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String targetHash = map.get(VM_INFO_TARGET);
|
||||
String targetHash = map.get(AVD_INFO_TARGET);
|
||||
if (targetHash == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -310,14 +332,14 @@ public final class VmManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
VmInfo info = new VmInfo();
|
||||
AvdInfo info = new AvdInfo();
|
||||
Matcher matcher = INI_NAME_PATTERN.matcher(path.getName());
|
||||
if (matcher.matches()) {
|
||||
info.name = matcher.group(1);
|
||||
} else {
|
||||
info.name = path.getName(); // really this should not happen.
|
||||
}
|
||||
info.path = vmPath;
|
||||
info.path = avdPath;
|
||||
info.target = target;
|
||||
|
||||
return info;
|
||||
@@ -447,4 +469,14 @@ public final class VmManager {
|
||||
return process.waitFor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an {@link AvdInfo} from the internal list.
|
||||
*
|
||||
* @param avdInfo The {@link AvdInfo} to remove.
|
||||
* @return true if this {@link AvdInfo} was present and has been removed.
|
||||
*/
|
||||
public boolean removeAvd(AvdInfo avdInfo) {
|
||||
return mAvdList.remove(avdInfo);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.sdklib.vm;
|
||||
package com.android.sdklib.avd;
|
||||
|
||||
import com.android.sdklib.ISdkLog;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package com.android.sdkuilib;
|
||||
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.vm.VmManager.VmInfo;
|
||||
import com.android.sdklib.avd.AvdManager.AvdInfo;
|
||||
|
||||
import org.eclipse.swt.SWT;
|
||||
import org.eclipse.swt.events.ControlAdapter;
|
||||
@@ -40,16 +40,16 @@ import java.util.ArrayList;
|
||||
|
||||
|
||||
/**
|
||||
* The VM selector is a table that is added to the given parent composite.
|
||||
* The AVD selector is a table that is added to the given parent composite.
|
||||
* <p/>
|
||||
* To use, create it using {@link #VmSelector(Composite, VmInfo[], boolean)} then
|
||||
* call {@link #setSelection(VmInfo)}, {@link #setSelectionListener(SelectionListener)}
|
||||
* To use, create it using {@link #AvdSelector(Composite, AvdInfo[], boolean)} then
|
||||
* call {@link #setSelection(AvdInfo)}, {@link #setSelectionListener(SelectionListener)}
|
||||
* and finally use {@link #getFirstSelected()} or {@link #getAllSelected()} to retrieve the
|
||||
* selection.
|
||||
*/
|
||||
public final class VmSelector {
|
||||
public final class AvdSelector {
|
||||
|
||||
private VmInfo[] mVms;
|
||||
private AvdInfo[] mAvds;
|
||||
private final boolean mAllowMultipleSelection;
|
||||
private SelectionListener mSelectionListener;
|
||||
private Table mTable;
|
||||
@@ -59,12 +59,12 @@ public final class VmSelector {
|
||||
* Creates a new SDK Target Selector.
|
||||
*
|
||||
* @param parent The parent composite where the selector will be added.
|
||||
* @param vms The list of vms. This is <em>not</em> copied, the caller must not modify.
|
||||
* @param avds The list of AVDs. This is <em>not</em> copied, the caller must not modify.
|
||||
* @param allowMultipleSelection True if more than one SDK target can be selected at the same
|
||||
* time.
|
||||
*/
|
||||
public VmSelector(Composite parent, VmInfo[] vms, boolean allowMultipleSelection) {
|
||||
mVms = vms;
|
||||
public AvdSelector(Composite parent, AvdInfo[] avds, boolean allowMultipleSelection) {
|
||||
mAvds = avds;
|
||||
|
||||
// Layout has 1 column
|
||||
Composite group = new Composite(parent, SWT.NONE);
|
||||
@@ -89,7 +89,7 @@ public final class VmSelector {
|
||||
|
||||
// create the table columns
|
||||
final TableColumn column0 = new TableColumn(mTable, SWT.NONE);
|
||||
column0.setText("VM Name");
|
||||
column0.setText("AVD Name");
|
||||
final TableColumn column1 = new TableColumn(mTable, SWT.NONE);
|
||||
column1.setText("Target Name");
|
||||
final TableColumn column2 = new TableColumn(mTable, SWT.NONE);
|
||||
@@ -104,25 +104,25 @@ public final class VmSelector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new set of VM, with an optional filter.
|
||||
* Sets a new set of AVD, with an optional filter.
|
||||
* <p/>This must be called from the UI thread.
|
||||
*
|
||||
* @param vms The list of vms. This is <em>not</em> copied, the caller must not modify.
|
||||
* @param filter An IAndroidTarget. If non-null, only VM whose target are compatible with the
|
||||
* @param avds The list of AVDs. This is <em>not</em> copied, the caller must not modify.
|
||||
* @param filter An IAndroidTarget. If non-null, only AVD whose target are compatible with the
|
||||
* filter target will displayed an available for selection.
|
||||
*/
|
||||
public void setVms(VmInfo[] vms, IAndroidTarget filter) {
|
||||
mVms = vms;
|
||||
public void setAvds(AvdInfo[] avds, IAndroidTarget filter) {
|
||||
mAvds = avds;
|
||||
fillTable(mTable, filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of known Vms.
|
||||
* Returns the list of known AVDs.
|
||||
* <p/>
|
||||
* This is not a copy. Callers must <em>not</em> modify this array.
|
||||
*/
|
||||
public VmInfo[] getVms() {
|
||||
return mVms;
|
||||
public AvdInfo[] getAvds() {
|
||||
return mAvds;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,11 +151,11 @@ public final class VmSelector {
|
||||
* @param target the target to be selection
|
||||
* @return true if the target could be selected, false otherwise.
|
||||
*/
|
||||
public boolean setSelection(VmInfo target) {
|
||||
public boolean setSelection(AvdInfo target) {
|
||||
boolean found = false;
|
||||
boolean modified = false;
|
||||
for (TableItem i : mTable.getItems()) {
|
||||
if ((VmInfo) i.getData() == target) {
|
||||
if ((AvdInfo) i.getData() == target) {
|
||||
found = true;
|
||||
if (!i.getChecked()) {
|
||||
modified = true;
|
||||
@@ -181,14 +181,14 @@ public final class VmSelector {
|
||||
* @see #getFirstSelected()
|
||||
* @return An array of selected items. The list can be empty but not null.
|
||||
*/
|
||||
public VmInfo[] getAllSelected() {
|
||||
public AvdInfo[] getAllSelected() {
|
||||
ArrayList<IAndroidTarget> list = new ArrayList<IAndroidTarget>();
|
||||
for (TableItem i : mTable.getItems()) {
|
||||
if (i.getChecked()) {
|
||||
list.add((IAndroidTarget) i.getData());
|
||||
}
|
||||
}
|
||||
return list.toArray(new VmInfo[list.size()]);
|
||||
return list.toArray(new AvdInfo[list.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,10 +198,10 @@ public final class VmSelector {
|
||||
* @see #getAllSelected()
|
||||
* @return The first selected item or null.
|
||||
*/
|
||||
public VmInfo getFirstSelected() {
|
||||
public AvdInfo getFirstSelected() {
|
||||
for (TableItem i : mTable.getItems()) {
|
||||
if (i.getChecked()) {
|
||||
return (VmInfo) i.getData();
|
||||
return (AvdInfo) i.getData();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -283,7 +283,7 @@ public final class VmSelector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the table with all VM.
|
||||
* Fills the table with all AVD.
|
||||
* The table columns are:
|
||||
* <ul>
|
||||
* <li>column 0: sdk name
|
||||
@@ -294,14 +294,14 @@ public final class VmSelector {
|
||||
*/
|
||||
private void fillTable(final Table table, IAndroidTarget filter) {
|
||||
table.removeAll();
|
||||
if (mVms != null && mVms.length > 0) {
|
||||
if (mAvds != null && mAvds.length > 0) {
|
||||
table.setEnabled(true);
|
||||
for (VmInfo vm : mVms) {
|
||||
if (filter == null || filter.isCompatibleBaseFor(vm.getTarget())) {
|
||||
for (AvdInfo avd : mAvds) {
|
||||
if (filter == null || filter.isCompatibleBaseFor(avd.getTarget())) {
|
||||
TableItem item = new TableItem(table, SWT.NONE);
|
||||
item.setData(vm);
|
||||
item.setText(0, vm.getName());
|
||||
IAndroidTarget target = vm.getTarget();
|
||||
item.setData(avd);
|
||||
item.setText(0, avd.getName());
|
||||
IAndroidTarget target = avd.getTarget();
|
||||
item.setText(1, target.getFullName());
|
||||
item.setText(2, target.getApiVersionName());
|
||||
item.setText(3, Integer.toString(target.getApiVersionNumber()));
|
||||
@@ -314,7 +314,7 @@ public final class VmSelector {
|
||||
TableItem item = new TableItem(table, SWT.NONE);
|
||||
item.setData(null);
|
||||
item.setText(0, "--");
|
||||
item.setText(1, "No VM available");
|
||||
item.setText(1, "No AVD available");
|
||||
item.setText(2, "--");
|
||||
item.setText(3, "--");
|
||||
}
|
||||
@@ -365,13 +365,13 @@ public final class VmSelector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the description label with the path of the item's VM, if any.
|
||||
* Updates the description label with the path of the item's AVD, if any.
|
||||
*/
|
||||
private void updateDescription(TableItem item) {
|
||||
if (item != null) {
|
||||
Object data = item.getData();
|
||||
if (data instanceof VmInfo) {
|
||||
String newTooltip = ((VmInfo) data).getPath();
|
||||
if (data instanceof AvdInfo) {
|
||||
String newTooltip = ((AvdInfo) data).getPath();
|
||||
mDescription.setText(newTooltip == null ? "" : newTooltip); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user