Merge "rcp build: don't copy plugin/bin folder"
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
index 0dde05f..594912b 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/VersionCheck.java
@@ -21,6 +21,7 @@
import com.android.ide.eclipse.adt.AdtPlugin.CheckSdkErrorHandler.Solution;
import com.android.ide.eclipse.adt.Messages;
import com.android.sdklib.SdkConstants;
+import com.android.sdklib.internal.repository.packages.FullRevision;
import com.android.sdklib.repository.PkgProps;
import org.osgi.framework.Constants;
@@ -48,7 +49,7 @@
/**
* The minimum version of the SDK Tools that this version of ADT requires.
*/
- private final static int MIN_TOOLS_REV = 17;
+ private final static FullRevision MIN_TOOLS_REV = new FullRevision(17);
/**
* Pattern to get the minimum plugin version supported by the SDK. This is read from
@@ -57,7 +58,7 @@
private final static Pattern sPluginVersionPattern = Pattern.compile(
"^plugin.version=(\\d+)\\.(\\d+)\\.(\\d+).*$"); //$NON-NLS-1$
private final static Pattern sSourcePropPattern = Pattern.compile(
- "^" + PkgProps.PKG_MAJOR_REV + "=(\\d+).*$"); //$NON-NLS-1$
+ "^" + PkgProps.PKG_REVISION + "=(.*)$"); //$NON-NLS-1$
/**
* Checks the plugin and the SDK have compatible versions.
@@ -136,7 +137,7 @@
// now check whether the tools are new enough.
String osTools = osSdkPath + SdkConstants.OS_SDK_TOOLS_FOLDER;
- int toolsRevision = Integer.MAX_VALUE;
+ FullRevision toolsRevision = new FullRevision(Integer.MAX_VALUE);
try {
reader = new FileReader(osTools + SdkConstants.FN_SOURCE_PROP);
BufferedReader bReader = new BufferedReader(reader);
@@ -144,7 +145,9 @@
while ((line = bReader.readLine()) != null) {
Matcher m = sSourcePropPattern.matcher(line);
if (m.matches()) {
- toolsRevision = Integer.parseInt(m.group(1));
+ try {
+ toolsRevision = FullRevision.parseRevision(m.group(1));
+ } catch (NumberFormatException ignore) {}
break;
}
}
@@ -163,7 +166,7 @@
}
}
- if (toolsRevision < MIN_TOOLS_REV) {
+ if (toolsRevision.compareTo(MIN_TOOLS_REV) < 0) {
// this is a warning only as we need to parse the SDK to allow updating
// of the tools!
return errorHandler.handleWarning(
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
index 58e156e..3c976b0 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/AndroidXmlEditor.java
@@ -246,6 +246,18 @@
mIgnoreXmlUpdate = ignore;
}
+ /**
+ * Returns whether XML model events are ignored or not. This is the case
+ * when we are deliberately modifying the document in a way which does not
+ * change the semantics (such as formatting), or when we have already
+ * directly updated the model ourselves.
+ *
+ * @return true if XML events should be ignored
+ */
+ public boolean getIgnoreXmlUpdate() {
+ return mIgnoreXmlUpdate;
+ }
+
// ---- Base Class Overrides, Interfaces Implemented ----
@Override
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java
index 325e284..4bc7641 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/LayoutEditorDelegate.java
@@ -487,6 +487,9 @@
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
getEditor().getSite().getSelectionProvider().setSelection(selection);
+ if (getEditor().getIgnoreXmlUpdate()) {
+ return;
+ }
SelectionManager manager =
mGraphicalEditor.getCanvasControl().getSelectionManager();
manager.setSelection(selection);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
index 2da7678..3fda20d 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/DomUtilities.java
@@ -21,6 +21,8 @@
import static com.android.ide.common.layout.LayoutConstants.NEW_ID_PREFIX;
import static org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML.ContentTypeID_XML;
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
import com.android.ide.eclipse.adt.AdtPlugin;
import com.android.ide.eclipse.adt.internal.editors.descriptors.DescriptorsUtils;
import com.android.util.Pair;
@@ -70,7 +72,8 @@
* @param node2 the second node to test
* @return the nearest common parent of the two given nodes
*/
- public static Node getCommonAncestor(Node node1, Node node2) {
+ @Nullable
+ public static Node getCommonAncestor(@NonNull Node node1, @NonNull Node node2) {
while (node2 != null) {
Node current = node1;
while (current != null && current != node2) {
@@ -92,13 +95,14 @@
* @param node the node to search from
* @return all elements in the subtree formed by the node parameter
*/
- public static List<Element> getAllElements(Node node) {
+ @NonNull
+ public static List<Element> getAllElements(@NonNull Node node) {
List<Element> elements = new ArrayList<Element>(64);
addElements(node, elements);
return elements;
}
- private static void addElements(Node node, List<Element> elements) {
+ private static void addElements(@NonNull Node node, @NonNull List<Element> elements) {
if (node instanceof Element) {
elements.add((Element) node);
}
@@ -116,7 +120,7 @@
* @param node the node to test
* @return the depth in the document
*/
- public static int getDepth(Node node) {
+ public static int getDepth(@NonNull Node node) {
int depth = -1;
while (node != null) {
depth++;
@@ -132,7 +136,7 @@
* @param node the node to test for element children
* @return true if the node has one or more element children
*/
- public static boolean hasElementChildren(Node node) {
+ public static boolean hasElementChildren(@NonNull Node node) {
NodeList children = node.getChildNodes();
for (int i = 0, n = children.getLength(); i < n; i++) {
if (children.item(i).getNodeType() == Node.ELEMENT_NODE) {
@@ -151,7 +155,8 @@
* @param offset The offset to look up the node for
* @return The node containing the offset, or null
*/
- public static Node getNode(IDocument document, int offset) {
+ @Nullable
+ public static Node getNode(@NonNull IDocument document, int offset) {
Node node = null;
IModelManager modelManager = StructuredModelManager.getModelManager();
if (modelManager == null) {
@@ -204,7 +209,8 @@
* return the parent. Note that the method can also return null if no
* document or model could be obtained or if the offset is invalid.
*/
- public static Pair<Node, Node> getNodeContext(IDocument document, int offset) {
+ @Nullable
+ public static Pair<Node, Node> getNodeContext(@NonNull IDocument document, int offset) {
Node node = null;
IModelManager modelManager = StructuredModelManager.getModelManager();
if (modelManager == null) {
@@ -283,7 +289,8 @@
* @return the node which surrounds the given offset, or the node adjacent to the offset
* where the side depends on the forward parameter
*/
- public static Node getNode(IDocument document, int offset, boolean forward) {
+ @Nullable
+ public static Node getNode(@NonNull IDocument document, int offset, boolean forward) {
Node node = getNode(document, offset);
if (node instanceof IndexedRegion) {
@@ -318,8 +325,9 @@
* @param endOffset the ending offset of the range
* @return a pair of begin+end elements, or null
*/
- public static Pair<Element, Element> getElementRange(IDocument document, int beginOffset,
- int endOffset) {
+ @Nullable
+ public static Pair<Element, Element> getElementRange(@NonNull IDocument document,
+ int beginOffset, int endOffset) {
Element beginElement = null;
Element endElement = null;
Node beginNode = getNode(document, beginOffset, true);
@@ -383,7 +391,8 @@
* @param node the starting node
* @return the next sibling element, or null
*/
- public static Element getNextElement(Node node) {
+ @Nullable
+ public static Element getNextElement(@NonNull Node node) {
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
node = node.getNextSibling();
}
@@ -397,7 +406,8 @@
* @param node the starting node
* @return the previous sibling element, or null
*/
- public static Element getPreviousElement(Node node) {
+ @Nullable
+ public static Element getPreviousElement(@NonNull Node node) {
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
node = node.getPreviousSibling();
}
@@ -411,7 +421,8 @@
* @param node the starting node
* @return the closest parent element, or null
*/
- public static Element getParentElement(Node node) {
+ @Nullable
+ public static Element getParentElement(@NonNull Node node) {
while (node != null && node.getNodeType() != Node.ELEMENT_NODE) {
node = node.getParentNode();
}
@@ -426,7 +437,8 @@
* @param attrValue the value to be escaped
* @return the escaped value
*/
- public static String toXmlAttributeValue(String attrValue) {
+ @NonNull
+ public static String toXmlAttributeValue(@NonNull String attrValue) {
for (int i = 0, n = attrValue.length(); i < n; i++) {
char c = attrValue.charAt(i);
if (c == '"' || c == '\'' || c == '<' || c == '&') {
@@ -446,7 +458,8 @@
* @param sb the string builder
* @param attrValue the attribute value to be appended and escaped
*/
- public static void appendXmlAttributeValue(StringBuilder sb, String attrValue) {
+ public static void appendXmlAttributeValue(@NonNull StringBuilder sb,
+ @NonNull String attrValue) {
int n = attrValue.length();
// &, ", ' and < are illegal in attributes; see http://www.w3.org/TR/REC-xml/#NT-AttValue
// (' legal in a " string and " is legal in a ' string but here we'll stay on the safe
@@ -474,7 +487,7 @@
* @param sb the string builder
* @param textValue the text value to be appended and escaped
*/
- public static void appendXmlTextValue(StringBuilder sb, String textValue) {
+ public static void appendXmlTextValue(@NonNull StringBuilder sb, @NonNull String textValue) {
for (int i = 0, n = textValue.length(); i < n; i++) {
char c = textValue.charAt(i);
if (c == '<') {
@@ -488,7 +501,7 @@
}
/** Utility used by {@link #getFreeWidgetId(Element)} */
- private static void addLowercaseIds(Element root, Set<String> seen) {
+ private static void addLowercaseIds(@NonNull Element root, @NonNull Set<String> seen) {
if (root.hasAttributeNS(ANDROID_URI, ATTR_ID)) {
String id = root.getAttributeNS(ANDROID_URI, ATTR_ID);
if (id.startsWith(NEW_ID_PREFIX)) {
@@ -514,7 +527,10 @@
* @return a unique id, never null, which does not include the {@code @id/} prefix
* @see DescriptorsUtils#getFreeWidgetId
*/
- public static String getFreeWidgetId(Element element, Set<String> reserved, String prefix) {
+ public static String getFreeWidgetId(
+ @NonNull Element element,
+ @Nullable Set<String> reserved,
+ @Nullable String prefix) {
Set<String> ids = new HashSet<String>();
if (reserved != null) {
for (String id : reserved) {
@@ -545,7 +561,8 @@
* @param element the parent element
* @return a list of child elements, possibly empty but never null
*/
- public static List<Element> getChildren(Element element) {
+ @NonNull
+ public static List<Element> getChildren(@NonNull Element element) {
// Convenience to avoid lots of ugly DOM access casting
NodeList children = element.getChildNodes();
// An iterator would have been more natural (to directly drive the child list
@@ -568,7 +585,7 @@
* @param elements the elements to be tested
* @return true if the elements are contiguous siblings with no gaps
*/
- public static boolean isContiguous(List<Element> elements) {
+ public static boolean isContiguous(@NonNull List<Element> elements) {
if (elements.size() > 1) {
// All elements must be siblings (e.g. same parent)
Node parent = elements.get(0).getParentNode();
@@ -621,7 +638,7 @@
* @param element2 the second element to compare
* @return true if the two element hierarchies are logically equal
*/
- public static boolean isEquivalent(Element element1, Element element2) {
+ public static boolean isEquivalent(@Nullable Element element1, @Nullable Element element2) {
if (element1 == null || element2 == null) {
return false;
}
@@ -713,7 +730,8 @@
* @param document the document to search for an equivalent element in
* @return an equivalent element, or null
*/
- public static Element findCorresponding(Element element, Document document) {
+ @Nullable
+ public static Element findCorresponding(@NonNull Element element, @NonNull Document document) {
// Make sure the method is called correctly -- the element is for a different
// document than the one we are searching
assert element.getOwnerDocument() != document;
@@ -736,7 +754,8 @@
}
/** Helper method for {@link #findCorresponding(Element, Document)} */
- private static Element findCorresponding(Element element, String targetId) {
+ @Nullable
+ private static Element findCorresponding(@NonNull Element element, @NonNull String targetId) {
String id = element.getAttributeNS(ANDROID_URI, ATTR_ID);
if (id != null) { // Work around DOM bug
if (id.equals(targetId)) {
@@ -772,7 +791,8 @@
* @param xml the XML content to be parsed (must be well formed)
* @return the DOM document, or null
*/
- public static Document parseStructuredDocument(String xml) {
+ @Nullable
+ public static Document parseStructuredDocument(@NonNull String xml) {
IStructuredModel model = createStructuredModel(xml);
if (model instanceof IDOMModel) {
IDOMModel domModel = (IDOMModel) model;
@@ -788,7 +808,8 @@
* @param xml the XML content to be parsed (must be well formed)
* @return the structured model
*/
- public static IStructuredModel createStructuredModel(String xml) {
+ @Nullable
+ public static IStructuredModel createStructuredModel(@NonNull String xml) {
IStructuredModel model = createEmptyModel();
IStructuredDocument document = model.getStructuredDocument();
model.aboutToChangeModel();
@@ -803,6 +824,7 @@
*
* @return a new Eclipse XML model
*/
+ @NonNull
public static IStructuredModel createEmptyModel() {
IModelManager modelManager = StructuredModelManager.getModelManager();
return modelManager.createUnManagedStructuredModelFor(ContentTypeID_XML);
@@ -813,6 +835,7 @@
*
* @return an empty Eclipse XML document
*/
+ @Nullable
public static Document createEmptyDocument() {
IStructuredModel model = createEmptyModel();
if (model instanceof IDOMModel) {
@@ -832,7 +855,8 @@
* silently return null
* @return the DOM document, or null
*/
- public static Document parseDocument(String xml, boolean logParserErrors) {
+ @Nullable
+ public static Document parseDocument(@NonNull String xml, boolean logParserErrors) {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
InputSource is = new InputSource(new StringReader(xml));
factory.setNamespaceAware(true);
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutActionBar.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutActionBar.java
index 8f950b9..49157a7 100644
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutActionBar.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutActionBar.java
@@ -18,6 +18,7 @@
import static com.android.ide.common.layout.LayoutConstants.ANDROID_URI;
import static com.android.ide.common.layout.LayoutConstants.ATTR_ID;
+import com.android.annotations.NonNull;
import com.android.ide.common.api.INode;
import com.android.ide.common.api.RuleAction;
import com.android.ide.common.api.RuleAction.Choices;
@@ -31,6 +32,7 @@
import com.android.ide.eclipse.adt.internal.lint.EclipseLintClient;
import com.android.ide.eclipse.adt.internal.preferences.AdtPrefs;
import com.android.sdkuilib.internal.widgets.ResolutionChooserDialog;
+import com.google.common.base.Strings;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.window.Window;
@@ -72,6 +74,7 @@
private ToolItem mZoomInButton;
private ToolItem mZoomFitButton;
private ToolItem mLintButton;
+ private List<RuleAction> mPrevActions;
/**
* Creates a new {@link LayoutActionBar} and adds it to the given parent.
@@ -98,14 +101,14 @@
mLintToolBar.setLayoutData(lintData);
}
+ @Override
+ public void dispose() {
+ super.dispose();
+ mPrevActions = null;
+ }
+
/** Updates the layout contents based on the current selection */
void updateSelection() {
- // Get rid of any previous children
- for (ToolItem c : mLayoutToolBar.getItems()) {
- c.dispose();
- }
- mLayoutToolBar.pack();
-
NodeProxy parent = null;
LayoutCanvas canvas = mEditor.getCanvasControl();
SelectionManager selectionManager = canvas.getSelectionManager();
@@ -167,12 +170,94 @@
}
}
- addActions(actions, index, label);
+ if (!updateActions(actions)) {
+ updateToolbar(actions, index, label);
+ }
+ mPrevActions = actions;
+ }
+ /** Update the toolbar widgets */
+ private void updateToolbar(final List<RuleAction> actions, final int labelIndex,
+ final String label) {
+ if (mLayoutToolBar == null || mLayoutToolBar.isDisposed()) {
+ return;
+ }
+ for (ToolItem c : mLayoutToolBar.getItems()) {
+ c.dispose();
+ }
+ mLayoutToolBar.pack();
+ addActions(actions, labelIndex, label);
mLayoutToolBar.pack();
mLayoutToolBar.layout();
}
+ /**
+ * Attempts to update the existing toolbar actions, if the action list is
+ * similar to the current list. Returns false if this cannot be done and the
+ * contents must be replaced.
+ */
+ private boolean updateActions(@NonNull List<RuleAction> actions) {
+ List<RuleAction> before = mPrevActions;
+ List<RuleAction> after = actions;
+
+ if (before == null) {
+ return false;
+ }
+
+ if (!before.equals(after) || after.size() > mLayoutToolBar.getItemCount()) {
+ return false;
+ }
+
+ int actionIndex = 0;
+ for (int i = 0, max = mLayoutToolBar.getItemCount(); i < max; i++) {
+ ToolItem item = mLayoutToolBar.getItem(i);
+ int style = item.getStyle();
+ Object data = item.getData();
+ if (data != null) {
+ // One action can result in multiple toolbar items (e.g. a choice action
+ // can result in multiple radio buttons), so we've have to replace all of
+ // them with the corresponding new action
+ RuleAction prevAction = before.get(actionIndex);
+ while (prevAction != data) {
+ actionIndex++;
+ if (actionIndex == before.size()) {
+ return false;
+ }
+ prevAction = before.get(actionIndex);
+ if (prevAction == data) {
+ break;
+ } else if (!(prevAction instanceof RuleAction.Separator)) {
+ return false;
+ }
+ }
+ RuleAction newAction = after.get(actionIndex);
+ assert newAction.equals(prevAction); // Maybe I can do this lazily instead?
+
+ // Update action binding to the new action
+ item.setData(newAction);
+
+ // Sync button states: the checked state is not considered part of
+ // RuleAction equality
+ if ((style & SWT.CHECK) != 0) {
+ assert newAction instanceof Toggle;
+ Toggle toggle = (Toggle) newAction;
+ item.setSelection(toggle.isChecked());
+ } else if ((style & SWT.RADIO) != 0) {
+ assert newAction instanceof Choices;
+ Choices choices = (Choices) newAction;
+ String current = choices.getCurrent();
+ String id = (String) item.getData(ATTR_ID);
+ boolean selected = Strings.nullToEmpty(current).equals(id);
+ item.setSelection(selected);
+ }
+ } else {
+ assert (style & SWT.SEPARATOR) != 0;
+ }
+ }
+
+ return true;
+ }
+
private void addActions(List<RuleAction> actions, int labelIndex, String label) {
if (actions.size() > 0) {
// Flag used to indicate that if there are any actions -after- this, it
@@ -226,7 +311,7 @@
}
}
- private void addToggle(final Toggle toggle) {
+ private void addToggle(Toggle toggle) {
final ToolItem button = new ToolItem(mLayoutToolBar, SWT.CHECK);
URL iconUrl = toggle.getIconUrl();
@@ -237,10 +322,12 @@
} else {
button.setText(title);
}
+ button.setData(toggle);
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
+ Toggle toggle = (Toggle) button.getData();
toggle.getCallback().action(toggle, getSelectedNodes(),
toggle.getId(), button.getSelection());
updateSelection();
@@ -263,7 +350,7 @@
}
- private void addPlainAction(final RuleAction menuAction) {
+ private void addPlainAction(RuleAction menuAction) {
final ToolItem button = new ToolItem(mLayoutToolBar, SWT.PUSH);
URL iconUrl = menuAction.getIconUrl();
@@ -274,10 +361,12 @@
} else {
button.setText(title);
}
+ button.setData(menuAction);
button.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
+ RuleAction menuAction = (RuleAction) button.getData();
menuAction.getCallback().action(menuAction, getSelectedNodes(), menuAction.getId(),
false);
updateSelection();
@@ -285,7 +374,7 @@
});
}
- private void addRadio(final RuleAction.Choices choices) {
+ private void addRadio(RuleAction.Choices choices) {
List<URL> icons = choices.getIconUrls();
List<String> titles = choices.getTitles();
List<String> ids = choices.getIds();
@@ -301,10 +390,13 @@
final ToolItem item = new ToolItem(mLayoutToolBar, SWT.RADIO);
item.setToolTipText(title);
item.setImage(IconFactory.getInstance().getIcon(iconUrl));
+ item.setData(choices);
+ item.setData(ATTR_ID, id);
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (item.getSelection()) {
+ RuleAction.Choices choices = (Choices) item.getData();
choices.getCallback().action(choices, getSelectedNodes(), id, null);
updateSelection();
}
@@ -317,7 +409,7 @@
}
}
- private void addDropdown(final RuleAction.Choices choices) {
+ private void addDropdown(RuleAction.Choices choices) {
final ToolItem combo = new ToolItem(mLayoutToolBar, SWT.DROP_DOWN);
URL iconUrl = choices.getIconUrl();
if (iconUrl != null) {
@@ -326,6 +418,7 @@
} else {
combo.setText(choices.getTitle());
}
+ combo.setData(choices);
Listener menuListener = new Listener() {
@Override
@@ -335,7 +428,7 @@
point = combo.getDisplay().map(mLayoutToolBar, null, point);
Menu menu = new Menu(mLayoutToolBar.getShell(), SWT.POP_UP);
-
+ RuleAction.Choices choices = (Choices) combo.getData();
List<URL> icons = choices.getIconUrls();
List<String> titles = choices.getTitles();
List<String> ids = choices.getIds();
@@ -360,6 +453,7 @@
item.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
+ RuleAction.Choices choices = (Choices) combo.getData();
choices.getCallback().action(choices, getSelectedNodes(), id, null);
updateSelection();
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvasViewer.java b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvasViewer.java
index bef4fba..e349a1c 100755
--- a/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvasViewer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.adt/src/com/android/ide/eclipse/adt/internal/editors/layout/gle2/LayoutCanvasViewer.java
@@ -114,6 +114,9 @@
*/
@Override
public void setSelection(ISelection selection, boolean reveal) {
+ if (mEditorDelegate.getEditor().getIgnoreXmlUpdate()) {
+ return;
+ }
mCanvas.getSelectionManager().setSelection(selection);
}
diff --git a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java
index fa73dbc..cce470f 100644
--- a/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java
+++ b/eclipse/plugins/com.android.ide.eclipse.ddms/src/com/android/ide/eclipse/ddms/preferences/PreferenceInitializer.java
@@ -23,6 +23,8 @@
import com.android.ddmlib.DdmPreferences;
import com.android.ddmuilib.DdmUiPreferences;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.SWT;
@@ -106,7 +108,15 @@
store.setDefault(ATTR_LOGCAT_FONT,
new FontData("Courier", 10, SWT.NORMAL).toString()); //$NON-NLS-1$
+ // When obtaining hprof files from the device, default to opening the file
+ // only if there is a registered content type for the hprof extension.
store.setDefault(ATTR_HPROF_ACTION, HProfHandler.ACTION_SAVE);
+ for (IContentType contentType: Platform.getContentTypeManager().getAllContentTypes()) {
+ if (contentType.isAssociatedWith(HProfHandler.DOT_HPROF)) {
+ store.setDefault(ATTR_HPROF_ACTION, HProfHandler.ACTION_OPEN);
+ break;
+ }
+ }
store.setDefault(ATTR_TIME_OUT, DdmPreferences.DEFAULT_TIMEOUT);
diff --git a/monitor/Android.mk b/monitor/Android.mk
index a0926a7..2661429 100644
--- a/monitor/Android.mk
+++ b/monitor/Android.mk
@@ -1,7 +1,7 @@
# Copyright 2012 The Android Open Source Project
# Expose the Monitor RCP only for the SDK builds.
-ifneq (,$(is_sdk_build)$(filter sdk,$(TARGET_PRODUCT)))
+ifneq (,$(is_sdk_build)$(filter sdk sdk_x86,$(TARGET_PRODUCT)))
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java
index 996aee4..38d3bbb 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/AndroidVersion.java
@@ -16,6 +16,7 @@
package com.android.sdklib;
+import com.android.annotations.Nullable;
import com.android.sdklib.repository.PkgProps;
import java.util.Properties;
@@ -61,7 +62,7 @@
*/
public AndroidVersion(int apiLevel, String codename) {
mApiLevel = apiLevel;
- mCodename = codename;
+ mCodename = sanitizeCodename(codename);
}
/**
@@ -73,11 +74,12 @@
public AndroidVersion(Properties properties, int defaultApiLevel, String defaultCodeName) {
if (properties == null) {
mApiLevel = defaultApiLevel;
- mCodename = defaultCodeName;
+ mCodename = sanitizeCodename(defaultCodeName);
} else {
mApiLevel = Integer.parseInt(properties.getProperty(PkgProps.VERSION_API_LEVEL,
- Integer.toString(defaultApiLevel)));
- mCodename = properties.getProperty(PkgProps.VERSION_CODENAME, defaultCodeName);
+ Integer.toString(defaultApiLevel)));
+ mCodename = sanitizeCodename(
+ properties.getProperty(PkgProps.VERSION_CODENAME, defaultCodeName));
}
}
@@ -95,7 +97,8 @@
if (apiLevel != null) {
try {
mApiLevel = Integer.parseInt(apiLevel);
- mCodename = properties.getProperty(PkgProps.VERSION_CODENAME, null/*defaultValue*/);
+ mCodename = sanitizeCodename(properties.getProperty(PkgProps.VERSION_CODENAME,
+ null/*defaultValue*/));
return;
} catch (NumberFormatException e) {
error = e;
@@ -298,4 +301,25 @@
public boolean isGreaterOrEqualThan(int api) {
return compareTo(api, null /*codename*/) >= 0;
}
+
+ /**
+ * Sanitizes the codename string according to the following rules:
+ * - A codename should be {@code null} for a release version or it should be a non-empty
+ * string for an actual preview.
+ * - In input, spacing is trimmed since it is irrelevant.
+ * - An empty string or the special codename "REL" means a release version
+ * and is converted to {@code null}.
+ *
+ * @param codename A possible-null codename.
+ * @return Null for a release version or a non-empty codename.
+ */
+ private @Nullable String sanitizeCodename(@Nullable String codename) {
+ if (codename != null) {
+ codename = codename.trim();
+ if (codename.length() == 0 || SdkConstants.CODENAME_RELEASE.equals(codename)) {
+ codename = null;
+ }
+ }
+ return codename;
+ }
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
index 02688c0..ac8de23 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
@@ -53,8 +53,7 @@
*
* @param sdkOsPath the root folder of the SDK
* @param platformOSPath the root folder of the platform component
- * @param apiLevel the API Level
- * @param codeName the codename. can be null.
+ * @param apiVersion the API Level + codename.
* @param versionName the version name of the platform.
* @param revision the revision of the platform component.
* @param layoutlibVersion The {@link LayoutlibVersion}. May be null.
@@ -65,8 +64,7 @@
PlatformTarget(
String sdkOsPath,
String platformOSPath,
- int apiLevel,
- String codeName,
+ AndroidVersion apiVersion,
String versionName,
int revision,
LayoutlibVersion layoutlibVersion,
@@ -77,7 +75,7 @@
}
mRootFolderOsPath = platformOSPath;
mProperties = Collections.unmodifiableMap(properties);
- mVersion = new AndroidVersion(apiLevel, codeName);
+ mVersion = apiVersion;
mVersionName = versionName;
mRevision = revision;
mLayoutlibVersion = layoutlibVersion;
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
index 6e6c657..b5ff9da 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkConstants.java
@@ -263,6 +263,9 @@
/** Name of the cache folder in the $HOME/.android. */
public final static String FD_CACHE = "cache"; //$NON-NLS-1$
+ /** API codename of a release (non preview) system image or platform. **/
+ public final static String CODENAME_RELEASE = "REL"; //$NON-NLS-1$
+
/** Namespace for the resource XML, i.e. "http://schemas.android.com/apk/res/android" */
public final static String NS_RESOURCES =
"http://schemas.android.com/apk/res/android"; //$NON-NLS-1$
@@ -377,7 +380,6 @@
FN_FRAMEWORK_RENDERSCRIPT + File.separator + FN_FRAMEWORK_INCLUDE_CLANG;
/* Folder paths relative to a addon folder */
-
/** Path of the images directory relative to a folder folder.
* This is an OS path, ending with a separator. */
public final static String OS_ADDON_LIBS_FOLDER = FD_ADDON_LIBS + File.separator;
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
index a786728..5c570ce 100644
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/SdkManager.java
@@ -437,12 +437,10 @@
}
}
- // codename (optional)
- String apiCodename = platformProp.get(PROP_VERSION_CODENAME);
- if (apiCodename != null && apiCodename.equals("REL")) {
- apiCodename = null; // REL means it's a release version and therefore the
- // codename is irrelevant at this point.
- }
+ // Codename must be either null or a platform codename.
+ // REL means it's a release version and therefore the codename should be null.
+ AndroidVersion apiVersion =
+ new AndroidVersion(apiNumber, platformProp.get(PROP_VERSION_CODENAME));
// version string
String apiName = platformProp.get(PkgProps.PLATFORM_VERSION);
@@ -463,7 +461,7 @@
int revision = 1;
LayoutlibVersion layoutlibVersion = null;
try {
- revision = Integer.parseInt(platformProp.get(PkgProps.PKG_MAJOR_REV));
+ revision = Integer.parseInt(platformProp.get(PkgProps.PKG_REVISION));
} catch (NumberFormatException e) {
// do nothing, we'll keep the default value of 1.
}
@@ -489,14 +487,13 @@
}
ISystemImage[] systemImages =
- getPlatformSystemImages(sdkOsPath, platformFolder, apiNumber, apiCodename);
+ getPlatformSystemImages(sdkOsPath, platformFolder, apiVersion);
// create the target.
PlatformTarget target = new PlatformTarget(
sdkOsPath,
platformFolder.getAbsolutePath(),
- apiNumber,
- apiCodename,
+ apiVersion,
apiName,
revision,
layoutlibVersion,
@@ -574,16 +571,14 @@
*
* @param sdkOsPath The path to the SDK.
* @param root Root of the platform target being loaded.
- * @param apiNumber API level of platform being loaded
- * @param apiCodename Optional codename of platform being loaded
+ * @param version API level + codename of platform being loaded.
* @return an array of ISystemImage containing all the system images for the target.
* The list can be empty.
*/
private static ISystemImage[] getPlatformSystemImages(
String sdkOsPath,
File root,
- int apiNumber,
- String apiCodename) {
+ AndroidVersion version) {
Set<ISystemImage> found = new TreeSet<ISystemImage>();
Set<String> abiFound = new HashSet<String>();
@@ -592,8 +587,6 @@
// The actual directory names are irrelevant.
// If we find multiple occurrences of the same platform/abi, the first one read wins.
- AndroidVersion version = new AndroidVersion(apiNumber, apiCodename);
-
File[] firstLevelFiles = new File(sdkOsPath, SdkConstants.FD_SYSTEM_IMAGES).listFiles();
if (firstLevelFiles != null) {
for (File firstLevel : firstLevelFiles) {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/FullRevision.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/FullRevision.java
index a90fa0a..40235c2 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/FullRevision.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/FullRevision.java
@@ -16,6 +16,11 @@
package com.android.sdklib.internal.repository.packages;
+import com.android.annotations.NonNull;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
/**
* Package multi-part revision number composed of a tuple
@@ -32,6 +37,10 @@
public static final int IMPLICIT_MICRO_REV = 0;
public static final int NOT_A_PREVIEW = 0;
+ private final static Pattern FULL_REVISION_PATTERN =
+ // 1=major 2=minor 3=micro 4=preview
+ Pattern.compile("\\s*([0-9]+)(?:\\.([0-9]+)(?:\\.([0-9]+))?)?\\s*(?:rc([0-9]+))?\\s*");
+
private final int mMajor;
private final int mMinor;
private final int mMicro;
@@ -73,6 +82,52 @@
}
/**
+ * Parses a string of format "major.minor.micro rcPreview" and returns
+ * a new {@link FullRevision} for it. All the fields except major are
+ * optional.
+ * <p/>
+ * The parsing is equivalent to the pseudo-BNF/regexp:
+ * <pre>
+ * Major/Minor/Micro/Preview := [0-9]+
+ * Revision := Major ('.' Minor ('.' Micro)? )? \s* ('rc'Preview)?
+ * </pre>
+ *
+ * @param revision A non-null revision to parse.
+ * @return A new non-null {@link FullRevision}.
+ * @throws NumberFormatException if the parsing failed.
+ */
+ public static @NonNull FullRevision parseRevision(@NonNull String revision)
+ throws NumberFormatException {
+
+ if (revision == null) {
+ throw new NumberFormatException("revision is <null>"); //$NON-NLS-1$
+ }
+
+ Throwable cause = null;
+ try {
+ Matcher m = FULL_REVISION_PATTERN.matcher(revision);
+ if (m != null && m.matches()) {
+ int major = Integer.parseInt(m.group(1));
+ String s = m.group(2);
+ int minor = s == null ? IMPLICIT_MINOR_REV : Integer.parseInt(s);
+ s = m.group(3);
+ int micro = s == null ? IMPLICIT_MICRO_REV : Integer.parseInt(s);
+ s = m.group(4);
+ int preview = s == null ? NOT_A_PREVIEW : Integer.parseInt(s);
+
+ return new FullRevision(major, minor, micro, preview);
+ }
+ } catch (Throwable t) {
+ cause = t;
+ }
+
+ NumberFormatException n = new NumberFormatException(
+ "Invalid full revision: " + revision); //$NON-NLS-1$
+ n.initCause(cause);
+ throw n;
+ }
+
+ /**
* Returns the version in a fixed format major.minor.micro
* with an optional "rc preview#". For example it would
* return "18.0.0", "18.1.0" or "18.1.2 rc5".
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/FullRevisionPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/FullRevisionPackage.java
index 10c4ce0..6028873 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/FullRevisionPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/FullRevisionPackage.java
@@ -102,12 +102,19 @@
super(source, props, revision, license, description, descUrl,
archiveOs, archiveArch, archiveOsPath);
- int major = getPropertyInt(props, PkgProps.PKG_MAJOR_REV,revision);
- int minor = getPropertyInt(props, PkgProps.PKG_MINOR_REV, FullRevision.IMPLICIT_MINOR_REV);
- int micro = getPropertyInt(props, PkgProps.PKG_MICRO_REV, FullRevision.IMPLICIT_MINOR_REV);
- int preview = getPropertyInt(props, PkgProps.PKG_PREVIEW_REV, FullRevision.NOT_A_PREVIEW);
+ String revStr = getProperty(props, PkgProps.PKG_REVISION, null);
- mPreviewVersion = new FullRevision(major, minor, micro, preview);
+ FullRevision rev = null;
+ if (revStr != null) {
+ try {
+ rev = FullRevision.parseRevision(revStr);
+ } catch (NumberFormatException ignore) {}
+ }
+ if (rev == null) {
+ rev = new FullRevision(revision);
+ }
+
+ mPreviewVersion = rev;
}
@Override
@@ -118,11 +125,7 @@
@Override
public void saveProperties(Properties props) {
super.saveProperties(props);
-
- props.setProperty(PkgProps.PKG_MAJOR_REV, Integer.toString(mPreviewVersion.getMajor()));
- props.setProperty(PkgProps.PKG_MINOR_REV, Integer.toString(mPreviewVersion.getMinor()));
- props.setProperty(PkgProps.PKG_MICRO_REV, Integer.toString(mPreviewVersion.getMicro()));
- props.setProperty(PkgProps.PKG_PREVIEW_REV, Integer.toString(mPreviewVersion.getPreview()));
+ props.setProperty(PkgProps.PKG_REVISION, mPreviewVersion.toString());
}
@Override
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/MajorRevision.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/MajorRevision.java
index 2678b1f..9ca9e22 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/MajorRevision.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/MajorRevision.java
@@ -16,6 +16,8 @@
package com.android.sdklib.internal.repository.packages;
+import com.android.annotations.NonNull;
+
/**
* Package revision number composed of a <em>single</em> major revision.
@@ -34,4 +36,21 @@
public String toString() {
return super.toShortString();
}
+
+ /**
+ * Parses a single-integer string and returns a new {@link MajorRevision} for it.
+ *
+ * @param revision A non-null revision to parse.
+ * @return A new non-null {@link MajorRevision}.
+ * @throws NumberFormatException if the parsing failed.
+ */
+ public static @NonNull MajorRevision parseRevision(@NonNull String revision)
+ throws NumberFormatException {
+
+ if (revision == null) {
+ throw new NumberFormatException("revision is <null>"); //$NON-NLS-1$
+ }
+
+ return new MajorRevision(Integer.parseInt(revision.trim()));
+ }
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/MajorRevisionPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/MajorRevisionPackage.java
index 7e61e5f..1348bb9 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/MajorRevisionPackage.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/packages/MajorRevisionPackage.java
@@ -77,7 +77,19 @@
super(source, props, revision, license, description, descUrl,
archiveOs, archiveArch, archiveOsPath);
- mRevision = new MajorRevision(getPropertyInt(props, PkgProps.PKG_MAJOR_REV, revision));
+ String revStr = getProperty(props, PkgProps.PKG_REVISION, null);
+
+ MajorRevision rev = null;
+ if (revStr != null) {
+ try {
+ rev = MajorRevision.parseRevision(revStr);
+ } catch (NumberFormatException ignore) {}
+ }
+ if (rev == null) {
+ rev = new MajorRevision(revision);
+ }
+
+ mRevision = rev;
}
/**
@@ -93,7 +105,7 @@
@Override
public void saveProperties(Properties props) {
super.saveProperties(props);
- props.setProperty(PkgProps.PKG_MAJOR_REV, Integer.toString(mRevision.getMajor()));
+ props.setProperty(PkgProps.PKG_REVISION, mRevision.toString());
}
@Override
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/PkgProps.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/PkgProps.java
index 4406b42..571a4a6 100755
--- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/PkgProps.java
+++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/PkgProps.java
@@ -29,6 +29,7 @@
public class PkgProps {
// Base Package
+ public static final String PKG_REVISION = "Pkg.Revision"; //$NON-NLS-1$
public static final String PKG_LICENSE = "Pkg.License"; //$NON-NLS-1$
public static final String PKG_DESC = "Pkg.Desc"; //$NON-NLS-1$
public static final String PKG_DESC_URL = "Pkg.DescUrl"; //$NON-NLS-1$
@@ -37,13 +38,6 @@
public static final String PKG_SOURCE_URL = "Pkg.SourceUrl"; //$NON-NLS-1$
public static final String PKG_OBSOLETE = "Pkg.Obsolete"; //$NON-NLS-1$
- // FullRevision
- // Note that MajorRev keeps the legacy "Pkg.Revision" property name for legacy compatibility.
- public static final String PKG_MAJOR_REV = "Pkg.Revision"; //$NON-NLS-1$
- public static final String PKG_MINOR_REV = "Pkg.MinorRev"; //$NON-NLS-1$
- public static final String PKG_MICRO_REV = "Pkg.MicroRev"; //$NON-NLS-1$
- public static final String PKG_PREVIEW_REV = "Pkg.PreviewRev"; //$NON-NLS-1$
-
// AndroidVersion
public static final String VERSION_API_LEVEL = "AndroidVersion.ApiLevel";//$NON-NLS-1$
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/AndroidVersionTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/AndroidVersionTest.java
new file mode 100755
index 0000000..5270bd1
--- /dev/null
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/AndroidVersionTest.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2012 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.sdklib;
+
+import junit.framework.TestCase;
+
+/**
+ * Unit tests for {@link AndroidVersion}.
+ */
+public class AndroidVersionTest extends TestCase {
+
+ public final void testAndroidVersion() {
+ AndroidVersion v = new AndroidVersion(1, " CODENAME ");
+ assertEquals(1, v.getApiLevel());
+ assertEquals("CODENAME", v.getApiString());
+ assertTrue(v.isPreview());
+ assertEquals("CODENAME", v.getCodename());
+ assertEquals("CODENAME".hashCode(), v.hashCode());
+ assertEquals("API 1, CODENAME preview", v.toString());
+
+ v = new AndroidVersion(15, "REL");
+ assertEquals(15, v.getApiLevel());
+ assertEquals("15", v.getApiString());
+ assertFalse(v.isPreview());
+ assertNull(v.getCodename());
+ assertTrue(v.equals(15));
+ assertEquals(15, v.hashCode());
+ assertEquals("API 15", v.toString());
+
+ v = new AndroidVersion(15, null);
+ assertEquals(15, v.getApiLevel());
+ assertEquals("15", v.getApiString());
+ assertFalse(v.isPreview());
+ assertNull(v.getCodename());
+ assertTrue(v.equals(15));
+ assertEquals(15, v.hashCode());
+ assertEquals("API 15", v.toString());
+
+ // An empty codename is like a null codename
+ v = new AndroidVersion(15, " ");
+ assertFalse(v.isPreview());
+ assertNull(v.getCodename());
+ assertEquals("15", v.getApiString());
+
+ v = new AndroidVersion(15, "");
+ assertFalse(v.isPreview());
+ assertNull(v.getCodename());
+ assertEquals("15", v.getApiString());
+
+ assertTrue(v.isGreaterOrEqualThan(0));
+ assertTrue(v.isGreaterOrEqualThan(14));
+ assertTrue(v.isGreaterOrEqualThan(15));
+ assertFalse(v.isGreaterOrEqualThan(16));
+ assertFalse(v.isGreaterOrEqualThan(Integer.MAX_VALUE));
+ }
+
+}
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/FullRevisionPackageTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/FullRevisionPackageTest.java
index d816256..9bf2703 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/FullRevisionPackageTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/FullRevisionPackageTest.java
@@ -34,14 +34,7 @@
public static Properties createProps(FullRevision revision) {
Properties props = new Properties();
if (revision != null) {
- props.setProperty(PkgProps.PKG_MAJOR_REV,
- Integer.toString(revision.getMajor()));
- props.setProperty(PkgProps.PKG_MINOR_REV,
- Integer.toString(revision.getMinor()));
- props.setProperty(PkgProps.PKG_MICRO_REV,
- Integer.toString(revision.getMicro()));
- props.setProperty(PkgProps.PKG_PREVIEW_REV,
- Integer.toString(revision.getPreview()));
+ props.setProperty(PkgProps.PKG_REVISION, revision.toString());
}
return props;
}
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/FullRevisionTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/FullRevisionTest.java
index 97e76bb..d072d05 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/FullRevisionTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/FullRevisionTest.java
@@ -20,16 +20,6 @@
public class FullRevisionTest extends TestCase {
- @Override
- protected void setUp() throws Exception {
- super.setUp();
- }
-
- @Override
- protected void tearDown() throws Exception {
- super.tearDown();
- }
-
public final void testFullRevision() {
FullRevision p = new FullRevision(5);
assertEquals(5, p.getMajor());
@@ -38,7 +28,9 @@
assertEquals(FullRevision.NOT_A_PREVIEW, p.getPreview());
assertFalse (p.isPreview());
assertEquals("5", p.toShortString());
+ assertEquals(p, FullRevision.parseRevision("5"));
assertEquals("5.0.0", p.toString());
+ assertEquals(p, FullRevision.parseRevision("5.0.0"));
p = new FullRevision(5, 0, 0, 6);
assertEquals(5, p.getMajor());
@@ -47,7 +39,9 @@
assertEquals(6, p.getPreview());
assertTrue (p.isPreview());
assertEquals("5 rc6", p.toShortString());
+ assertEquals(p, FullRevision.parseRevision("5 rc6"));
assertEquals("5.0.0 rc6", p.toString());
+ assertEquals(p, FullRevision.parseRevision("5.0.0 rc6"));
p = new FullRevision(6, 7, 0);
assertEquals(6, p.getMajor());
@@ -56,7 +50,9 @@
assertEquals(0, p.getPreview());
assertFalse (p.isPreview());
assertEquals("6.7", p.toShortString());
+ assertEquals(p, FullRevision.parseRevision("6.7"));
assertEquals("6.7.0", p.toString());
+ assertEquals(p, FullRevision.parseRevision("6.7.0"));
p = new FullRevision(10, 11, 12, FullRevision.NOT_A_PREVIEW);
assertEquals(10, p.getMajor());
@@ -66,6 +62,7 @@
assertFalse (p.isPreview());
assertEquals("10.11.12", p.toShortString());
assertEquals("10.11.12", p.toString());
+ assertEquals(p, FullRevision.parseRevision("10.11.12"));
p = new FullRevision(10, 11, 12, 13);
assertEquals(10, p.getMajor());
@@ -75,6 +72,48 @@
assertTrue (p.isPreview());
assertEquals("10.11.12 rc13", p.toShortString());
assertEquals("10.11.12 rc13", p.toString());
+ assertEquals(p, FullRevision.parseRevision("10.11.12 rc13"));
+ assertEquals(p, FullRevision.parseRevision(" 10.11.12 rc13"));
+ assertEquals(p, FullRevision.parseRevision("10.11.12 rc13 "));
+ assertEquals(p, FullRevision.parseRevision(" 10.11.12 rc13 "));
+ }
+
+ public final void testParseError() {
+ String errorMsg = null;
+ try {
+ FullRevision.parseRevision("not a number");
+ fail("FullRevision.parseRevision should thrown NumberFormatException");
+ } catch (NumberFormatException e) {
+ errorMsg = e.getMessage();
+ }
+ assertEquals("Invalid full revision: not a number", errorMsg);
+
+ errorMsg = null;
+ try {
+ FullRevision.parseRevision("5 .6 .7");
+ fail("FullRevision.parseRevision should thrown NumberFormatException");
+ } catch (NumberFormatException e) {
+ errorMsg = e.getMessage();
+ }
+ assertEquals("Invalid full revision: 5 .6 .7", errorMsg);
+
+ errorMsg = null;
+ try {
+ FullRevision.parseRevision("5.0.0 preview 1");
+ fail("FullRevision.parseRevision should thrown NumberFormatException");
+ } catch (NumberFormatException e) {
+ errorMsg = e.getMessage();
+ }
+ assertEquals("Invalid full revision: 5.0.0 preview 1", errorMsg);
+
+ errorMsg = null;
+ try {
+ FullRevision.parseRevision(" 5.1.2 rc 42 ");
+ fail("FullRevision.parseRevision should thrown NumberFormatException");
+ } catch (NumberFormatException e) {
+ errorMsg = e.getMessage();
+ }
+ assertEquals("Invalid full revision: 5.1.2 rc 42 ", errorMsg);
}
public final void testCompareTo() {
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/MajorRevisionTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/MajorRevisionTest.java
new file mode 100755
index 0000000..b77caad
--- /dev/null
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/MajorRevisionTest.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2012 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.sdklib.internal.repository.packages;
+
+import junit.framework.TestCase;
+
+public class MajorRevisionTest extends TestCase {
+
+ public final void testMajorRevision() {
+ MajorRevision p = new MajorRevision(5);
+ assertEquals(5, p.getMajor());
+ assertEquals(FullRevision.IMPLICIT_MINOR_REV, p.getMinor());
+ assertEquals(FullRevision.IMPLICIT_MICRO_REV, p.getMicro());
+ assertEquals(FullRevision.NOT_A_PREVIEW, p.getPreview());
+ assertFalse (p.isPreview());
+ assertEquals("5", p.toShortString());
+ assertEquals(p, MajorRevision.parseRevision("5"));
+ assertEquals("5", p.toString());
+
+ assertEquals(new FullRevision(5, 0, 0, 0), p);
+ }
+
+ public final void testParseError() {
+ String errorMsg = null;
+ try {
+ MajorRevision.parseRevision("5.0.0");
+ fail("MajorRevision.parseRevision should thrown NumberFormatException");
+ } catch (NumberFormatException e) {
+ errorMsg = e.getMessage();
+ }
+ assertEquals("For input string: \"5.0.0\"", errorMsg);
+ }
+
+ public final void testCompareTo() {
+ MajorRevision s4 = new MajorRevision(4);
+ MajorRevision i4 = new MajorRevision(4);
+ FullRevision g5 = new FullRevision (5, 1, 0, 6);
+ MajorRevision y5 = new MajorRevision(5);
+ FullRevision c5 = new FullRevision (5, 1, 0, 6);
+ FullRevision o5 = new FullRevision (5, 0, 0, 7);
+ FullRevision p5 = new FullRevision (5, 1, 0, 0);
+
+ assertEquals(s4, i4); // 4.0.0-0 == 4.0.0-0
+ assertEquals(g5, c5); // 5.1.0-6 == 5.1.0-6
+
+ assertFalse(y5.equals(p5)); // 5.0.0-0 != 5.1.0-0
+ assertFalse(g5.equals(p5)); // 5.1.0-6 != 5.1.0-0
+ assertTrue (s4.compareTo(i4) == 0); // 4.0.0-0 == 4.0.0-0
+ assertTrue (s4.compareTo(y5) < 0); // 4.0.0-0 < 5.0.0-0
+ assertTrue (y5.compareTo(y5) == 0); // 5.0.0-0 == 5.0.0-0
+ assertTrue (y5.compareTo(p5) < 0); // 5.0.0-0 < 5.1.0-0
+ assertTrue (o5.compareTo(y5) < 0); // 5.0.0-7 < 5.0.0-0
+ assertTrue (p5.compareTo(p5) == 0); // 5.1.0-0 == 5.1.0-0
+ assertTrue (c5.compareTo(p5) < 0); // 5.1.0-6 < 5.1.0-0
+ assertTrue (p5.compareTo(c5) > 0); // 5.1.0-0 > 5.1.0-6
+ assertTrue (p5.compareTo(o5) > 0); // 5.1.0-0 > 5.0.0-7
+ assertTrue (c5.compareTo(o5) > 0); // 5.1.0-6 > 5.0.0-7
+ assertTrue (o5.compareTo(o5) == 0); // 5.0.0-7 > 5.0.0-7
+ }
+
+}
diff --git a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/PackageTest.java b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/PackageTest.java
index 6023b5a..f4d7b56 100755
--- a/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/PackageTest.java
+++ b/sdkmanager/libs/sdklib/tests/src/com/android/sdklib/internal/repository/packages/PackageTest.java
@@ -136,7 +136,7 @@
Properties props = new Properties();
// Package properties
- props.setProperty(PkgProps.PKG_MAJOR_REV, "42");
+ props.setProperty(PkgProps.PKG_REVISION, "42");
props.setProperty(PkgProps.PKG_LICENSE, "The License");
props.setProperty(PkgProps.PKG_DESC, "Some description.");
props.setProperty(PkgProps.PKG_DESC_URL, "http://description/url");
diff --git a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AboutDialog.java b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AboutDialog.java
index 6352bdb..35e3420 100755
--- a/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AboutDialog.java
+++ b/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/AboutDialog.java
@@ -107,7 +107,7 @@
}
}
- String revision = p.getProperty(PkgProps.PKG_MAJOR_REV);
+ String revision = p.getProperty(PkgProps.PKG_REVISION);
if (revision != null) {
return revision;
}