import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
import com.android.sdklib.repository.SdkRepoConstants;\r
+import com.android.util.Pair;\r
\r
import org.w3c.dom.Node;\r
\r
* Represents an add-on XML node in an SDK repository.\r
*/\r
public class AddonPackage extends Package\r
- implements IPackageVersion, IPlatformDependency, IExactApiLevelDependency {\r
+ implements IPackageVersion, IPlatformDependency, IExactApiLevelDependency, ILayoutlibVersion {\r
\r
private static final String PROP_NAME = "Addon.Name"; //$NON-NLS-1$\r
private static final String PROP_VENDOR = "Addon.Vendor"; //$NON-NLS-1$\r
private final String mName;\r
private final AndroidVersion mVersion;\r
\r
+ /**\r
+ * The helper handling the layoutlib version.\r
+ */\r
+ private final LayoutlibVersionMixin mLayoutlibVersion;\r
+\r
/** An add-on library. */\r
public static class Lib {\r
private final String mName;\r
mVersion = new AndroidVersion(apiLevel, codeName);\r
\r
mLibs = parseLibs(XmlParserUtils.getFirstChild(packageNode, SdkRepoConstants.NODE_LIBS));\r
+\r
+ mLayoutlibVersion = new LayoutlibVersionMixin(packageNode);\r
}\r
\r
/**\r
mVersion = target.getVersion();\r
mName = target.getName();\r
mVendor = target.getVendor();\r
+ mLayoutlibVersion = new LayoutlibVersionMixin(props);\r
\r
IOptionalLibrary[] optLibs = target.getOptionalLibraries();\r
if (optLibs == null || optLibs.length == 0) {\r
super.saveProperties(props);\r
\r
mVersion.saveProperties(props);\r
+ mLayoutlibVersion.saveProperties(props);\r
+\r
if (mName != null) {\r
props.setProperty(PROP_NAME, mName);\r
}\r
}\r
\r
/**\r
+ * Returns the layoutlib version.\r
+ * <p/>\r
+ * The first integer is the API of layoublib, which should be > 0.\r
+ * It will be equal to {@link ILayoutlibVersion#LAYOUTLIB_API_NOT_SPECIFIED} (0)\r
+ * if the layoutlib version isn't specified.\r
+ * <p/>\r
+ * The second integer is the revision for that given API. It is >= 0\r
+ * and works as a minor revision number, incremented for the same API level.\r
+ *\r
+ * @since sdk-addon-2.xsd\r
+ */\r
+ public Pair<Integer, Integer> getLayoutlibVersion() {\r
+ return mLayoutlibVersion.getLayoutlibVersion();\r
+ }\r
+\r
+ /**\r
* Returns a description of this package that is suitable for a list display.\r
* <p/>\r
* {@inheritDoc}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2011 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
+import com.android.util.Pair;\r
+\r
+/**\r
+ * Interface used to decorate a {@link Package} that provides a version for layout lib.\r
+ */\r
+public interface ILayoutlibVersion {\r
+\r
+ public static final String PROP_LAYOUTLIB_API = "Layoutlib.Api"; //$NON-NLS-1$\r
+ public static final String PROP_LAYOUTLIB_REV = "Layoutlib.Revision"; //$NON-NLS-1$\r
+ public static final int LAYOUTLIB_API_NOT_SPECIFIED = 0;\r
+ public static final int LAYOUTLIB_REV_NOT_SPECIFIED = 0;\r
+\r
+ /**\r
+ * Returns the layoutlib version. Mandatory starting with repository XSD rev 4.\r
+ * <p/>\r
+ * The first integer is the API of layoublib, which should be > 0.\r
+ * It will be equal to {@link #LAYOUTLIB_API_NOT_SPECIFIED} (0) if the layoutlib\r
+ * version isn't specified.\r
+ * <p/>\r
+ * The second integer is the revision for that given API. It is >= 0\r
+ * and works as a minor revision number, incremented for the same API level.\r
+ *\r
+ * @since sdk-repository-4.xsd\r
+ */\r
+ public Pair<Integer, Integer> getLayoutlibVersion();\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2011 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
+import com.android.sdklib.repository.RepoConstants;\r
+import com.android.util.Pair;\r
+\r
+import org.w3c.dom.Node;\r
+\r
+import java.util.Properties;\r
+\r
+/**\r
+ * Helper class to handle the layoutlib version provided by a package.\r
+ */\r
+public class LayoutlibVersionMixin implements ILayoutlibVersion {\r
+\r
+ /**\r
+ * The layoutlib version.\r
+ * The first integer is the API of layoublib, which should be > 0.\r
+ * It will be equal to {@link #LAYOUTLIB_API_NOT_SPECIFIED} (0) if the layoutlib\r
+ * version isn't specified.\r
+ * The second integer is the revision for that given API. It is >= 0\r
+ * and works as a minor revision number, incremented for the same API level.\r
+ */\r
+ private final Pair<Integer, Integer> mLayoutlibVersion;\r
+\r
+ /**\r
+ * Parses an XML node to process the {@code <layoutlib>} element.\r
+ *\r
+ * The layoutlib element is new in the XSD rev 4, so we need to cope with it missing\r
+ * in earlier XMLs.\r
+ */\r
+ public LayoutlibVersionMixin(Node pkgNode) {\r
+\r
+ int api = LAYOUTLIB_API_NOT_SPECIFIED;\r
+ int rev = LAYOUTLIB_REV_NOT_SPECIFIED;\r
+\r
+ Node layoutlibNode = XmlParserUtils.getFirstChild(pkgNode, RepoConstants.NODE_LAYOUT_LIB);\r
+\r
+ if (layoutlibNode != null) {\r
+ api = XmlParserUtils.getXmlInt(layoutlibNode, RepoConstants.NODE_API, 0);\r
+ rev = XmlParserUtils.getXmlInt(layoutlibNode, RepoConstants.NODE_REVISION, 0);\r
+ }\r
+\r
+ mLayoutlibVersion = Pair.of(api, rev);\r
+ }\r
+\r
+ /**\r
+ * Parses the layoutlib version optionally available in the given {@link Properties}.\r
+ */\r
+ public LayoutlibVersionMixin(Properties props) {\r
+ int layoutlibApi = Integer.parseInt(\r
+ Package.getProperty(props, PROP_LAYOUTLIB_API,\r
+ Integer.toString(LAYOUTLIB_API_NOT_SPECIFIED)));\r
+ int layoutlibRev = Integer.parseInt(\r
+ Package.getProperty(props, PROP_LAYOUTLIB_REV,\r
+ Integer.toString(LAYOUTLIB_REV_NOT_SPECIFIED)));\r
+ mLayoutlibVersion = Pair.of(layoutlibApi, layoutlibRev);\r
+ }\r
+\r
+ /**\r
+ * Stores the layoutlib version in the given {@link Properties}.\r
+ */\r
+ void saveProperties(Properties props) {\r
+ if (mLayoutlibVersion.getFirst().intValue() != LAYOUTLIB_API_NOT_SPECIFIED) {\r
+ props.setProperty(PROP_LAYOUTLIB_API, mLayoutlibVersion.getFirst().toString());\r
+ props.setProperty(PROP_LAYOUTLIB_REV, mLayoutlibVersion.getSecond().toString());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the layoutlib version.\r
+ * <p/>\r
+ * The first integer is the API of layoublib, which should be > 0.\r
+ * It will be equal to {@link #LAYOUTLIB_API_NOT_SPECIFIED} (0) if the layoutlib\r
+ * version isn't specified.\r
+ * <p/>\r
+ * The second integer is the revision for that given API. It is >= 0\r
+ * and works as a minor revision number, incremented for the same API level.\r
+ *\r
+ * @since sdk-repository-4.xsd and sdk-addon-2.xsd\r
+ */\r
+ public Pair<Integer, Integer> getLayoutlibVersion() {\r
+ return mLayoutlibVersion;\r
+ }\r
+}\r
* @return The string value of the given key in the properties, or null if the key\r
* isn't found or if {@code props} is null.\r
*/\r
- protected String getProperty(Properties props, String propKey, String defaultValue) {\r
+ static String getProperty(Properties props, String propKey, String defaultValue) {\r
if (props == null) {\r
return defaultValue;\r
}\r
/**\r
* Represents a platform XML node in an SDK repository.\r
*/\r
-public class PlatformPackage extends MinToolsPackage implements IPackageVersion {\r
+public class PlatformPackage extends MinToolsPackage implements IPackageVersion, ILayoutlibVersion {\r
\r
- public static final String PROP_VERSION = "Platform.Version"; //$NON-NLS-1$\r
- public static final String PROP_LAYOUTLIB_API = "Platform.Layoutlib.Api"; //$NON-NLS-1$\r
- public static final String PROP_LAYOUTLIB_REV = "Platform.Layoutlib.Revision"; //$NON-NLS-1$\r
- public static final int LAYOUTLIB_API_NOT_SPECIFIED = 0;\r
- public static final int LAYOUTLIB_REV_NOT_SPECIFIED = 0;\r
+ public static final String PROP_VERSION = "Platform.Version";\r
\r
/** The package version, for platform, add-on and doc packages. */\r
private final AndroidVersion mVersion;\r
private final String mVersionName;\r
\r
/**\r
- * The layoutlib version. Mandatory starting with XSD rev 4.\r
- * The first integer is the API of layoublib, which should be > 0.\r
- * It will be equal to {@link #LAYOUTLIB_API_NOT_SPECIFIED} (0) if the layoutlib\r
- * version isn't specified.\r
- * The second integer is the revision for that given API. It is >= 0\r
- * and works as a minor revision number, incremented for the same API level.\r
+ * The helper handling the layoutlib version.\r
*/\r
- private final Pair<Integer, Integer> mLayoutlibVersion;\r
+ private final LayoutlibVersionMixin mLayoutlibVersion;\r
\r
/**\r
* Creates a new platform package from the attributes and elements of the given XML node.\r
\r
mVersion = new AndroidVersion(apiLevel, codeName);\r
\r
- mLayoutlibVersion = parseLayoutlib(\r
- XmlParserUtils.getFirstChild(packageNode, SdkRepoConstants.NODE_LAYOUT_LIB));\r
- }\r
-\r
- /**\r
- * Parses an XML node to process the {@code <layoutlib>} element.\r
- *\r
- * The layoutlib element is new in the XSD rev 4, so we need to cope with it missing\r
- * in earlier XMLs even though it is now mandatory.\r
- */\r
- private Pair<Integer, Integer> parseLayoutlib(Node layoutlibNode) {\r
- int api = LAYOUTLIB_API_NOT_SPECIFIED;\r
- int rev = LAYOUTLIB_REV_NOT_SPECIFIED;\r
- if (layoutlibNode != null) {\r
- api = XmlParserUtils.getXmlInt(layoutlibNode, SdkRepoConstants.NODE_API, 0);\r
- rev = XmlParserUtils.getXmlInt(layoutlibNode, SdkRepoConstants.NODE_REVISION, 0);\r
- }\r
-\r
- return Pair.of(api, rev);\r
+ mLayoutlibVersion = new LayoutlibVersionMixin(packageNode);\r
}\r
\r
/**\r
\r
mVersion = target.getVersion();\r
mVersionName = target.getVersionName();\r
-\r
- int layoutlibApi = Integer.parseInt(\r
- getProperty(props, PROP_LAYOUTLIB_API, Integer.toString(LAYOUTLIB_API_NOT_SPECIFIED)));\r
- int layoutlibRev = Integer.parseInt(\r
- getProperty(props, PROP_LAYOUTLIB_REV, Integer.toString(LAYOUTLIB_REV_NOT_SPECIFIED)));\r
- mLayoutlibVersion = Pair.of(layoutlibApi, layoutlibRev);\r
+ mLayoutlibVersion = new LayoutlibVersionMixin(props);\r
}\r
\r
/**\r
super.saveProperties(props);\r
\r
mVersion.saveProperties(props);\r
+ mLayoutlibVersion.saveProperties(props);\r
\r
if (mVersionName != null) {\r
props.setProperty(PROP_VERSION, mVersionName);\r
}\r
\r
- if (mLayoutlibVersion.getFirst().intValue() != LAYOUTLIB_API_NOT_SPECIFIED) {\r
- props.setProperty(PROP_LAYOUTLIB_API, mLayoutlibVersion.getFirst().toString());\r
- props.setProperty(PROP_LAYOUTLIB_REV, mLayoutlibVersion.getSecond().toString());\r
- }\r
}\r
\r
/** Returns the version, a string, for platform packages. */\r
* Returns the layoutlib version. Mandatory starting with repository XSD rev 4.\r
* <p/>\r
* The first integer is the API of layoublib, which should be > 0.\r
- * It will be equal to {@link #LAYOUTLIB_API_NOT_SPECIFIED} (0) if the layoutlib\r
- * version isn't specified.\r
+ * It will be equal to {@link ILayoutlibVersion#LAYOUTLIB_API_NOT_SPECIFIED} (0)\r
+ * if the layoutlib version isn't specified.\r
* <p/>\r
* The second integer is the revision for that given API. It is >= 0\r
* and works as a minor revision number, incremented for the same API level.\r
* @since sdk-repository-4.xsd\r
*/\r
public Pair<Integer, Integer> getLayoutlibVersion() {\r
- return mLayoutlibVersion;\r
+ return mLayoutlibVersion.getLayoutlibVersion();\r
}\r
\r
/**\r
<extra> packages.
- v2 is used by the SDK Updater in Tools r12.
- <extra> element now has a <project-files> element that contains 1 or
- or more <path>, each indicating the relative path of a file that this package
- can contribute to installed projects.
+ - <extra> element now has a <project-files> element that contains 1 or
+ or more <path>, each indicating the relative path of a file that this package
+ can contribute to installed projects.
+ - <addon> element now has an optional <layoutlib> that indicates the API
+ and revision of the layout library for this particular add-on, if any.
-->
<xsd:element name="sdk-addon" type="sdk:repositoryType" />
<xsd:element name="api-level" type="xsd:positiveInteger" />
<!-- The optional codename for this add-on, if it's a preview. -->
<xsd:element name="codename" type="xsd:string" minOccurs="0" />
-
<!-- The revision, an int > 0, incremented each time a new
package is generated. -->
<xsd:element name="revision" type="xsd:positiveInteger" />
+
+ <!-- An add-on can declare 0 or more libraries.
+ This element is mandatory but it can be empty.
+ -->
+
+ <xsd:element name="libs">
+ <xsd:complexType>
+ <xsd:sequence minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="lib">
+ <xsd:complexType>
+ <xsd:all>
+ <!-- The name of the library. -->
+ <xsd:element name="name" type="xsd:normalizedString" />
+ <!-- The optional description of this add-on library. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:sequence>
+ </xsd:complexType>
+ </xsd:element>
+
+ <!-- optional elements -->
+
<!-- The optional license of this package. If present, users will have
to agree to it before downloading. -->
<xsd:element name="uses-license" type="sdk:usesLicenseType" minOccurs="0" />
The string content is however currently not defined and ignored. -->
<xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
- <!-- An add-on can declare 0 or more libraries. -->
+ <!-- Information on the layoutlib packaged in this platform. -->
+ <xsd:element name="layoutlib" type="sdk:layoutlibType" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
- <xsd:element name="libs">
- <xsd:complexType>
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:element name="lib">
- <xsd:complexType>
- <xsd:all>
- <!-- The name of the library. -->
- <xsd:element name="name" type="xsd:normalizedString" />
- <!-- The optional description of this add-on library. -->
- <xsd:element name="description" type="xsd:string" minOccurs="0" />
- </xsd:all>
- </xsd:complexType>
- </xsd:element>
- </xsd:sequence>
- </xsd:complexType>
- </xsd:element>
+ <!-- The definition of a layout library used by an addon. -->
+
+ <xsd:complexType name="layoutlibType" >
+ <xsd:annotation>
+ <xsd:documentation>
+ Version information for a layoutlib included in an addon.
+ .</xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The layoutlib API level, an int > 0,
+ incremented with each new incompatible lib. -->
+ <xsd:element name="api" type="xsd:positiveInteger" />
+ <!-- The incremental minor revision for that API, e.g. in case of bug fixes.
+ Optional. An int >= 0, assumed to be 0 if the element is missing. -->
+ <xsd:element name="revision" type="xsd:nonNegativeInteger" minOccurs="0" />
</xsd:all>
</xsd:complexType>
<xsd:element name="api-level" type="xsd:positiveInteger" />
<!-- The optional codename for this platform, if it's a preview. -->
<xsd:element name="codename" type="xsd:string" minOccurs="0" />
-
<!-- The revision, an int > 0, incremented each time a new
package is generated. -->
<xsd:element name="revision" type="xsd:positiveInteger" />
<xsd:complexType name="layoutlibType" >
<xsd:annotation>
- <xsd:documentation>An SDK tool package.</xsd:documentation>
+ <xsd:documentation>
+ Version information for a layoutlib included in a platform.
+ </xsd:documentation>
</xsd:annotation>
<xsd:all>
<!-- The layoutlib API level, an int > 0,
/** The name, a string, for add-on packages or for libraries. */\r
public static final String NODE_NAME = "name"; //$NON-NLS-1$\r
\r
+\r
+ /** A layoutlib package. */\r
+ public static final String NODE_LAYOUT_LIB = "layoutlib"; //$NON-NLS-1$\r
+ /** The API integer for a layoutlib element. */\r
+ public static final String NODE_API = "api"; //$NON-NLS-1$\r
+\r
/** The libs container, optional for an add-on. */\r
public static final String NODE_LIBS = "libs"; //$NON-NLS-1$\r
/** A lib element in a libs container. */\r
public static final String NODE_SAMPLE = "sample"; //$NON-NLS-1$\r
\r
\r
- /** A layoutlib package. */\r
- public static final String NODE_LAYOUT_LIB = "layoutlib"; //$NON-NLS-1$\r
- /** The API integer for a layoutlib element. */\r
- public static final String NODE_API = "api"; //$NON-NLS-1$\r
-\r
-\r
/**\r
* List of possible nodes in a repository XML. Used to populate options automatically\r
* in the no-GUI mode.\r
\r
import com.android.sdklib.SdkManager;\r
import com.android.sdklib.repository.SdkAddonConstants;\r
+import com.android.util.Pair;\r
\r
import org.w3c.dom.Document;\r
\r
\r
// check the packages we found... we expected to find 11 packages with each at least\r
// one archive.\r
+ // Note the order doesn't necessary match the one from the\r
+ // assertEquald(getCapturedVerboseLog) because packages are sorted using the\r
+ // Packages' sorting order, e.g. all platforms are sorted by descending API level, etc.\r
Package[] pkgs = mSource.getPackages();\r
+\r
assertEquals(6, pkgs.length);\r
for (Package p : pkgs) {\r
assertTrue(p.getArchives().length >= 1);\r
}\r
\r
+ // Check the layoutlib of the platform packages.\r
+ ArrayList<Pair<Integer, Integer>> layoutlibVers = new ArrayList<Pair<Integer,Integer>>();\r
+ for (Package p : pkgs) {\r
+ if (p instanceof AddonPackage) {\r
+ layoutlibVers.add(((AddonPackage) p).getLayoutlibVersion());\r
+ }\r
+ }\r
+ assertEquals(\r
+ "[Pair [first=3, second=42], " + // for #3 "This add-on has no libraries"\r
+ "Pair [first=0, second=0], " + // for #2 "My Second add-on"\r
+ "Pair [first=5, second=0]]", // for #1 "My First add-on"\r
+ Arrays.toString(layoutlibVers.toArray()));\r
+\r
+\r
// Check the extra packages path, vendor, install folder\r
\r
final String osSdkPath = "SDK";\r
<sdk:name>com.android.mymaps</sdk:name>
</sdk:lib>
</sdk:libs>
+ <sdk:layoutlib>
+ <sdk:api>5</sdk:api>
+ <sdk:revision>0</sdk:revision>
+ </sdk:layoutlib>
</sdk:add-on>
<sdk:add-on>
</sdk:lib>
</sdk:libs>
<sdk:uses-license ref="license2" />
+ <!-- No layoutlib element in this package. It's optional. -->
</sdk:add-on>
<sdk:add-on>
</sdk:archives>
<!-- The libs node is mandatory, however it can be empty. -->
<sdk:libs />
+ <sdk:layoutlib>
+ <sdk:api>3</sdk:api>
+ <sdk:revision>42</sdk:revision>
+ </sdk:layoutlib>
</sdk:add-on>
<sdk:extra>
<sdk:min-tools-rev>3</sdk:min-tools-rev>
<sdk:min-api-level>42</sdk:min-api-level>
<sdk:obsolete></sdk:obsolete>
+ <!-- No project-files element in this package. -->
</sdk:extra>
</sdk:sdk-addon>