OSDN Git Service

SDK Updater: display properties of sources and packages.
authorRaphael <raphael@google.com>
Fri, 22 May 2009 23:51:51 +0000 (16:51 -0700)
committerRaphael <raphael@google.com>
Fri, 22 May 2009 23:51:51 +0000 (16:51 -0700)
tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java
tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java [new file with mode: 0755]
tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java
tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java
tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java
tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java
tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java
tools/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java
tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/RepoSources.java

index eb016cd..becdd57 100755 (executable)
@@ -20,35 +20,110 @@ import com.android.sdklib.repository.SdkRepository;
 \r
 import org.w3c.dom.Node;\r
 \r
+import java.util.ArrayList;\r
+\r
 /**\r
- *\r
+ * Represents an add-on XML node in an SDK repository.\r
  */\r
 public class AddonPackage extends Package {\r
 \r
     private final String mVendor;\r
     private final String mName;\r
-    private final String mApiLevel;\r
+    private final int    mApiLevel;\r
+\r
+    /** An add-on library. */\r
+    public static class Lib {\r
+        private final String mName;\r
+        private final String mDescription;\r
+\r
+        public Lib(String name, String description) {\r
+            mName = name;\r
+            mDescription = description;\r
+        }\r
+\r
+        public String getName() {\r
+            return mName;\r
+        }\r
 \r
-    public AddonPackage(Node packageNode) {\r
+        public String getDescription() {\r
+            return mDescription;\r
+        }\r
+    }\r
+\r
+    private final Lib[] mLibs;\r
+\r
+    /**\r
+     * Creates a new add-on package from the attributes and elements of the given XML node.\r
+     * <p/>\r
+     * This constructor should throw an exception if the package cannot be created.\r
+     */\r
+    AddonPackage(Node packageNode) {\r
         super(packageNode);\r
         mVendor   = getXmlString(packageNode, SdkRepository.NODE_VENDOR);\r
         mName     = getXmlString(packageNode, SdkRepository.NODE_NAME);\r
-        mApiLevel = getXmlString(packageNode, SdkRepository.NODE_API_LEVEL);\r
+        mApiLevel = getXmlInt   (packageNode, SdkRepository.NODE_API_LEVEL, 0);\r
 \r
-        // TODO libs\r
+        mLibs = parseLibs(getFirstChild(packageNode, SdkRepository.NODE_LIBS));\r
     }\r
 \r
+    private Lib[] parseLibs(Node libsNode) {\r
+        ArrayList<Lib> libs = new ArrayList<Lib>();\r
+\r
+        if (libsNode != null) {\r
+            for(Node child = libsNode.getFirstChild();\r
+                child != null;\r
+                child = child.getNextSibling()) {\r
+\r
+                if (child.getNodeType() == Node.ELEMENT_NODE &&\r
+                        SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI()) &&\r
+                        SdkRepository.NODE_LIB.equals(child.getLocalName())) {\r
+                    libs.add(parseLib(child));\r
+                }\r
+            }\r
+        }\r
+\r
+        return libs.toArray(new Lib[libs.size()]);\r
+    }\r
+\r
+    private Lib parseLib(Node libNode) {\r
+        return new Lib(getXmlString(libNode, SdkRepository.NODE_NAME),\r
+                       getXmlString(libNode, SdkRepository.NODE_DESCRIPTION));\r
+    }\r
+\r
+    /** Returns the vendor, a string, for add-on packages. */\r
     public String getVendor() {\r
         return mVendor;\r
     }\r
 \r
+    /** Returns the name, a string, for add-on packages or for libraries. */\r
     public String getName() {\r
         return mName;\r
     }\r
 \r
-    public String getApiLevel() {\r
+    /** Returns the api-level, an int > 0, for platform, add-on and doc packages. */\r
+    public int getApiLevel() {\r
         return mApiLevel;\r
     }\r
 \r
+    /** Returns the libs defined in this add-on. Can be an empty array but not null. */\r
+    public Lib[] getLibs() {\r
+        return mLibs;\r
+    }\r
+\r
+    /** Returns a short description for an {@link IDescription}. */\r
+    @Override\r
+    public String getShortDescription() {\r
+        return String.format("%1$s by %2$s for Android API %3$d",\r
+                getName(),\r
+                getVendor(),\r
+                getApiLevel());\r
+    }\r
 \r
+    /** Returns a long description for an {@link IDescription}. */\r
+    @Override\r
+    public String getLongDescription() {\r
+        return String.format("%1$s.\n%2$s",\r
+                getShortDescription(),\r
+                super.getLongDescription());\r
+    }\r
 }\r
diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
new file mode 100755 (executable)
index 0000000..267c179
--- /dev/null
@@ -0,0 +1,131 @@
+/*\r
+ * Copyright (C) 2009 The Android Open Source Project\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ *      http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package com.android.sdklib.internal.repository;\r
+\r
+\r
+/**\r
+ * A {@link Archive} is the base class for "something" that can be downloaded from\r
+ * the SDK repository -- subclasses include {@link PlatformPackage}, {@link AddonPackage},\r
+ * {@link DocPackage} and {@link ToolPackage}.\r
+ * <p/>\r
+ * A package has some attributes (revision, description) and a list of archives\r
+ * which represent the downloadable bits.\r
+ * <p/>\r
+ * Packages are contained in offered by a {@link RepoSource} (a download site).\r
+ */\r
+public class Archive implements IDescription {\r
+\r
+    /** The checksum type. */\r
+    public enum ChecksumType {\r
+        /** A SHA1 checksum, represented as a 40-hex string. */\r
+        SHA1\r
+    }\r
+\r
+    /** The OS that this archive can be downloaded on. */\r
+    public enum Os {\r
+        ANY,\r
+        LINUX,\r
+        MACOSX,\r
+        WINDOWS\r
+    }\r
+\r
+    /** The Architecture that this archvie can be downloaded on. */\r
+    public enum Arch {\r
+        ANY,\r
+        PPC,\r
+        X86,\r
+        X86_64\r
+    }\r
+\r
+    private final Os     mOs;\r
+    private final Arch   mArch;\r
+    private final String mUrl;\r
+    private final long   mSize;\r
+    private final String mChecksum;\r
+    private final ChecksumType mChecksumType = ChecksumType.SHA1;\r
+\r
+    /**\r
+     * Creates a new archive.\r
+     */\r
+    Archive(Os os, Arch arch, String url, long size, String checksum) {\r
+        mOs = os;\r
+        mArch = arch;\r
+        mUrl = url;\r
+        mSize = size;\r
+        mChecksum = checksum;\r
+    }\r
+\r
+    /** Returns the archive size, an int > 0. */\r
+    public long getSize() {\r
+        return mSize;\r
+    }\r
+\r
+    /** Returns the SHA1 archive checksum, as a 40-char hex. */\r
+    public String getChecksum() {\r
+        return mChecksum;\r
+    }\r
+\r
+    /** Returns the checksum type, always {@link ChecksumType#SHA1} right now. */\r
+    public ChecksumType getChecksumType() {\r
+        return mChecksumType;\r
+    }\r
+\r
+    /** Returns the optional description URL for all packages (platform, add-on, tool, doc).\r
+     * Can be empty but not null. */\r
+    public String getDescUrl() {\r
+        return mUrl;\r
+    }\r
+\r
+    /** Returns the archive {@link Os} enum. */\r
+    public Os getOs() {\r
+        return mOs;\r
+    }\r
+\r
+    /** Returns the archive {@link Arch} enum. */\r
+    public Arch getArch() {\r
+        return mArch;\r
+    }\r
+\r
+    public String getShortDescription() {\r
+        String os = "any OS";\r
+        if (mOs != Os.ANY) {\r
+            os = capitalize(mOs.toString());\r
+        }\r
+\r
+        String arch = "";\r
+        if (mArch != Arch.ANY) {\r
+            arch = mArch.toString().toLowerCase();\r
+        }\r
+\r
+        return String.format("Archive for %1$s %2$s", os, arch);\r
+    }\r
+\r
+    private String capitalize(String string) {\r
+        if (string.length() > 1) {\r
+            return string.substring(0, 1).toUpperCase() + string.substring(1).toLowerCase();\r
+        } else {\r
+            return string.toUpperCase();\r
+        }\r
+    }\r
+\r
+    public String getLongDescription() {\r
+        return String.format("%1$s\nSize: %2$d MiB\nSHA1: %3$s",\r
+                getShortDescription(),\r
+                Math.round(getSize() / (1024*1024)),\r
+                getChecksum());\r
+    }\r
+}\r
index fa71d4f..7601766 100755 (executable)
 \r
 package com.android.sdklib.internal.repository;\r
 \r
+import com.android.sdklib.repository.SdkRepository;\r
+\r
 import org.w3c.dom.Node;\r
 \r
 /**\r
- *\r
+ * Represents a doc XML node in an SDK repository.\r
  */\r
 public class DocPackage extends Package {\r
 \r
-    public DocPackage(Node packageNode) {\r
+    private final int mApiLevel;\r
+\r
+    /**\r
+     * Creates a new doc package from the attributes and elements of the given XML node.\r
+     * <p/>\r
+     * This constructor should throw an exception if the package cannot be created.\r
+     */\r
+    DocPackage(Node packageNode) {\r
         super(packageNode);\r
+        mApiLevel = getXmlInt(packageNode, SdkRepository.NODE_API_LEVEL, 0);\r
+    }\r
+\r
+    /** Returns the api-level, an int > 0, for platform, add-on and doc packages. */\r
+    public int getApiLevel() {\r
+        return mApiLevel;\r
+    }\r
+\r
+    /** Returns a short description for an {@link IDescription}. */\r
+    @Override\r
+    public String getShortDescription() {\r
+        return String.format("Documentation for SDK Android API %1$d", getApiLevel());\r
+    }\r
+\r
+    /** Returns a long description for an {@link IDescription}. */\r
+    @Override\r
+    public String getLongDescription() {\r
+        return String.format("%1$s.\n%2$s",\r
+                getShortDescription(),\r
+                super.getLongDescription());\r
     }\r
 }\r
index 126694a..061eb16 100755 (executable)
 \r
 package com.android.sdklib.internal.repository;\r
 \r
+import com.android.sdklib.internal.repository.Archive.Arch;\r
+import com.android.sdklib.internal.repository.Archive.Os;\r
 import com.android.sdklib.repository.SdkRepository;\r
 \r
 import org.w3c.dom.Node;\r
 \r
+import java.util.ArrayList;\r
+\r
 /**\r
- *\r
+ * A {@link Package} is the base class for "something" that can be downloaded from\r
+ * the SDK repository -- subclasses include {@link PlatformPackage}, {@link AddonPackage},\r
+ * {@link DocPackage} and {@link ToolPackage}.\r
+ * <p/>\r
+ * A package has some attributes (revision, description) and a list of archives\r
+ * which represent the downloadable bits.\r
+ * <p/>\r
+ * Packages are contained by a {@link RepoSource} (a download site).\r
+ * <p/>\r
+ * Derived classes must implement the {@link IDescription} methods.\r
  */\r
-public class Package {\r
+public abstract class Package implements IDescription {\r
 \r
     private final int mRevision;\r
     private final String mDescription;\r
     private final String mDescUrl;\r
+    private final Archive[] mArchives;\r
+\r
+    /**\r
+     * Creates a new package from the attributes and elements of the given XML node.\r
+     * <p/>\r
+     * This constructor should throw an exception if the package cannot be created.\r
+     */\r
+    Package(Node packageNode) {\r
+        mRevision    = getXmlInt   (packageNode, SdkRepository.NODE_REVISION, 0);\r
+        mDescription = getXmlString(packageNode, SdkRepository.NODE_DESCRIPTION);\r
+        mDescUrl     = getXmlString(packageNode, SdkRepository.NODE_DESC_URL);\r
 \r
-    private Package(int revision, String description, String descUrl) {\r
-        mRevision = revision;\r
-        mDescription = description;\r
-        mDescUrl = descUrl;\r
+        mArchives = parseArchives(getFirstChild(packageNode, SdkRepository.NODE_ARCHIVES));\r
     }\r
 \r
-    public Package(Node packageNode) {\r
-        this(getXmlInt   (packageNode, SdkRepository.NODE_REVISION, 0),\r
-             getXmlString(packageNode, SdkRepository.NODE_DESCRIPTION),\r
-             getXmlString(packageNode, SdkRepository.NODE_DESC_URL));\r
+    private Archive[] parseArchives(Node archivesNode) {\r
+        ArrayList<Archive> archives = new ArrayList<Archive>();\r
+\r
+        if (archivesNode != null) {\r
+            for(Node child = archivesNode.getFirstChild();\r
+                child != null;\r
+                child = child.getNextSibling()) {\r
 \r
-        // TODO archives\r
+                if (child.getNodeType() == Node.ELEMENT_NODE &&\r
+                        SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI()) &&\r
+                        SdkRepository.NODE_ARCHIVE.equals(child.getLocalName())) {\r
+                    archives.add(parseArchive(child));\r
+                }\r
+            }\r
+        }\r
+\r
+        return archives.toArray(new Archive[archives.size()]);\r
     }\r
 \r
-    /** The revision, an int > 0, for all packages (platform, add-on, tool, doc). */\r
+    private Archive parseArchive(Node archiveNode) {\r
+        Archive a = new Archive(\r
+                    (Os)   getEnumAttribute(archiveNode, SdkRepository.ATTR_OS,\r
+                            Os.values(), null),\r
+                    (Arch) getEnumAttribute(archiveNode, SdkRepository.ATTR_ARCH,\r
+                            Arch.values(), Arch.ANY),\r
+                    getXmlString(archiveNode, SdkRepository.NODE_URL),\r
+                    getXmlInt(archiveNode, SdkRepository.NODE_SIZE, 0),\r
+                    getXmlString(archiveNode, SdkRepository.NODE_CHECKSUM)\r
+                );\r
+\r
+        return a;\r
+    }\r
+\r
+    /** Returns the revision, an int > 0, for all packages (platform, add-on, tool, doc). */\r
     public int getRevision() {\r
         return mRevision;\r
     }\r
 \r
-    /** The optional description for all packages (platform, add-on, tool, doc) or for a lib. */\r
+    /** Returns the optional description for all packages (platform, add-on, tool, doc) or\r
+     *  for a lib. */\r
     public String getDescription() {\r
         return mDescription;\r
     }\r
 \r
-    /** The optional description URL for all packages (platform, add-on, tool, doc).\r
+    /** Returns the optional description URL for all packages (platform, add-on, tool, doc).\r
      * Can be empty but not null. */\r
     public String getDescUrl() {\r
         return mDescUrl;\r
     }\r
 \r
-    /**\r
-     * Retrieves the value of that XML element as a string.\r
-     * Returns an empty string when the element is missing.\r
-     */\r
-    protected static String getXmlString(Node node, String xmlLocalName) {\r
+    /** Returns the archives defined in this package. Can be an empty array but not null. */\r
+    public Archive[] getArchives() {\r
+        return mArchives;\r
+    }\r
+\r
+    /** Returns a short description for an {@link IDescription}. */\r
+    public abstract String getShortDescription();\r
+\r
+    /** Returns a long description for an {@link IDescription}. */\r
+    public String getLongDescription() {\r
+        return String.format("%1$s\nRevision %2$d", getDescription(), getRevision());\r
+    }\r
+\r
+    //---\r
+\r
+    protected static Node getFirstChild(Node node, String xmlLocalName) {\r
+\r
         for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {\r
             if (child.getNodeType() == Node.ELEMENT_NODE &&\r
-                    child.getNamespaceURI().equals(SdkRepository.NS_SDK_REPOSITORY)) {\r
-                if (xmlLocalName == null || child.getLocalName().equals(xmlLocalName)) {\r
-                    return child.getTextContent();\r
+                    SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI())) {\r
+                if (xmlLocalName == null || xmlLocalName.equals(child.getLocalName())) {\r
+                    return child;\r
                 }\r
             }\r
         }\r
 \r
-        return "";\r
+        return null;\r
+    }\r
+\r
+    /**\r
+     * Retrieves the value of that XML element as a string.\r
+     * Returns an empty string when the element is missing.\r
+     */\r
+    protected static String getXmlString(Node node, String xmlLocalName) {\r
+        Node child = getFirstChild(node, xmlLocalName);\r
+\r
+        return child == null ? "" : child.getTextContent();  //$NON-NLS-1$\r
     }\r
 \r
     /**\r
@@ -89,4 +158,29 @@ public class Package {
         }\r
     }\r
 \r
+    /**\r
+     * Retrieve an attribute which value must match one of the given enums using a\r
+     * case-insensitive name match.\r
+     *\r
+     * Returns defaultValue if the attribute does not exist or its value does not match\r
+     * the given enum values.\r
+     */\r
+    private Object getEnumAttribute(\r
+            Node archiveNode,\r
+            String attrName,\r
+            Object[] values,\r
+            Object defaultValue) {\r
+\r
+        Node attr = archiveNode.getAttributes().getNamedItem(attrName);\r
+        if (attr != null) {\r
+            String found = attr.getNodeValue();\r
+            for (Object value : values) {\r
+                if (value.toString().equalsIgnoreCase(found)) {\r
+                    return value;\r
+                }\r
+            }\r
+        }\r
+\r
+        return defaultValue;\r
+    }\r
 }\r
index b798ea8..8284c08 100755 (executable)
@@ -21,26 +21,47 @@ import com.android.sdklib.repository.SdkRepository;
 import org.w3c.dom.Node;\r
 \r
 /**\r
- *\r
+ * Represents a platform XML node in an SDK repository.\r
  */\r
 public class PlatformPackage extends Package {\r
 \r
     private final String mVersion;\r
-    private final String mApiLevel;\r
+    private final int mApiLevel;\r
 \r
-    public PlatformPackage(Node packageNode) {\r
+    /**\r
+     * Creates a new platform package from the attributes and elements of the given XML node.\r
+     * <p/>\r
+     * This constructor should throw an exception if the package cannot be created.\r
+     */\r
+    PlatformPackage(Node packageNode) {\r
         super(packageNode);\r
         mVersion  = getXmlString(packageNode, SdkRepository.NODE_VERSION);\r
-        mApiLevel = getXmlString(packageNode, SdkRepository.NODE_API_LEVEL);\r
+        mApiLevel = getXmlInt   (packageNode, SdkRepository.NODE_API_LEVEL, 0);\r
     }\r
 \r
+    /** Returns the version, a string, for platform packages. */\r
     public String getVersion() {\r
         return mVersion;\r
     }\r
 \r
-    public String getApiLevel() {\r
+    /** Returns the api-level, an int > 0, for platform, add-on and doc packages. */\r
+    public int getApiLevel() {\r
         return mApiLevel;\r
     }\r
 \r
+    /** Returns a short description for an {@link IDescription}. */\r
+    @Override\r
+    public String getShortDescription() {\r
+        return String.format("SDK Platform Android %1$s, API %2$d",\r
+                getVersion(),\r
+                getApiLevel());\r
+    }\r
 \r
+    /** Returns a long description for an {@link IDescription}. */\r
+    @Override\r
+    public String getLongDescription() {\r
+        return String.format("%1$s.\n%2$s",\r
+                getShortDescription(),\r
+                super.getLongDescription());\r
+    }\r
 }\r
index fd909ab..20777c3 100755 (executable)
@@ -41,14 +41,16 @@ import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;\r
 \r
 /**\r
- * An sdk-repository source. It may be a full repository or an add-on only repository.\r
+ * An sdk-repository source, i.e. a download site.\r
+ * It may be a full repository or an add-on only repository.\r
+ * A repository describes one or {@link Package}s available for download.\r
  */\r
 public class RepoSource implements IDescription {\r
 \r
     private final String mUrl;\r
     private final boolean mAddonOnly;\r
 \r
-    private ArrayList<String> mPackages;\r
+    private Package[] mPackages;\r
     private String mDescription;\r
 \r
     /**\r
@@ -68,7 +70,7 @@ public class RepoSource implements IDescription {
     /**\r
      * Returns the list of known packages. This is null when the source hasn't been loaded yet.\r
      */\r
-    public ArrayList<String> getPackages() {\r
+    public Package[] getPackages() {\r
         return mPackages;\r
     }\r
 \r
@@ -112,12 +114,12 @@ public class RepoSource implements IDescription {
                 monitor.setDescription("Parse XML");\r
                 monitor.incProgress(1);\r
                 parsePackages(xml, monitor);\r
-                if (mPackages.size() == 0) {\r
+                if (mPackages.length == 0) {\r
                     mDescription += "\nNo packages found.";\r
-                } else if (mPackages.size() == 1) {\r
+                } else if (mPackages.length == 1) {\r
                     mDescription += "\nOne package found.";\r
                 } else {\r
-                    mDescription += String.format("\n%1$d packages found.", mPackages.size());\r
+                    mDescription += String.format("\n%1$d packages found.", mPackages.length);\r
                 }\r
 \r
                 // done\r
@@ -223,32 +225,43 @@ public class RepoSource implements IDescription {
             Node root = getFirstChild(doc, SdkRepository.NODE_SDK_REPOSITORY);\r
             if (root != null) {\r
 \r
-                mPackages = new ArrayList<String>();\r
+                ArrayList<Package> packages = new ArrayList<Package>();\r
 \r
                 for (Node child = root.getFirstChild();\r
                      child != null;\r
                      child = child.getNextSibling()) {\r
                     if (child.getNodeType() == Node.ELEMENT_NODE &&\r
-                            child.getNamespaceURI().equals(SdkRepository.NS_SDK_REPOSITORY)) {\r
+                            SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI())) {\r
                         String name = child.getLocalName();\r
-                        if (SdkRepository.NODE_ADD_ON.equals(name)) {\r
-                            parseAddon(child, mPackages, monitor);\r
-\r
-                        } else if (!mAddonOnly) {\r
-                            if (SdkRepository.NODE_PLATFORM.equals(name)) {\r
-                                parsePlatform(child, mPackages, monitor);\r
-\r
-                            } else if (SdkRepository.NODE_DOC.equals(name)) {\r
-                                parseDoc(child, mPackages, monitor);\r
-\r
-                            } else if (SdkRepository.NODE_TOOL.equals(name)) {\r
-                                parseTool(child, mPackages, monitor);\r
+                        Package p = null;\r
+\r
+                        try {\r
+                            if (SdkRepository.NODE_ADD_ON.equals(name)) {\r
+                                p = new AddonPackage(child);\r
+\r
+                            } else if (!mAddonOnly) {\r
+                                if (SdkRepository.NODE_PLATFORM.equals(name)) {\r
+                                    p = new PlatformPackage(child);\r
+                                } else if (SdkRepository.NODE_DOC.equals(name)) {\r
+                                    p = new DocPackage(child);\r
+                                } else if (SdkRepository.NODE_TOOL.equals(name)) {\r
+                                    p = new ToolPackage(child);\r
+                                }\r
+                            }\r
 \r
+                            if (p != null) {\r
+                                packages.add(p);\r
+                                monitor.setDescription(\r
+                                        String.format("Found %1$s", p.getShortDescription()));\r
                             }\r
+                        } catch (Exception e) {\r
+                            // Ignore invalid packages\r
                         }\r
                     }\r
                 }\r
 \r
+                mPackages = packages.toArray(new Package[packages.size()]);\r
+\r
                 return true;\r
             }\r
 \r
@@ -269,7 +282,7 @@ public class RepoSource implements IDescription {
 \r
         for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {\r
             if (child.getNodeType() == Node.ELEMENT_NODE &&\r
-                    child.getNamespaceURI().equals(SdkRepository.NS_SDK_REPOSITORY)) {\r
+                    SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI())) {\r
                 if (xmlLocalName == null || child.getLocalName().equals(xmlLocalName)) {\r
                     return child;\r
                 }\r
@@ -290,42 +303,4 @@ public class RepoSource implements IDescription {
 \r
         return doc;\r
     }\r
-\r
-    private void parseAddon(Node addon, ArrayList<String> packages, ITaskMonitor monitor) {\r
-        // TODO Auto-generated method stub\r
-        String s = String.format("addon %1$s by %2$s, api %3$s, rev %4$s",\r
-                getFirstChild(addon, SdkRepository.NODE_NAME).getTextContent(),\r
-                getFirstChild(addon, SdkRepository.NODE_VENDOR).getTextContent(),\r
-                getFirstChild(addon, SdkRepository.NODE_API_LEVEL).getTextContent(),\r
-                getFirstChild(addon, SdkRepository.NODE_REVISION).getTextContent()\r
-                );\r
-        packages.add(s);\r
-    }\r
-\r
-    private void parsePlatform(Node platform, ArrayList<String> packages, ITaskMonitor monitor) {\r
-        // TODO Auto-generated method stub\r
-        String s = String.format("platform %1$s, api %2$s, rev %3$s",\r
-                getFirstChild(platform, SdkRepository.NODE_VERSION).getTextContent(),\r
-                getFirstChild(platform, SdkRepository.NODE_API_LEVEL).getTextContent(),\r
-                getFirstChild(platform, SdkRepository.NODE_REVISION).getTextContent()\r
-                );\r
-        packages.add(s);\r
-    }\r
-\r
-    private void parseDoc(Node doc, ArrayList<String> packages, ITaskMonitor monitor) {\r
-        // TODO Auto-generated method stub\r
-        String s = String.format("doc for api %1$s, rev %2$s",\r
-                getFirstChild(doc, SdkRepository.NODE_API_LEVEL).getTextContent(),\r
-                getFirstChild(doc, SdkRepository.NODE_REVISION).getTextContent()\r
-                );\r
-        packages.add(s);\r
-    }\r
-\r
-    private void parseTool(Node tool, ArrayList<String> packages, ITaskMonitor monitor) {\r
-        // TODO Auto-generated method stub\r
-        String s = String.format("tool, rev %1$s",\r
-                getFirstChild(tool, SdkRepository.NODE_REVISION).getTextContent()\r
-                );\r
-        packages.add(s);\r
-    }\r
 }\r
index 9979ee3..4416ea0 100755 (executable)
 \r
 package com.android.sdklib.internal.repository;\r
 \r
-import com.android.sdklib.repository.SdkRepository;\r
-\r
 import org.w3c.dom.Node;\r
 \r
 /**\r
- *\r
+ * Represents a tool XML node in an SDK repository.\r
  */\r
 public class ToolPackage extends Package {\r
 \r
-    private final String mApiLevel;\r
-\r
-    public ToolPackage(Node packageNode) {\r
+    /**\r
+     * Creates a new tool package from the attributes and elements of the given XML node.\r
+     * <p/>\r
+     * This constructor should throw an exception if the package cannot be created.\r
+     */\r
+    ToolPackage(Node packageNode) {\r
         super(packageNode);\r
-        mApiLevel = getXmlString(packageNode, SdkRepository.NODE_API_LEVEL);\r
     }\r
 \r
-    public String getApiLevel() {\r
-        return mApiLevel;\r
+    /** Returns a short description for an {@link IDescription}. */\r
+    @Override\r
+    public String getShortDescription() {\r
+        return String.format("Android SDK Tools, revision %1$d", getRevision());\r
     }\r
 \r
-\r
+    /** Returns a long description for an {@link IDescription}. */\r
+    @Override\r
+    public String getLongDescription() {\r
+        return String.format("Android SDK Tools, revision %1$d.\n%2$s",\r
+                getRevision(),\r
+                super.getLongDescription());\r
+    }\r
 }\r
index 65962c9..d0ea56c 100755 (executable)
@@ -61,9 +61,9 @@ public class SdkRepository {
     public static final String NODE_LIB       = "lib";                          //$NON-NLS-1$\r
 \r
     /** The archives container, for all packages. */\r
-    public static final String NODE_ARCHVIES = "archives";                      //$NON-NLS-1$\r
+    public static final String NODE_ARCHIVES = "archives";                      //$NON-NLS-1$\r
     /** An archive element, for the archives container. */\r
-    public static final String NODE_ARCHVIE  = "archive";                       //$NON-NLS-1$\r
+    public static final String NODE_ARCHIVE  = "archive";                       //$NON-NLS-1$\r
 \r
     /** An archive size, an int > 0. */\r
     public static final String NODE_SIZE     = "size";                          //$NON-NLS-1$\r
@@ -72,10 +72,12 @@ public class SdkRepository {
     /** A download archive URL, either absolute or relative to the repository xml. */\r
     public static final String NODE_URL      = "url";                           //$NON-NLS-1$\r
 \r
+    /** An archive checksum type, mandatory. */\r
+    public static final String ATTR_TYPE = "type";                              //$NON-NLS-1$\r
     /** An archive OS attribute, mandatory. */\r
-    public static final String NODE_OS   = "os";                                //$NON-NLS-1$\r
+    public static final String ATTR_OS   = "os";                                //$NON-NLS-1$\r
     /** An optional archive Architecture attribute. */\r
-    public static final String NODE_ARCH = "arch";                              //$NON-NLS-1$\r
+    public static final String ATTR_ARCH = "arch";                              //$NON-NLS-1$\r
 \r
     public static InputStream getXsdStream() {\r
         return SdkRepository.class.getResourceAsStream("sdk-repository.xsd");   //$NON-NLS-1$\r
index 42ab5b2..0e61b1e 100755 (executable)
 \r
 package com.android.sdkuilib.internal.repository;\r
 \r
+import com.android.sdklib.internal.repository.Archive;\r
 import com.android.sdklib.internal.repository.IDescription;\r
 import com.android.sdklib.internal.repository.ITaskFactory;\r
+import com.android.sdklib.internal.repository.Package;\r
 import com.android.sdklib.internal.repository.RepoSource;\r
 \r
 import org.eclipse.jface.viewers.IContentProvider;\r
@@ -108,8 +110,9 @@ class RepoSources {
          * Get the children of the given parent. This is requested on-demand as\r
          * nodes are expanded.\r
          *\r
-         * For a {@link RepoSources} object, returns an array of {@link RepoSource}.\r
-         * For a {@link RepoSource}, returns an array of packages.\r
+         * For a {@link RepoSources} object, returns an array of {@link RepoSource}s.\r
+         * For a {@link RepoSource}, returns an array of {@link Package}s.\r
+         * For a {@link Package}, returns an array of {@link Archive}s.\r
          */\r
         public Object[] getChildren(Object parentElement) {\r
             if (parentElement instanceof RepoSources) {\r
@@ -117,17 +120,21 @@ class RepoSources {
 \r
             } else if (parentElement instanceof RepoSource) {\r
                 RepoSource source = (RepoSource) parentElement;\r
-                ArrayList<String> pkgs = source.getPackages();\r
+                Package[] packages = source.getPackages();\r
 \r
-                if (pkgs == null) {\r
+                if (packages == null) {\r
                     source.load(mTaskFactory);\r
-                    pkgs = source.getPackages();\r
+                    packages = source.getPackages();\r
                 }\r
-                if (pkgs != null) {\r
-                    return pkgs.toArray();\r
+                if (packages != null) {\r
+                    return packages;\r
                 }\r
+\r
+            } else if (parentElement instanceof Package) {\r
+                return ((Package) parentElement).getArchives();\r
             }\r
 \r
+\r
             return new Object[0];\r
         }\r
 \r
@@ -148,7 +155,7 @@ class RepoSources {
          * All {@link RepoSource} are expandable, whether they actually have any childre or not.\r
          */\r
         public boolean hasChildren(Object element) {\r
-            return element instanceof RepoSource;\r
+            return element instanceof RepoSource || element instanceof Package;\r
         }\r
     }\r
 \r