OSDN Git Service

SDK Repo Schema: <vendor> for <extra> elements.
authorRaphael Moll <ralf@android.com>
Wed, 3 Nov 2010 21:12:47 +0000 (14:12 -0700)
committerRaphael Moll <ralf@android.com>
Wed, 3 Nov 2010 21:12:47 +0000 (14:12 -0700)
Change-Id: I8fa13d28b787e3ecb8bd96896e6410313e2a66a9

sdkmanager/libs/sdklib/src/com/android/sdklib/PlatformTarget.java
sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java
sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java
sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java
sdkmanager/libs/sdklib/src/com/android/sdklib/repository/RepoConstants.java
sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-addon-1.xsd
sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository-3.xsd
sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/SdkAddonSourceTest.java
sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/SdkRepoSourceTest.java
sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/addon_sample_1.xml
sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/repository_sample_3.xml

index 61c59c7..2a22d0a 100644 (file)
@@ -54,6 +54,7 @@ final class PlatformTarget implements IAndroidTarget {
      * @param versionName the version name of the platform.
      * @param revision the revision of the platform component.
      */
+    @SuppressWarnings("deprecation")
     PlatformTarget(String sdkOsPath, String platformOSPath, Map<String, String> properties,
             int apiLevel, String codeName, String versionName, int revision) {
         if (platformOSPath.endsWith(File.separator) == false) {
index 10e6424..2bab0b5 100755 (executable)
@@ -18,6 +18,7 @@ package com.android.sdklib.internal.repository;
 \r
 import com.android.sdklib.SdkConstants;\r
 import com.android.sdklib.SdkManager;\r
+import com.android.sdklib.repository.RepoConstants;\r
 \r
 import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;\r
 import org.apache.commons.compress.archivers.zip.ZipFile;\r
@@ -1032,7 +1033,7 @@ public class Archive implements IDescription, Comparable<Archive> {
      * This folder is always at osBasePath/temp.\r
      */\r
     private File getTempFolder(String osBasePath) {\r
-        File baseTempFolder = new File(osBasePath, "temp");     //$NON-NLS-1$\r
+        File baseTempFolder = new File(osBasePath, RepoConstants.FD_TEMP);\r
         return baseTempFolder;\r
     }\r
 \r
index 622b8ba..d3f3a9b 100755 (executable)
@@ -20,6 +20,7 @@ import com.android.sdklib.SdkConstants;
 import com.android.sdklib.SdkManager;\r
 import com.android.sdklib.internal.repository.Archive.Arch;\r
 import com.android.sdklib.internal.repository.Archive.Os;\r
+import com.android.sdklib.repository.RepoConstants;\r
 import com.android.sdklib.repository.SdkRepoConstants;\r
 \r
 import org.w3c.dom.Node;\r
@@ -35,14 +36,22 @@ public class ExtraPackage extends MinToolsPackage
     implements IMinApiLevelDependency {\r
 \r
     private static final String PROP_PATH          = "Extra.Path";         //$NON-NLS-1$\r
+    private static final String PROP_VENDOR        = "Extra.Vendor";       //$NON-NLS-1$\r
     private static final String PROP_MIN_API_LEVEL = "Extra.MinApiLevel";  //$NON-NLS-1$\r
 \r
     /**\r
-     * The install folder name. It must be a single-segment path.\r
-     * The paths "add-ons", "platforms", "tools" and "docs" are reserved and cannot be used.\r
+     * The vendor folder name. It must be a non-empty single-segment path.\r
+     * <p/>\r
+     * The paths "add-ons", "platforms", "platform-tools", "tools" and "docs" are reserved and\r
+     * cannot be used.\r
      * This limitation cannot be written in the XML Schema and must be enforced here by using\r
      * the method {@link #isPathValid()} *before* installing the package.\r
      */\r
+    private final String mVendor;\r
+\r
+    /**\r
+     * The sub-folder name. It must be a non-empty single-segment path.\r
+     */\r
     private final String mPath;\r
 \r
     /**\r
@@ -64,7 +73,8 @@ public class ExtraPackage extends MinToolsPackage
     ExtraPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
         super(source, packageNode, nsUri, licenses);\r
 \r
-        mPath = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_PATH);\r
+        mPath   = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_PATH);\r
+        mVendor = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_VENDOR);\r
 \r
         mMinApiLevel = XmlParserUtils.getXmlInt(packageNode, SdkRepoConstants.NODE_MIN_API_LEVEL,\r
                 MIN_API_LEVEL_NOT_SPECIFIED);\r
@@ -79,6 +89,7 @@ public class ExtraPackage extends MinToolsPackage
      */\r
     ExtraPackage(SdkSource source,\r
             Properties props,\r
+            String vendor,\r
             String path,\r
             int revision,\r
             String license,\r
@@ -97,8 +108,14 @@ public class ExtraPackage extends MinToolsPackage
                 archiveArch,\r
                 archiveOsPath);\r
 \r
+        // The vendor argument is not supposed to be empty. However this attribute did not\r
+        // exist prior to schema repo-v3 and tools r8, which means we need to cope with a\r
+        // lack of it when reading back old local repositories. In this case we allow an\r
+        // empty string.\r
+        mVendor = vendor != null ? vendor : getProperty(props, PROP_VENDOR, "");\r
+\r
         // The path argument comes before whatever could be in the properties\r
-        mPath = path != null ? path : getProperty(props, PROP_PATH, path);\r
+        mPath   = path != null ? path : getProperty(props, PROP_PATH, path);\r
 \r
         mMinApiLevel = Integer.parseInt(\r
             getProperty(props, PROP_MIN_API_LEVEL, Integer.toString(MIN_API_LEVEL_NOT_SPECIFIED)));\r
@@ -113,6 +130,9 @@ public class ExtraPackage extends MinToolsPackage
         super.saveProperties(props);\r
 \r
         props.setProperty(PROP_PATH, mPath);\r
+        if (mVendor != null) {\r
+            props.setProperty(PROP_PATH, mVendor);\r
+        }\r
 \r
         if (getMinApiLevel() != MIN_API_LEVEL_NOT_SPECIFIED) {\r
             props.setProperty(PROP_MIN_API_LEVEL, Integer.toString(getMinApiLevel()));\r
@@ -133,21 +153,38 @@ public class ExtraPackage extends MinToolsPackage
     public boolean isPathValid() {\r
         if (SdkConstants.FD_ADDONS.equals(mPath) ||\r
                 SdkConstants.FD_PLATFORMS.equals(mPath) ||\r
+                SdkConstants.FD_PLATFORM_TOOLS.equals(mPath) ||\r
                 SdkConstants.FD_TOOLS.equals(mPath) ||\r
-                SdkConstants.FD_DOCS.equals(mPath)) {\r
+                SdkConstants.FD_DOCS.equals(mPath) ||\r
+                RepoConstants.FD_TEMP.equals(mPath)) {\r
             return false;\r
         }\r
         return mPath != null && mPath.indexOf('/') == -1 && mPath.indexOf('\\') == -1;\r
     }\r
 \r
     /**\r
-     * The install folder name. It must be a single-segment path.\r
+     * The install folder name. It is a single-segment path.\r
+     * <p/>\r
      * The paths "add-ons", "platforms", "tools" and "docs" are reserved and cannot be used.\r
      * This limitation cannot be written in the XML Schema and must be enforced here by using\r
      * the method {@link #isPathValid()} *before* installing the package.\r
      */\r
     public String getPath() {\r
-        return mPath;\r
+        String path = mPath;\r
+\r
+        if (mVendor != null && mVendor.length() > 0) {\r
+            path = mVendor + "-" + mPath;    //$NON-NLS-1$\r
+        }\r
+\r
+        int h = path.hashCode();\r
+\r
+        // Sanitize the path\r
+        path = path.replaceAll("[^a-zA-Z0-9-]+", "_");       //$NON-NLS-1$\r
+        if (path.length() == 0) {\r
+            path = String.format("unknown_extra%08x", h);  //$NON-NLS-1$\r
+        }\r
+\r
+        return path;\r
     }\r
 \r
     /** Returns a short description for an {@link IDescription}. */\r
index 8d79ced..915a8e6 100755 (executable)
@@ -170,6 +170,7 @@ public class LocalSdkParser {
                         ExtraPackage pkg = new ExtraPackage(\r
                                 null,                       //source\r
                                 props,                      //properties\r
+                                null,                       //vendor\r
                                 dir.getName(),              //path\r
                                 0,                          //revision\r
                                 null,                       //license\r
index 58a2c83..61a67bd 100755 (executable)
@@ -56,7 +56,7 @@ public class RepoConstants {
     public static final String NODE_API_LEVEL = "api-level";                    //$NON-NLS-1$\r
     /** The codename, a string, for platform packages. */\r
     public static final String NODE_CODENAME = "codename";                      //$NON-NLS-1$\r
-    /** The vendor, a string, for add-on packages. */\r
+    /** The vendor, a string, for add-on and extra packages. */\r
     public static final String NODE_VENDOR    = "vendor";                       //$NON-NLS-1$\r
     /** The name, a string, for add-on packages or for libraries. */\r
     public static final String NODE_NAME      = "name";                         //$NON-NLS-1$\r
@@ -66,8 +66,8 @@ public class RepoConstants {
     /** A lib element in a libs container. */\r
     public static final String NODE_LIB       = "lib";                          //$NON-NLS-1$\r
 \r
-    /** The path, a string, for extra packages. */\r
-    public static final String NODE_PATH = "path";                              //$NON-NLS-1$\r
+    /** The path segment, a string, for extra packages. */\r
+    public static final String NODE_PATH = "path";                                  //$NON-NLS-1$\r
 \r
     /** The archives container, for all packages. */\r
     public static final String NODE_ARCHIVES = "archives";                      //$NON-NLS-1$\r
@@ -99,4 +99,11 @@ public class RepoConstants {
     /** Length of a string representing a SHA1 checksum; always 40 characters long. */\r
     public static final int SHA1_CHECKSUM_LEN = 40;\r
 \r
+    /**\r
+     * Temporary folder used to hold downloads and extract archives during installation.\r
+     * This folder will be located in the SDK.\r
+     */\r
+    public static final String FD_TEMP = "temp";     //$NON-NLS-1$\r
+\r
+\r
 }\r
index 041a038..8d84205 100755 (executable)
@@ -17,7 +17,7 @@
 <xsd:schema
     targetNamespace="http://schemas.android.com/sdk/android/addon/1"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-    xmlns:sa1="http://schemas.android.com/sdk/android/addon/1"
+    xmlns:sdk="http://schemas.android.com/sdk/android/addon/1"
     elementFormDefault="qualified"
     attributeFormDefault="unqualified"
     version="1">
@@ -35,7 +35,7 @@
            <extra> packages.
     -->
 
-    <xsd:element name="sdk-addon" type="sa1:repositoryType" />
+    <xsd:element name="sdk-addon" type="sdk:repositoryType" />
 
     <xsd:complexType name="repositoryType">
         <xsd:annotation>
@@ -44,9 +44,9 @@
             </xsd:documentation>
         </xsd:annotation>
         <xsd:choice minOccurs="0" maxOccurs="unbounded">
-            <xsd:element name="add-on"          type="sa1:addonType"        />
-            <xsd:element name="extra"           type="sa1:extraType"        />
-            <xsd:element name="license"         type="sa1:licenseType"      />
+            <xsd:element name="add-on"          type="sdk:addonType"        />
+            <xsd:element name="extra"           type="sdk:extraType"        />
+            <xsd:element name="license"         type="sdk:licenseType"      />
         </xsd:choice>
     </xsd:complexType>
 
@@ -71,7 +71,7 @@
             <xsd:element name="revision"     type="xsd:positiveInteger" />
             <!-- The optional license of this package. If present, users will have
                  to agree to it before downloading. -->
-            <xsd:element name="uses-license" type="sa1:usesLicenseType" minOccurs="0" />
+            <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
             <!-- The optional description of this package. -->
             <xsd:element name="description"  type="xsd:string"      minOccurs="0" />
             <!-- The optional description URL of this package -->
@@ -81,7 +81,7 @@
             <!-- The optional release note URL of this package -->
             <xsd:element name="release-url"  type="xsd:token"       minOccurs="0" />
             <!-- A list of file archives for this package. -->
-            <xsd:element name="archives"     type="sa1:archivesType" />
+            <xsd:element name="archives"     type="sdk:archivesType" />
 
             <!-- An optional element indicating the package is obsolete.
                  The string content is however currently not defined and ignored. -->
 
 
     <!-- The definition of an SDK extra package. This kind of package is for
-         "free" content and specifies in which fixed root directory it must be
-         installed.
+         "free" content. Such packages are installed in SDK/vendor/path.
     -->
 
     <xsd:complexType name="extraType" >
         <xsd:annotation>
             <xsd:documentation>
-                An SDK extra package. This kind of package is for "free"
-                content and specifies in which fixed root directory it must be
-                installed.
-                The paths "add-ons", "platforms", "tools" and "docs" are
-                reserved and cannot be used.
+                An SDK extra package. This kind of package is for "free" content.
+                Such packages are installed in SDK/vendor/path.
             </xsd:documentation>
         </xsd:annotation>
         <xsd:all>
-            <!-- The install folder name. It must be a single-segment path.
-                 The paths "add-ons", "platforms", "tools" and "docs" are
-                 reserved and cannot be used.
+
+            <!-- The install path top folder name. It must not be empty.
+                 The segments "add-ons", "docs", "platforms", "platform-tools", "temp"
+                 and "tools" are reserved and cannot be used.
             -->
-            <xsd:element name="path">
-                <xsd:simpleType>
-                    <xsd:restriction base="xsd:token">
-                        <xsd:pattern value="[^/\\]+"/>
-                    </xsd:restriction>
-                </xsd:simpleType>
-            </xsd:element>
+            <xsd:element name="vendor" type="sdk:segmentType" />
+
+            <!-- The install path sub-folder name. It must not be empty. -->
+            <xsd:element name="path" type="sdk:segmentType" />
 
             <!-- The revision, an int > 0, incremented each time a new
                  package is generated. -->
             <xsd:element name="revision"     type="xsd:positiveInteger" />
             <!-- The optional license of this package. If present, users will have
                  to agree to it before downloading. -->
-            <xsd:element name="uses-license" type="sa1:usesLicenseType" minOccurs="0" />
+            <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
             <!-- The optional description of this package. -->
             <xsd:element name="description"  type="xsd:string"      minOccurs="0" />
             <!-- The optional description URL of this package -->
             <!-- The optional release note URL of this package -->
             <xsd:element name="release-url"  type="xsd:token"       minOccurs="0" />
             <!-- A list of file archives for this package. -->
-            <xsd:element name="archives"     type="sa1:archivesType" />
+            <xsd:element name="archives"     type="sdk:archivesType" />
             <!-- The minimal revision of tools required by this package.
                  Optional. If present, must be an int > 0. -->
             <xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
     </xsd:complexType>
 
 
+    <!-- The definition of a path segment used by the extra element. -->
+
+    <xsd:simpleType name="segmentType">
+        <xsd:annotation>
+            <xsd:documentation>
+                One path segment for the install path of an extra element.
+                It must be a single-segment path. It must not be empty.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:restriction base="xsd:token">
+            <xsd:pattern value="[a-zA-Z0-9_]+"/>
+        </xsd:restriction>
+    </xsd:simpleType>
+
+
     <!-- The definition of a license to be referenced by the uses-license element. -->
 
     <xsd:complexType name="licenseType">
                         <!-- The size in bytes of the archive to download. -->
                         <xsd:element name="size"     type="xsd:positiveInteger" />
                         <!-- The checksum of the archive file. -->
-                        <xsd:element name="checksum" type="sa1:checksumType" />
+                        <xsd:element name="checksum" type="sdk:checksumType" />
                         <!-- The URL is an absolute URL if it starts with http://, https://
                              or ftp://. Otherwise it is relative to the parent directory that
                              contains this repository.xml -->
             <xsd:documentation>A file checksum, currently only SHA1.</xsd:documentation>
         </xsd:annotation>
         <xsd:simpleContent>
-            <xsd:extension base="sa1:sha1Number">
+            <xsd:extension base="sdk:sha1Number">
                 <xsd:attribute name="type" type="xsd:token" fixed="sha1" />
             </xsd:extension>
         </xsd:simpleContent>
index 89c74d2..75d8541 100755 (executable)
@@ -17,7 +17,7 @@
 <xsd:schema
     targetNamespace="http://schemas.android.com/sdk/android/repository/3"
     xmlns:xsd="http://www.w3.org/2001/XMLSchema"
-    xmlns:sr3="http://schemas.android.com/sdk/android/repository/3"
+    xmlns:sdk="http://schemas.android.com/sdk/android/repository/3"
     elementFormDefault="qualified"
     attributeFormDefault="unqualified"
     version="1">
@@ -49,7 +49,7 @@
             - It removes the <addon> repository type, which is now in its own XML Schema.
     -->
 
-    <xsd:element name="sdk-repository" type="sr3:repositoryType" />
+    <xsd:element name="sdk-repository" type="sdk:repositoryType" />
 
     <xsd:complexType name="repositoryType">
         <xsd:annotation>
             </xsd:documentation>
         </xsd:annotation>
         <xsd:choice minOccurs="0" maxOccurs="unbounded">
-            <xsd:element name="platform"        type="sr3:platformType"     />
-            <xsd:element name="tool"            type="sr3:toolType"         />
-            <xsd:element name="platform-tool"   type="sr3:platformToolType" />
-            <xsd:element name="doc"             type="sr3:docType"          />
-            <xsd:element name="sample"          type="sr3:sampleType"       />
-            <xsd:element name="extra"           type="sr3:extraType"        />
-            <xsd:element name="license"         type="sr3:licenseType"      />
+            <xsd:element name="platform"        type="sdk:platformType"     />
+            <xsd:element name="tool"            type="sdk:toolType"         />
+            <xsd:element name="platform-tool"   type="sdk:platformToolType" />
+            <xsd:element name="doc"             type="sdk:docType"          />
+            <xsd:element name="sample"          type="sdk:sampleType"       />
+            <xsd:element name="extra"           type="sdk:extraType"        />
+            <xsd:element name="license"         type="sdk:licenseType"      />
         </xsd:choice>
     </xsd:complexType>
 
@@ -87,7 +87,7 @@
             <xsd:element name="revision"     type="xsd:positiveInteger" />
             <!-- The optional license of this package. If present, users will have
                  to agree to it before downloading. -->
-            <xsd:element name="uses-license" type="sr3:usesLicenseType" minOccurs="0" />
+            <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
             <!-- The optional description of this package. -->
             <xsd:element name="description"  type="xsd:string"      minOccurs="0" />
             <!-- The optional description URL of this package -->
@@ -97,7 +97,7 @@
             <!-- The optional release note URL of this package -->
             <xsd:element name="release-url"  type="xsd:token"       minOccurs="0" />
             <!-- A list of file archives for this package. -->
-            <xsd:element name="archives"     type="sr3:archivesType" />
+            <xsd:element name="archives"     type="sdk:archivesType" />
             <!-- The minimal revision of tools required by this package.
                  Optional. If present, must be an int > 0. -->
             <xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
             <xsd:element name="revision"     type="xsd:positiveInteger" />
             <!-- The optional license of this package. If present, users will have
                  to agree to it before downloading. -->
-            <xsd:element name="uses-license" type="sr3:usesLicenseType" minOccurs="0" />
+            <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
             <!-- The optional description of this package. -->
             <xsd:element name="description"  type="xsd:string"      minOccurs="0" />
             <!-- The optional description URL of this package -->
             <!-- The optional release note URL of this package -->
             <xsd:element name="release-url"  type="xsd:token"       minOccurs="0" />
             <!-- A list of file archives for this package. -->
-            <xsd:element name="archives"     type="sr3:archivesType" />
+            <xsd:element name="archives"     type="sdk:archivesType" />
             <!-- An optional element indicating the package is obsolete.
                  The string content is however currently not defined and ignored. -->
             <xsd:element name="obsolete"  type="xsd:string" minOccurs="0" />
             <xsd:element name="revision"     type="xsd:positiveInteger" />
             <!-- The optional license of this package. If present, users will have
                  to agree to it before downloading. -->
-            <xsd:element name="uses-license" type="sr3:usesLicenseType" minOccurs="0" />
+            <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
             <!-- The optional description of this package. -->
             <xsd:element name="description"  type="xsd:string"      minOccurs="0" />
             <!-- The optional description URL of this package -->
             <!-- The optional release note URL of this package -->
             <xsd:element name="release-url"  type="xsd:token"       minOccurs="0" />
             <!-- A list of file archives for this package. -->
-            <xsd:element name="archives"     type="sr3:archivesType" />
+            <xsd:element name="archives"     type="sdk:archivesType" />
 
             <!-- An optional element indicating the package is obsolete.
                  The string content is however currently not defined and ignored. -->
             <xsd:element name="revision"     type="xsd:positiveInteger" />
             <!-- The optional license of this package. If present, users will have
                  to agree to it before downloading. -->
-            <xsd:element name="uses-license" type="sr3:usesLicenseType" minOccurs="0" />
+            <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
             <!-- The optional description of this package. -->
             <xsd:element name="description"  type="xsd:string"      minOccurs="0" />
             <!-- The optional description URL of this package -->
             <!-- The optional release note URL of this package -->
             <xsd:element name="release-url"  type="xsd:token"       minOccurs="0" />
             <!-- A list of file archives for this package. -->
-            <xsd:element name="archives"     type="sr3:archivesType" />
+            <xsd:element name="archives"     type="sdk:archivesType" />
 
             <!-- An optional element indicating the package is obsolete.
                  The string content is however currently not defined and ignored. -->
             <xsd:element name="revision"     type="xsd:positiveInteger" />
             <!-- The optional license of this package. If present, users will have
                  to agree to it before downloading. -->
-            <xsd:element name="uses-license" type="sr3:usesLicenseType" minOccurs="0" />
+            <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
             <!-- The optional description of this package. -->
             <xsd:element name="description"  type="xsd:string"      minOccurs="0" />
             <!-- The optional description URL of this package -->
             <!-- The optional release note URL of this package -->
             <xsd:element name="release-url"  type="xsd:token"       minOccurs="0" />
             <!-- A list of file archives for this package. -->
-            <xsd:element name="archives"     type="sr3:archivesType" />
+            <xsd:element name="archives"     type="sdk:archivesType" />
             <!-- The minimal revision of tools required by this package.
                  Optional. If present, must be an int > 0. -->
             <xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
 
 
     <!-- The definition of an SDK extra package. This kind of package is for
-         "free" content and specifies in which fixed root directory it must be
-         installed.
+         "free" content. Such packages are installed in SDK/vendor/path.
     -->
 
     <xsd:complexType name="extraType" >
         <xsd:annotation>
             <xsd:documentation>
-                An SDK extra package. This kind of package is for "free"
-                content and specifies in which fixed root directory it must be
-                installed.
-                Path names matching existing package types here (e.g. "add-ons",
-                "platforms", "tools", "docs", etc.) are reserved and cannot be used.
+                An SDK extra package. This kind of package is for "free" content.
+                Such packages are installed in SDK/vendor/path.
             </xsd:documentation>
         </xsd:annotation>
         <xsd:all>
-            <!-- The install folder name. It must be a single-segment path.
-                 The paths "add-ons", "platforms", "tools" and "docs" are
-                 reserved and cannot be used.
+
+            <!-- The install path top folder name.
+                 The segments "add-ons", "docs", "platforms", "platform-tools", "temp"
+                 and "tools" are reserved and cannot be used.
             -->
-            <xsd:element name="path">
-                <xsd:simpleType>
-                    <xsd:restriction base="xsd:token">
-                        <xsd:pattern value="[^/\\]+"/>
-                    </xsd:restriction>
-                </xsd:simpleType>
-            </xsd:element>
+            <xsd:element name="vendor" type="sdk:segmentType" />
+
+            <!-- The install path sub-folder name. -->
+            <xsd:element name="path" type="sdk:segmentType" />
 
             <!-- The revision, an int > 0, incremented each time a new
                  package is generated. -->
             <xsd:element name="revision"     type="xsd:positiveInteger" />
             <!-- The optional license of this package. If present, users will have
                  to agree to it before downloading. -->
-            <xsd:element name="uses-license" type="sr3:usesLicenseType" minOccurs="0" />
+            <xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
             <!-- The optional description of this package. -->
             <xsd:element name="description"  type="xsd:string"      minOccurs="0" />
             <!-- The optional description URL of this package -->
             <!-- The optional release note URL of this package -->
             <xsd:element name="release-url"  type="xsd:token"       minOccurs="0" />
             <!-- A list of file archives for this package. -->
-            <xsd:element name="archives"     type="sr3:archivesType" />
+            <xsd:element name="archives"     type="sdk:archivesType" />
             <!-- The minimal revision of tools required by this package.
                  Optional. If present, must be an int > 0. -->
             <xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
     </xsd:complexType>
 
 
+    <!-- The definition of a path segment used by the extra element. -->
+
+    <xsd:simpleType name="segmentType">
+        <xsd:annotation>
+            <xsd:documentation>
+                One path segment for the install path of an extra element.
+                It must be a single-segment path.
+            </xsd:documentation>
+        </xsd:annotation>
+        <xsd:restriction base="xsd:token">
+            <xsd:pattern value="[a-zA-Z0-9_]+"/>
+        </xsd:restriction>
+    </xsd:simpleType>
+
+
     <!-- The definition of a license to be referenced by the uses-license element. -->
 
     <xsd:complexType name="licenseType">
                         <!-- The size in bytes of the archive to download. -->
                         <xsd:element name="size"     type="xsd:positiveInteger" />
                         <!-- The checksum of the archive file. -->
-                        <xsd:element name="checksum" type="sr3:checksumType" />
+                        <xsd:element name="checksum" type="sdk:checksumType" />
                         <!-- The URL is an absolute URL if it starts with http://, https://
                              or ftp://. Otherwise it is relative to the parent directory that
                              contains this repository.xml -->
             <xsd:documentation>A file checksum, currently only SHA1.</xsd:documentation>
         </xsd:annotation>
         <xsd:simpleContent>
-            <xsd:extension base="sr3:sha1Number">
+            <xsd:extension base="sdk:sha1Number">
                 <xsd:attribute name="type" type="xsd:token" fixed="sha1" />
             </xsd:extension>
         </xsd:simpleContent>
index d05c967..9e152d5 100755 (executable)
@@ -24,6 +24,8 @@ import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;\r
 import java.io.IOException;\r
 import java.io.InputStream;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
 \r
 import junit.framework.TestCase;\r
 \r
@@ -169,8 +171,8 @@ public class SdkAddonSourceTest extends TestCase {
         assertEquals("Found My First add-on by John Doe, Android API 1, revision 1\n" +\r
                      "Found My Second add-on by John Deer, Android API 2, revision 42\n" +\r
                      "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +\r
-                     "Found Usb Driver package, revision 43 (Obsolete)\n" +\r
-                     "Found Extra Api Dep package, revision 2 (Obsolete)\n",\r
+                     "Found Usb Driver package, revision 43 (Obsolete)\n" +\r
+                     "Found Android Vendor Extra Api Dep package, revision 2 (Obsolete)\n",\r
                 monitor.getCapturedDescriptions());\r
         assertEquals("", monitor.getCapturedResults());\r
 \r
@@ -181,6 +183,17 @@ public class SdkAddonSourceTest extends TestCase {
         for (Package p : pkgs) {\r
             assertTrue(p.getArchives().length >= 1);\r
         }\r
+\r
+        // Check the extra packages path\r
+        ArrayList<String> extraPaths = new ArrayList<String>();\r
+        for (Package p : pkgs) {\r
+            if (p instanceof ExtraPackage) {\r
+                extraPaths.add(((ExtraPackage) p).getPath());\r
+            }\r
+        }\r
+        assertEquals(\r
+                "[a-usb_driver, android_vendor-extra_api_dep]",\r
+                Arrays.toString(extraPaths.toArray()));\r
     }\r
 \r
     /**\r
index c6d6eb3..c92acde 100755 (executable)
@@ -24,6 +24,8 @@ import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;\r
 import java.io.IOException;\r
 import java.io.InputStream;\r
+import java.util.ArrayList;\r
+import java.util.Arrays;\r
 \r
 import junit.framework.TestCase;\r
 \r
@@ -205,6 +207,17 @@ public class SdkRepoSourceTest extends TestCase {
         for (Package p : pkgs) {\r
             assertTrue(p.getArchives().length >= 1);\r
         }\r
+\r
+        // Check the extra packages path\r
+        ArrayList<String> extraPaths = new ArrayList<String>();\r
+        for (Package p : pkgs) {\r
+            if (p instanceof ExtraPackage) {\r
+                extraPaths.add(((ExtraPackage) p).getPath());\r
+            }\r
+        }\r
+        assertEquals(\r
+                "[usb_driver]",\r
+                Arrays.toString(extraPaths.toArray()));\r
     }\r
 \r
     /**\r
@@ -258,6 +271,79 @@ public class SdkRepoSourceTest extends TestCase {
         for (Package p : pkgs) {\r
             assertTrue(p.getArchives().length >= 1);\r
         }\r
+\r
+        // Check the extra packages path\r
+        ArrayList<String> extraPaths = new ArrayList<String>();\r
+        for (Package p : pkgs) {\r
+            if (p instanceof ExtraPackage) {\r
+                extraPaths.add(((ExtraPackage) p).getPath());\r
+            }\r
+        }\r
+        assertEquals(\r
+                "[usb_driver, extra_api_dep]",\r
+                Arrays.toString(extraPaths.toArray()));\r
+    }\r
+\r
+    /**\r
+     * Validate what we can load from repository in schema version 3\r
+     */\r
+    public void testLoadXml_3() throws Exception {\r
+        InputStream xmlStream = getTestResource(\r
+                    "/com/android/sdklib/testdata/repository_sample_3.xml");\r
+\r
+        // guess the version from the XML document\r
+        int version = mSource._getXmlSchemaVersion(xmlStream);\r
+        assertEquals(3, version);\r
+\r
+        Boolean[] validatorFound = new Boolean[] { Boolean.FALSE };\r
+        String[] validationError = new String[] { null };\r
+        String url = "not-a-valid-url://" + SdkRepoConstants.URL_DEFAULT_FILENAME;\r
+\r
+        String uri = mSource._validateXml(xmlStream, url, version, validationError, validatorFound);\r
+        assertEquals(Boolean.TRUE, validatorFound[0]);\r
+        assertEquals(null, validationError[0]);\r
+        assertEquals(SdkRepoConstants.getSchemaUri(3), uri);\r
+\r
+        // Validation was successful, load the document\r
+        MockMonitor monitor = new MockMonitor();\r
+        Document doc = mSource._getDocument(xmlStream, monitor);\r
+        assertNotNull(doc);\r
+\r
+        // Get the packages\r
+        assertTrue(mSource._parsePackages(doc, uri, monitor));\r
+\r
+        assertEquals("Found SDK Platform Android 1.0, API 1, revision 3\n" +\r
+                    "Found Documentation for Android SDK, API 1, revision 1\n" +\r
+                    "Found SDK Platform Android 1.1, API 2, revision 12\n" +\r
+                    "Found SDK Platform Android Pastry Preview, revision 3\n" +\r
+                    "Found Android SDK Tools, revision 1\n" +\r
+                    "Found Documentation for Android SDK, API 2, revision 42\n" +\r
+                    "Found Android SDK Tools, revision 42\n" +\r
+                    "Found Android SDK Platform-tools, revision 3\n" +\r
+                    "Found A Usb Driver package, revision 43 (Obsolete)\n" +\r
+                    "Found Android Vendor Extra Api Dep package, revision 2 (Obsolete)\n" +\r
+                    "Found Samples for SDK API 14, revision 24 (Obsolete)\n",\r
+                monitor.getCapturedDescriptions());\r
+        assertEquals("", monitor.getCapturedResults());\r
+\r
+        // check the packages we found... we expected to find 13 packages with each at least\r
+        // one archive.\r
+        Package[] pkgs = mSource.getPackages();\r
+        assertEquals(11, pkgs.length);\r
+        for (Package p : pkgs) {\r
+            assertTrue(p.getArchives().length >= 1);\r
+        }\r
+\r
+        // Check the extra packages path\r
+        ArrayList<String> extraPaths = new ArrayList<String>();\r
+        for (Package p : pkgs) {\r
+            if (p instanceof ExtraPackage) {\r
+                extraPaths.add(((ExtraPackage) p).getPath());\r
+            }\r
+        }\r
+        assertEquals(\r
+                "[a-usb_driver, android_vendor-extra_api_dep]",\r
+                Arrays.toString(extraPaths.toArray()));\r
     }\r
 \r
     /**\r
index 8ebafac..4e3f750 100755 (executable)
     </sdk:add-on>
 
     <sdk:extra>
+        <sdk:vendor>a</sdk:vendor>
         <sdk:path>usb_driver</sdk:path>
         <sdk:uses-license ref="license2" />
         <sdk:revision>43</sdk:revision>
     </sdk:extra>
 
     <sdk:extra>
+        <sdk:vendor>android_vendor</sdk:vendor>
         <sdk:path>extra_api_dep</sdk:path>
         <sdk:uses-license ref="license2" />
         <sdk:revision>2</sdk:revision>
index 5da497a..05a9c79 100755 (executable)
     </sdk:platform-tool>
 
     <sdk:extra>
+        <sdk:vendor>a</sdk:vendor>
         <sdk:path>usb_driver</sdk:path>
         <sdk:uses-license ref="license2" />
         <sdk:revision>43</sdk:revision>
     </sdk:extra>
 
     <sdk:extra>
+        <sdk:vendor>android_vendor</sdk:vendor>
         <sdk:path>extra_api_dep</sdk:path>
         <sdk:uses-license ref="license2" />
         <sdk:revision>2</sdk:revision>