auto import from //branches/cupcake/...@125939

This commit is contained in:
The Android Open Source Project
2009-01-09 17:51:19 -08:00
parent e943f2fd8e
commit 95cf464c5a
176 changed files with 4721 additions and 7588 deletions

View File

@@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="src" path="tests"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry combineaccessrules="false" kind="src" path="/SdkLib"/>
<classpathentry combineaccessrules="false" kind="src" path="/AndroidPrefs"/>
<classpathentry combineaccessrules="false" kind="src" path="/SdkUiLib"/>
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,580 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.sdkmanager;
import java.util.HashMap;
import java.util.Map.Entry;
/**
* Parses the command-line and stores flags needed or requested.
* <p/>
* This is a base class. To be useful you want to:
* <ul>
* <li>override it.
* <li>pass an action array to the constructor.
* <li>define flags for your actions.
* </ul>
* <p/>
* To use, call {@link #parseArgs(String[])} and then call {@link #getValue(String, String)}.
*/
public class CommandLineProcessor {
/** Internal action name for all global flags. */
public final static String GLOBAL_FLAG = "global";
/** Internal action name for internally hidden flags.
* This is currently used to store the requested action name. */
public final static String INTERNAL_FLAG = "internal";
/** The global help flag. */
public static final String KEY_HELP = "help";
/** The global verbose flag. */
public static final String KEY_VERBOSE = "verbose";
/** The internal action flag. */
public static final String KEY_ACTION = "action";
/** List of available actions.
* <p/>
* Each entry must be a 2-string array with first the action name and then
* a description.
*/
private final String[][] mActions;
/** The hash of all defined arguments.
* <p/>
* The key is a string "action/longName".
*/
private final HashMap<String, Arg> mArguments = new HashMap<String, Arg>();
public CommandLineProcessor(String[][] actions) {
mActions = actions;
define(MODE.STRING, false, INTERNAL_FLAG, null, KEY_ACTION, "Selected Action", null);
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "v", KEY_VERBOSE, "Verbose mode", false);
define(MODE.BOOLEAN, false, GLOBAL_FLAG, "h", KEY_HELP, "This help", false);
}
//------------------
// Helpers to get flags values
/** Helper that returns true if --verbose was requested. */
public boolean isVerbose() {
return ((Boolean) getValue(GLOBAL_FLAG, KEY_VERBOSE)).booleanValue();
}
/** Helper that returns true if --help was requested. */
public boolean isHelpRequested() {
return ((Boolean) getValue(GLOBAL_FLAG, KEY_HELP)).booleanValue();
}
/** Helper that returns the requested action name. */
public String getActionRequested() {
return (String) getValue(INTERNAL_FLAG, KEY_ACTION);
}
//------------------
/**
* Raw access to parsed parameter values.
* @param action The action name, including {@link #GLOBAL_FLAG} and {@link #INTERNAL_FLAG}
* @param longFlagName The long flag name for the given action.
* @return The current value object stored in the parameter, which depends on the argument mode.
*/
public Object getValue(String action, String longFlagName) {
String key = action + "/" + longFlagName;
Arg arg = mArguments.get(key);
return arg.getCurrentValue();
}
/**
* Internal setter for raw parameter value.
* @param action The action name, including {@link #GLOBAL_FLAG} and {@link #INTERNAL_FLAG}
* @param longFlagName The long flag name for the given action.
* @param value The new current value object stored in the parameter, which depends on the
* argument mode.
*/
protected void setValue(String action, String longFlagName, Object value) {
String key = action + "/" + longFlagName;
Arg arg = mArguments.get(key);
arg.setCurrentValue(value);
}
/**
* Parses the command-line arguments.
* <p/>
* This method will exit and not return if a parsing error arise.
*
* @param args The arguments typically received by a main method.
*/
public void parseArgs(String[] args) {
String needsHelp = null;
String action = null;
int n = args.length;
for (int i = 0; i < n; i++) {
Arg arg = null;
String a = args[i];
if (a.startsWith("--")) {
arg = findLongArg(action, a.substring(2));
} else if (a.startsWith("-")) {
arg = findShortArg(action, a.substring(1));
}
// Not a keyword and we don't have an action yet, this should be an action
if (arg == null && action == null) {
if (a.startsWith("-")) {
// Got a keyword but not valid for global flags
needsHelp = String.format(
"Flag '%1$s' is not a valid global flag. Did you mean to specify it after the action name?",
a, action);
break;
}
for (String[] actionDesc : mActions) {
if (actionDesc[0].equals(a)) {
action = a;
break;
}
}
if (action == null) {
needsHelp = String.format(
"Expected action name after global parameters but found %1$s instead.",
a);
break;
}
} else if (arg == null && action != null) {
// Got a keyword but not valid for the current action
needsHelp = String.format(
"Flag '%1$s' is not valid for action '%2$s'.",
a, action);
break;
} else if (arg != null) {
// Process keyword
String error = null;
if (arg.getMode().needsExtra()) {
if (++i >= n) {
needsHelp = String.format("Missing argument for flag %1$s.", a);
break;
}
error = arg.getMode().process(arg, args[i]);
} else {
error = arg.getMode().process(arg, null);
// If we just toggled help, we want to exit now without printing any error.
// We do this test here only when a Boolean flag is toggled since booleans
// are the only flags that don't take parameters and help is a boolean.
if (isHelpRequested()) {
printHelpAndExit(null);
// The call above should terminate however in unit tests we override
// it so we still need to return here.
return;
}
}
if (error != null) {
needsHelp = String.format("Invalid usage for flag %1$s: %2$s.", a, error);
break;
}
}
}
if (needsHelp == null) {
if (action == null) {
needsHelp = "Missing action name.";
} else {
// Validate that all mandatory arguments are non-null for this action
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getAction().equals(action)) {
if (arg.isMandatory() && arg.getCurrentValue() == null) {
needsHelp = String.format("The parameter --%1$s must be defined for action '%2$s'",
arg.getLongArg(),
action);
break;
}
}
}
setValue(INTERNAL_FLAG, KEY_ACTION, action);
}
}
if (needsHelp != null) {
printHelpAndExitForAction(action, needsHelp);
}
}
/**
* Finds an {@link Arg} given an action name and a long flag name.
* @return The {@link Arg} found or null.
*/
protected Arg findLongArg(String action, String longName) {
if (action == null) {
action = GLOBAL_FLAG;
}
String key = action + "/" + longName;
return mArguments.get(key);
}
/**
* Finds an {@link Arg} given an action name and a short flag name.
* @return The {@link Arg} found or null.
*/
protected Arg findShortArg(String action, String shortName) {
if (action == null) {
action = GLOBAL_FLAG;
}
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getAction().equals(action)) {
if (shortName.equals(arg.getShortArg())) {
return arg;
}
}
}
return null;
}
/**
* Prints the help/usage and exits.
*
* @param errorFormat Optional error message to print prior to usage using String.format
* @param args Arguments for String.format
*/
public void printHelpAndExit(String errorFormat, Object... args) {
printHelpAndExitForAction(null /*actionFilter*/, errorFormat, args);
}
/**
* Prints the help/usage and exits.
*
* @param actionFilter If null, displays help for all actions. If not null, display help only
* for that specific action. In all cases also display general usage and action list.
* @param errorFormat Optional error message to print prior to usage using String.format
* @param args Arguments for String.format
*/
public void printHelpAndExitForAction(String actionFilter, String errorFormat, Object... args) {
if (errorFormat != null) {
stderr(errorFormat, args);
}
/*
* usage should fit in 80 columns
* 12345678901234567890123456789012345678901234567890123456789012345678901234567890
*/
stdout("\n" +
"Usage:\n" +
" android [global options] action [action options]\n" +
"\n" +
"Global options:");
listOptions(GLOBAL_FLAG);
stdout("\nValid actions:");
for (String[] action : mActions) {
String filler = "";
int len = action[0].length();
if (len < 10) {
filler = " ".substring(len);
}
stdout("- %1$s:%2$s %3$s", action[0], filler, action[1]);
}
for (String[] action : mActions) {
if (actionFilter == null || actionFilter.equals(action[0])) {
stdout("\nAction \"%1$s\":", action[0]);
stdout(" %1$s", action[1]);
stdout("Options:");
listOptions(action[0]);
}
}
exit();
}
/**
* Internal helper to print all the option flags for a given action name.
*/
protected void listOptions(String action) {
int numOptions = 0;
for (Entry<String, Arg> entry : mArguments.entrySet()) {
Arg arg = entry.getValue();
if (arg.getAction().equals(action)) {
String value = null;
if (arg.getDefaultValue() instanceof String[]) {
value = "";
for (String v : (String[]) arg.getDefaultValue()) {
if (value.length() > 0) {
value += "|";
}
value += v;
}
} else if (arg.getDefaultValue() != null) {
value = arg.getDefaultValue().toString();
}
stdout(" -%1$s %2$-10s %3$s%4$s",
arg.getShortArg(),
"--" + arg.getLongArg(),
arg.getDescription(),
value == null ? "" : " (" + value + ")");
numOptions++;
}
}
if (numOptions == 0) {
stdout(" No options");
}
}
//----
/**
* The mode of an argument specifies the type of variable it represents,
* whether an extra parameter is required after the flag and how to parse it.
*/
static enum MODE {
/** Argument value is a Boolean. Default value is a Boolean. */
BOOLEAN {
@Override
public boolean needsExtra() {
return false;
}
@Override
public String process(Arg arg, String extra) {
// Toggle the current value
arg.setCurrentValue(! ((Boolean) arg.getCurrentValue()).booleanValue());
return null;
}
},
/** Argument value is an Integer. Default value is an Integer. */
INTEGER {
@Override
public boolean needsExtra() {
return true;
}
@Override
public String process(Arg arg, String extra) {
try {
arg.setCurrentValue(Integer.parseInt(extra));
return null;
} catch (NumberFormatException e) {
return String.format("Failed to parse '%1$s' as an integer: %2%s",
extra, e.getMessage());
}
}
},
/** Argument value is a String. Default value is a String[]. */
ENUM {
@Override
public boolean needsExtra() {
return true;
}
@Override
public String process(Arg arg, String extra) {
StringBuilder desc = new StringBuilder();
String[] values = (String[]) arg.getDefaultValue();
for (String value : values) {
if (value.equals(extra)) {
arg.setCurrentValue(extra);
return null;
}
if (desc.length() != 0) {
desc.append(", ");
}
desc.append(value);
}
return String.format("'%1$s' is not one of %2$s", extra, desc.toString());
}
},
/** Argument value is a String. Default value is a null. */
STRING {
@Override
public boolean needsExtra() {
return true;
}
@Override
public String process(Arg arg, String extra) {
arg.setCurrentValue(extra);
return null;
}
};
/**
* Returns true if this mode requires an extra parameter.
*/
public abstract boolean needsExtra();
/**
* Processes the flag for this argument.
*
* @param arg The argument being processed.
* @param extra The extra parameter. Null if {@link #needsExtra()} returned false.
* @return An error string or null if there's no error.
*/
public abstract String process(Arg arg, String extra);
}
/**
* An argument accepted by the command-line, also called "a flag".
* Arguments must have a short version (one letter), a long version name and a description.
* They can have a default value, or it can be null.
* Depending on the {@link MODE}, the default value can be a Boolean, an Integer, a String
* or a String array (in which case the first item is the current by default.)
*/
static class Arg {
private final String mAction;
private final String mShortName;
private final String mLongName;
private final String mDescription;
private final Object mDefaultValue;
private Object mCurrentValue;
private final MODE mMode;
private final boolean mMandatory;
/**
* Creates a new argument flag description.
*
* @param mode The {@link MODE} for the argument.
* @param mandatory True if this argument is mandatory for this action.
* @param action The action name. Can be #GLOBAL_FLAG or #INTERNAL_FLAG.
* @param shortName The one-letter short argument name. Cannot be empty nor null.
* @param longName The long argument name. Cannot be empty nor null.
* @param description The description. Cannot be null.
* @param defaultValue The default value (or values), which depends on the selected {@link MODE}.
*/
public Arg(MODE mode,
boolean mandatory,
String action,
String shortName,
String longName,
String description,
Object defaultValue) {
mMode = mode;
mMandatory = mandatory;
mAction = action;
mShortName = shortName;
mLongName = longName;
mDescription = description;
mDefaultValue = defaultValue;
if (defaultValue instanceof String[]) {
mCurrentValue = ((String[])defaultValue)[0];
} else {
mCurrentValue = mDefaultValue;
}
}
public boolean isMandatory() {
return mMandatory;
}
public String getShortArg() {
return mShortName;
}
public String getLongArg() {
return mLongName;
}
public String getDescription() {
return mDescription;
}
public String getAction() {
return mAction;
}
public Object getDefaultValue() {
return mDefaultValue;
}
public Object getCurrentValue() {
return mCurrentValue;
}
public void setCurrentValue(Object currentValue) {
mCurrentValue = currentValue;
}
public MODE getMode() {
return mMode;
}
}
/**
* Internal helper to define a new argument for a give action.
*
* @param mode The {@link MODE} for the argument.
* @param action The action name. Can be #GLOBAL_FLAG or #INTERNAL_FLAG.
* @param shortName The one-letter short argument name. Cannot be empty nor null.
* @param longName The long argument name. Cannot be empty nor null.
* @param description The description. Cannot be null.
* @param defaultValue The default value (or values), which depends on the selected {@link MODE}.
*/
protected void define(MODE mode,
boolean mandatory,
String action,
String shortName, String longName,
String description, Object defaultValue) {
assert(mandatory || mode == MODE.BOOLEAN); // a boolean mode cannot be mandatory
String key = action + "/" + longName;
mArguments.put(key, new Arg(mode, mandatory,
action, shortName, longName, description, defaultValue));
}
/**
* Exits in case of error.
* This is protected so that it can be overridden in unit tests.
*/
protected void exit() {
System.exit(1);
}
/**
* Prints a line to stdout.
* This is protected so that it can be overridden in unit tests.
*
* @param format The string to be formatted. Cannot be null.
* @param args Format arguments.
*/
protected void stdout(String format, Object...args) {
System.out.println(String.format(format, args));
}
/**
* Prints a line to stderr.
* This is protected so that it can be overridden in unit tests.
*
* @param format The string to be formatted. Cannot be null.
* @param args Format arguments.
*/
protected void stderr(String format, Object...args) {
System.err.println(String.format(format, args));
}
}

View File

@@ -23,6 +23,8 @@ import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkConstants;
import com.android.sdklib.SdkManager;
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;
import com.android.sdklib.project.ProjectCreator;
import com.android.sdklib.project.ProjectCreator.OutputLevel;
import com.android.sdklib.vm.HardwareProperties;
import com.android.sdklib.vm.VmManager;
import com.android.sdklib.vm.HardwareProperties.HardwareProperty;
@@ -35,31 +37,20 @@ import java.util.List;
import java.util.Map;
/**
* Main class for the 'android' application
*
* Main class for the 'android' application.
*/
class Main {
private final static String TOOLSDIR = "com.android.sdkmanager.toolsdir";
private final static String ARG_LIST_TARGET = "target";
private final static String ARG_LIST_VM = "vm";
private final static String[] BOOLEAN_YES_REPLIES = new String[] { "yes", "y" };
private final static String[] BOOLEAN_NO_REPLIES = new String[] { "no", "n" };
private String mSdkFolder;
private ISdkLog mSdkLog;
private SdkManager mSdkManager;
private VmManager mVmManager;
/* --list parameters */
private String mListObject;
/* --create parameters */
private boolean mCreateVm;
private int mCreateTargetId;
private IAndroidTarget mCreateTarget;
private String mCreateName;
private SdkCommandLine mSdkCommandLine;
public static void main(String[] args) {
new Main().run(args);
@@ -71,7 +62,7 @@ class Main {
*/
private void run(String[] args) {
init();
parseArgs(args);
mSdkCommandLine.parseArgs(args);
parseSdk();
doAction();
}
@@ -81,70 +72,41 @@ class Main {
* doing basic parsing of the SDK.
*/
private void init() {
mSdkCommandLine = new SdkCommandLine();
/* We get passed a property for the tools dir */
String toolsDirProp = System.getProperty(TOOLSDIR);
if (toolsDirProp == null) {
// for debugging, it's easier to override using the process environment
toolsDirProp = System.getenv(TOOLSDIR);
}
if (toolsDirProp == null) {
printHelpAndExit("ERROR: The tools directory property is not set, please make sure you are executing android or android.bat");
}
// got back a level for the SDK folder
File tools = new File(toolsDirProp);
mSdkFolder = tools.getParent();
}
/**
* Parses command-line arguments, or prints help/usage and exits if error.
* @param args arguments passed to the program
*/
private void parseArgs(String[] args) {
final int numArgs = args.length;
try {
int argPos = 0;
for (; argPos < numArgs; argPos++) {
final String arg = args[argPos];
if (arg.equals("-l") || arg.equals("--list")) {
mListObject = args[++argPos];
} else if (arg.equals("-c") || arg.equals("--create")) {
mCreateVm = true;
parseCreateArgs(args, ++argPos);
if (toolsDirProp != null) {
// got back a level for the SDK folder
File tools;
if (toolsDirProp.length() > 0) {
tools = new File(toolsDirProp);
mSdkFolder = tools.getParent();
} else {
try {
tools = new File(".").getCanonicalFile();
mSdkFolder = tools.getParent();
} catch (IOException e) {
// Will print an error below since mSdkFolder is not defined
}
}
} catch (ArrayIndexOutOfBoundsException e) {
/* Any OOB triggers help */
printHelpAndExit("ERROR: Not enough arguments.");
}
}
private void parseCreateArgs(String[] args, int argPos) {
final int numArgs = args.length;
try {
for (; argPos < numArgs; argPos++) {
final String arg = args[argPos];
if (arg.equals("-t") || arg.equals("--target")) {
String targetId = args[++argPos];
try {
// get the target id
mCreateTargetId = Integer.parseInt(targetId);
} catch (NumberFormatException e) {
printHelpAndExit("ERROR: Target Id is not a number");
}
} else if (arg.equals("-n") || arg.equals("--name")) {
mCreateName = args[++argPos];
} else {
printHelpAndExit("ERROR: '%s' unknown argument for --create mode",
args[argPos]);
}
if (mSdkFolder == null) {
String os = System.getProperty("os.name");
String cmd = "android";
if (os.startsWith("Windows")) {
cmd += ".bat";
}
} catch (ArrayIndexOutOfBoundsException e) {
/* Any OOB triggers help */
printHelpAndExit("ERROR: Not enough arguments for --create");
mSdkCommandLine.printHelpAndExit(
"ERROR: The tools directory property is not set, please make sure you are executing %1$s",
cmd);
}
}
@@ -152,10 +114,15 @@ class Main {
* Does the basic SDK parsing required for all actions
*/
private void parseSdk() {
mSdkManager = SdkManager.createManager(mSdkFolder, new ISdkLog() {
public void error(String errorFormat, Object... args) {
System.err.printf("Error: " + errorFormat, args);
System.err.println("");
mSdkLog = new ISdkLog() {
public void error(Throwable t, String errorFormat, Object... args) {
if (errorFormat != null) {
System.err.printf("Error: " + errorFormat, args);
System.err.println("");
}
if (t != null) {
System.err.print("Error: " + t.getMessage());
}
}
public void warning(String warningFormat, Object... args) {
@@ -165,10 +132,15 @@ class Main {
System.out.println("");
}
}
});
public void printf(String msgFormat, Object... args) {
System.out.printf(msgFormat, args);
}
};
mSdkManager = SdkManager.createManager(mSdkFolder, mSdkLog);
if (mSdkManager == null) {
printHelpAndExit("ERROR: Unable to parse SDK content.");
mSdkCommandLine.printHelpAndExit("ERROR: Unable to parse SDK content.");
}
}
@@ -176,19 +148,37 @@ class Main {
* Actually do an action...
*/
private void doAction() {
if (mListObject != null) {
String action = mSdkCommandLine.getActionRequested();
if (SdkCommandLine.ACTION_LIST.equals(action)) {
// list action.
if (ARG_LIST_TARGET.equals(mListObject)) {
if (SdkCommandLine.ARG_TARGET.equals(mSdkCommandLine.getListFilter())) {
displayTargetList();
} else if (ARG_LIST_VM.equals(mListObject)) {
} else if (SdkCommandLine.ARG_VM.equals(mSdkCommandLine.getListFilter())) {
displayVmList();
} else {
printHelpAndExit("'%s' is not a valid --list option", mListObject);
displayTargetList();
displayVmList();
}
} else if (mCreateVm) {
} else if (SdkCommandLine.ACTION_NEW_VM.equals(action)) {
createVm();
} else if (SdkCommandLine.ACTION_NEW_PROJECT.equals(action)) {
// get the target and try to resolve it.
int targetId = mSdkCommandLine.getNewProjectTargetId();
IAndroidTarget[] targets = mSdkManager.getTargets();
if (targetId < 1 || targetId > targets.length) {
mSdkCommandLine.printHelpAndExit("ERROR: Wrong target id.");
}
IAndroidTarget target = targets[targetId - 1];
ProjectCreator creator = new ProjectCreator(mSdkFolder,
OutputLevel.NORMAL, mSdkLog);
creator.createProject(mSdkCommandLine.getNewProjectLocation(),
mSdkCommandLine.getNewProjectName(), mSdkCommandLine.getNewProjectPackage(),
mSdkCommandLine.getNewProjectActivity(), target, true);
} else {
printHelpAndExit(null);
mSdkCommandLine.printHelpAndExit(null);
}
}
@@ -274,7 +264,7 @@ class Main {
index++;
}
} catch (AndroidLocationException e) {
printHelpAndExit(e.getMessage());
mSdkCommandLine.printHelpAndExit(e.getMessage());
}
}
@@ -283,11 +273,14 @@ class Main {
*/
private void createVm() {
// find a matching target
if (mCreateTargetId >= 1 && mCreateTargetId <= mSdkManager.getTargets().length) {
mCreateTarget = mSdkManager.getTargets()[mCreateTargetId-1]; // target it is 1-based
int targetId = mSdkCommandLine.getNewVmTargetId();
IAndroidTarget target = null;
if (targetId >= 1 && targetId <= mSdkManager.getTargets().length) {
target = mSdkManager.getTargets()[targetId-1]; // target it is 1-based
} else {
printHelpAndExit(
"ERROR: Target Id is not a valid Id. Check android --list target for the list of targets.");
mSdkCommandLine.printHelpAndExit(
"ERROR: Target Id is not a valid Id. Check 'android list target' for the list of targets.");
}
try {
@@ -295,19 +288,24 @@ class Main {
String vmRoot = AndroidLocation.getFolder() + AndroidLocation.FOLDER_VMS;
Map<String, String> hardwareConfig = null;
if (mCreateTarget.isPlatform()) {
if (target.isPlatform()) {
try {
hardwareConfig = promptForHardware(mCreateTarget);
hardwareConfig = promptForHardware(target);
} catch (IOException e) {
printHelpAndExit(e.getMessage());
mSdkCommandLine.printHelpAndExit(e.getMessage());
}
}
VmManager.createVm(vmRoot, mCreateName, mCreateTarget, null /*skinName*/,
null /*sdcardPath*/, 0 /*sdcardSize*/, hardwareConfig,
VmManager.createVm(vmRoot,
mSdkCommandLine.getNewVmName(),
target,
null /*skinName*/,
null /*sdcardPath*/,
0 /*sdcardSize*/,
hardwareConfig,
null /* sdklog */);
} catch (AndroidLocationException e) {
printHelpAndExit(e.getMessage());
mSdkCommandLine.printHelpAndExit(e.getMessage());
}
}
@@ -325,7 +323,7 @@ class Main {
System.out.print(String.format("Do you which to create a custom hardware profile [%s]",
defaultAnswer));
result = readLine(readLineBuffer);
result = readLine(readLineBuffer).trim();
// handle default:
if (result.length() == 0) {
result = defaultAnswer;
@@ -391,8 +389,7 @@ class Main {
break;
case INTEGER:
try {
@SuppressWarnings("unused")
int value = Integer.parseInt(result);
Integer.parseInt(result);
map.put(property.getName(), result);
i++; // valid reply, move to next property
} catch (NumberFormatException e) {
@@ -414,9 +411,8 @@ class Main {
}
/**
* Read the line from the input stream.
* Reads the line from the input stream.
* @param buffer
* @return
* @throws IOException
*/
private String readLine(byte[] buffer) throws IOException {
@@ -434,7 +430,12 @@ class Main {
return new String(buffer, 0, count) + secondHalf;
}
return new String(buffer, 0, count - 1); // -1 to not include the carriage return
// ignore end whitespace
while (count > 0 && (buffer[count-1] == '\r' || buffer[count-1] == '\n')) {
count--;
}
return new String(buffer, 0, count);
}
/**
@@ -442,6 +443,7 @@ class Main {
* @throws IOException If the value is not a boolean string.
*/
private boolean getBooleanReply(String reply) throws IOException {
for (String valid : BOOLEAN_YES_REPLIES) {
if (valid.equalsIgnoreCase(reply)) {
return true;
@@ -456,32 +458,4 @@ class Main {
throw new IOException(String.format("%s is not a valid reply", reply));
}
/**
* Prints the help/usage and exits.
* @param errorFormat Optional error message to print prior to usage using String.format
* @param args Arguments for String.format
*/
private void printHelpAndExit(String errorFormat, Object... args) {
if (errorFormat != null) {
System.err.println(String.format(errorFormat, args));
}
/*
* usage should fit in 80 columns
* 12345678901234567890123456789012345678901234567890123456789012345678901234567890
*/
final String usage = "\n" +
"Usage:\n" +
" android --list [target|vm]\n" +
" android --create --target <target id> --name <name>\n" +
"\n" +
"Options:\n" +
" -l [target|vm], --list [target|vm]\n" +
" Outputs the available targets or Virtual Machines and their Ids.\n" +
"\n";
System.out.println(usage);
System.exit(1);
}
}

View File

@@ -0,0 +1,152 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.sdkmanager;
import com.android.sdklib.SdkManager;
/**
* Specific command-line flags for the {@link SdkManager}.
*/
public class SdkCommandLine extends CommandLineProcessor {
public static final String ARG_ALIAS = "alias";
public static final String ARG_ACTIVITY = "activity";
public static final String ARG_VM = "vm";
public static final String ARG_TARGET = "target";
public static final String ARG_ALL = "all";
public static final String KEY_IN = "in";
public static final String KEY_ACTIVITY = ARG_ACTIVITY;
public static final String KEY_PACKAGE = "package";
public static final String KEY_MODE = "mode";
public static final String KEY_TARGET_ID = ARG_TARGET;
public static final String KEY_NAME = "name";
public static final String KEY_OUT = "out";
public static final String KEY_FILTER = "filter";
public final static String ACTION_LIST = "list";
public final static String ACTION_NEW_VM = ARG_VM;
public final static String ACTION_NEW_PROJECT = "project";
public final static String ACTION_UPDATE_PROJECT = "update";
private final static String[][] ACTIONS = {
{ ACTION_LIST,
"Lists existing targets or VMs." },
{ ACTION_NEW_VM,
"Creates a new VM." },
{ ACTION_NEW_PROJECT,
"Creates a new project using a template." },
{ ACTION_UPDATE_PROJECT,
"Updates a new project from existing source (must have an AndroidManifest.xml)." },
};
public SdkCommandLine() {
super(ACTIONS);
define(MODE.ENUM, false, ACTION_LIST, "f", KEY_FILTER,
"List filter", new String[] { ARG_ALL, ARG_TARGET, ARG_VM });
define(MODE.STRING, false, ACTION_NEW_VM, "o", KEY_OUT,
"Location path of new VM", null);
define(MODE.STRING, true, ACTION_NEW_VM, "n", KEY_NAME,
"Name of the new VM", null);
define(MODE.INTEGER, true, ACTION_NEW_VM, "t", KEY_TARGET_ID,
"Target id of the new VM", null);
define(MODE.ENUM, true, ACTION_NEW_PROJECT, "m", KEY_MODE,
"Project mode", new String[] { ARG_ACTIVITY, ARG_ALIAS });
define(MODE.STRING, false, ACTION_NEW_PROJECT, "o", KEY_OUT,
"Location path of new project", null);
define(MODE.STRING, true, ACTION_NEW_PROJECT, "n", KEY_NAME,
"Name of the new project", null);
define(MODE.INTEGER, true, ACTION_NEW_PROJECT, "t", KEY_TARGET_ID,
"Target id of the new project", null);
define(MODE.STRING, true, ACTION_NEW_PROJECT, "p", KEY_PACKAGE,
"Package name", null);
define(MODE.STRING, true, ACTION_NEW_PROJECT, "a", KEY_ACTIVITY,
"Activity name", null);
define(MODE.STRING, false, ACTION_UPDATE_PROJECT, "i", KEY_IN,
"Directory location of the project", null);
define(MODE.STRING, true, ACTION_UPDATE_PROJECT, "t", KEY_TARGET_ID,
"Target id to set for the project", null);
}
// -- some helpers for list action flags
/** Helper to retrieve the --filter for the list action. */
public String getListFilter() {
return ((String) getValue(ACTION_LIST, KEY_FILTER));
}
// -- some helpers for vm action flags
/** Helper to retrieve the --out location for the new vm action. */
public String getNewVmLocation() {
return ((String) getValue(ACTION_NEW_VM, KEY_OUT));
}
/** Helper to retrieve the --target id for the new vm action. */
public int getNewVmTargetId() {
return ((Integer) getValue(ACTION_NEW_VM, KEY_TARGET_ID)).intValue();
}
/** Helper to retrieve the --name for the new vm action. */
public String getNewVmName() {
return ((String) getValue(ACTION_NEW_VM, KEY_NAME));
}
// -- some helpers for project action flags
/** Helper to retrieve the --out location for the new project action. */
public String getNewProjectLocation() {
return ((String) getValue(ACTION_NEW_PROJECT, KEY_OUT));
}
/** Helper to retrieve the --target id for the new project action. */
public int getNewProjectTargetId() {
return ((Integer) getValue(ACTION_NEW_PROJECT, KEY_TARGET_ID)).intValue();
}
/** Helper to retrieve the --name for the new project action. */
public String getNewProjectName() {
return ((String) getValue(ACTION_NEW_PROJECT, KEY_NAME));
}
/** Helper to retrieve the --package for the new project action. */
public String getNewProjectPackage() {
return ((String) getValue(ACTION_NEW_PROJECT, KEY_PACKAGE));
}
/** Helper to retrieve the --activity for the new project action. */
public String getNewProjectActivity() {
return ((String) getValue(ACTION_NEW_PROJECT, KEY_ACTIVITY));
}
// -- some helpers for update action flags
/** Helper to retrieve the --out location for the update project action. */
public String getUpdateProjectLocation() {
return ((String) getValue(ACTION_UPDATE_PROJECT, KEY_OUT));
}
/** Helper to retrieve the --target id for the update project action. */
public int getUpdateProjectTargetId() {
return ((Integer) getValue(ACTION_UPDATE_PROJECT, KEY_TARGET_ID)).intValue();
}
}

View File

@@ -0,0 +1,180 @@
/*
* 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 junit.framework.TestCase;
public class CommandLineProcessorTest extends TestCase {
/**
* A mock version of the {@link CommandLineProcessor} class that does not
* exits and captures its stdout/stderr output.
*/
public static class MockCommandLineProcessor extends CommandLineProcessor {
private boolean mExitCalled;
private boolean mHelpCalled;
private String mStdOut = "";
private String mStdErr = "";
public MockCommandLineProcessor() {
super(new String[][] {
{ "action1", "Some action" },
{ "action2", "Another action" },
});
define(MODE.STRING, false /*mandatory*/,
"action1", "1", "first", "non-mandatory flag", null);
define(MODE.STRING, true /*mandatory*/,
"action1", "2", "second", "mandatory flag", null);
}
@Override
public void printHelpAndExitForAction(String actionFilter,
String errorFormat, Object... args) {
mHelpCalled = true;
super.printHelpAndExitForAction(actionFilter, errorFormat, args);
}
@Override
protected void exit() {
mExitCalled = true;
}
@Override
protected void stdout(String format, Object... args) {
String s = String.format(format, args);
mStdOut += s + "\n";
// don't call super to avoid printing stuff
}
@Override
protected void stderr(String format, Object... args) {
String s = String.format(format, args);
mStdErr += s + "\n";
// don't call super to avoid printing stuff
}
public boolean wasHelpCalled() {
return mHelpCalled;
}
public boolean wasExitCalled() {
return mExitCalled;
}
public String getStdOut() {
return mStdOut;
}
public String getStdErr() {
return mStdErr;
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
public final void testPrintHelpAndExit() {
MockCommandLineProcessor c = new MockCommandLineProcessor();
assertFalse(c.wasExitCalled());
assertFalse(c.wasHelpCalled());
assertTrue(c.getStdOut().equals(""));
assertTrue(c.getStdErr().equals(""));
c.printHelpAndExit(null);
assertTrue(c.getStdOut().indexOf("-v") != -1);
assertTrue(c.getStdOut().indexOf("--verbose") != -1);
assertTrue(c.getStdErr().equals(""));
assertTrue(c.wasExitCalled());
c = new MockCommandLineProcessor();
assertFalse(c.wasExitCalled());
assertTrue(c.getStdOut().equals(""));
assertTrue(c.getStdErr().indexOf("Missing parameter") == -1);
c.printHelpAndExit("Missing %s", "parameter");
assertTrue(c.wasExitCalled());
assertFalse(c.getStdOut().equals(""));
assertTrue(c.getStdErr().indexOf("Missing parameter") != -1);
}
public final void testVerbose() {
MockCommandLineProcessor c = new MockCommandLineProcessor();
assertFalse(c.isVerbose());
c.parseArgs(new String[] { "-v" });
assertTrue(c.isVerbose());
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("Missing action name.") != -1);
c = new MockCommandLineProcessor();
c.parseArgs(new String[] { "--verbose" });
assertTrue(c.isVerbose());
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("Missing action name.") != -1);
}
public final void testHelp() {
MockCommandLineProcessor c = new MockCommandLineProcessor();
c.parseArgs(new String[] { "-h" });
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("Missing action name.") == -1);
c = new MockCommandLineProcessor();
c.parseArgs(new String[] { "--help" });
assertTrue(c.wasExitCalled());
assertTrue(c.wasHelpCalled());
assertTrue(c.getStdErr().indexOf("Missing action name.") == -1);
}
public final void testMandatory() {
MockCommandLineProcessor c = new MockCommandLineProcessor();
c.parseArgs(new String[] { "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"));
c = new MockCommandLineProcessor();
c.parseArgs(new String[] { "action1", "-2", "value2" });
assertFalse(c.wasExitCalled());
assertFalse(c.wasHelpCalled());
assertEquals("", c.getStdErr());
assertEquals(null, c.getValue("action1", "first"));
assertEquals("value2", c.getValue("action1", "second"));
c = new MockCommandLineProcessor();
c.parseArgs(new String[] { "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"));
}
}

View File

@@ -0,0 +1,105 @@
/*
* 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 junit.framework.TestCase;
public class SdkCommandLineTest extends TestCase {
/**
* A mock version of the {@link SdkCommandLine} class that does not
* exits and discards its stdout/stderr output.
*/
public static class MockSdkCommandLine extends SdkCommandLine {
private boolean mExitCalled;
private boolean mHelpCalled;
public MockSdkCommandLine() {
}
@Override
public void printHelpAndExitForAction(String actionFilter,
String errorFormat, Object... args) {
mHelpCalled = true;
super.printHelpAndExitForAction(actionFilter, errorFormat, args);
}
@Override
protected void exit() {
mExitCalled = true;
}
@Override
protected void stdout(String format, Object... args) {
// discard
}
@Override
protected void stderr(String format, Object... args) {
// discard
}
public boolean wasExitCalled() {
return mExitCalled;
}
public boolean wasHelpCalled() {
return mHelpCalled;
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
/** Test list with long name and verbose */
public final void testList_Long_Verbose() {
MockSdkCommandLine c = new MockSdkCommandLine();
assertEquals("all", c.getListFilter());
c.parseArgs(new String[] { "-v", "list", "--filter", "vm" });
assertFalse(c.wasHelpCalled());
assertFalse(c.wasExitCalled());
assertEquals("vm", c.getListFilter());
assertTrue(c.isVerbose());
}
/** Test list with short name and no verbose */
public final void testList_Short() {
MockSdkCommandLine c = new MockSdkCommandLine();
assertEquals("all", c.getListFilter());
c.parseArgs(new String[] { "list", "-f", "vm" });
assertFalse(c.wasHelpCalled());
assertFalse(c.wasExitCalled());
assertEquals("vm", c.getListFilter());
}
/** Test list with long name and missing parameter */
public final void testList_Long_MissingParam() {
MockSdkCommandLine c = new MockSdkCommandLine();
assertEquals("all", c.getListFilter());
c.parseArgs(new String[] { "list", "--filter" });
assertTrue(c.wasHelpCalled());
assertTrue(c.wasExitCalled());
assertEquals("all", c.getListFilter());
}
}