diff options
| author | Raphael <raphael@google.com> | 2009-11-16 13:06:54 -0800 |
|---|---|---|
| committer | Raphael <raphael@google.com> | 2009-11-16 13:07:43 -0800 |
| commit | 84e2e85c08f1a66de28fc74a23ef7baf9be920df (patch) | |
| tree | 229488c533322ebfd0a84564698bf56987c8bb7f /sdkmanager | |
| parent | d0d97b9d6192cdc039053deda9e395b9b87fb6c1 (diff) | |
| parent | 85a5f9325f24ed2b45eb7dad927e60cccd71a70d (diff) | |
| download | sdk-84e2e85c08f1a66de28fc74a23ef7baf9be920df.zip sdk-84e2e85c08f1a66de28fc74a23ef7baf9be920df.tar.gz sdk-84e2e85c08f1a66de28fc74a23ef7baf9be920df.tar.bz2 | |
resolved conflicts for merge of 0da4f158 to eclair
Fixes a merge eclair-sdk => eclair conflict of
SDK Manager: phase 1 of support for future schemas
SDK BUG 2252825
Change-Id: I7530bdb7315439416abad114ef59208f8d4b3ab8
Diffstat (limited to 'sdkmanager')
12 files changed, 1440 insertions, 173 deletions
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java index f1cdf1d..0dec3bb 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java @@ -143,12 +143,13 @@ public class AddonPackage extends Package implements IPackageVersion { ArrayList<Lib> libs = new ArrayList<Lib>();
if (libsNode != null) {
+ String nsUri = libsNode.getNamespaceURI();
for(Node child = libsNode.getFirstChild();
child != null;
child = child.getNextSibling()) {
if (child.getNodeType() == Node.ELEMENT_NODE &&
- SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI()) &&
+ nsUri.equals(child.getNamespaceURI()) &&
SdkRepository.NODE_LIB.equals(child.getLocalName())) {
libs.add(parseLib(child));
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java index 040668c..18774ea 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java @@ -96,6 +96,11 @@ public class Archive implements IDescription { return mUiName;
}
+ /** Returns the XML name of the OS. */
+ public String getXmlName() {
+ return toString().toLowerCase();
+ }
+
/**
* Returns the current OS as one of the {@link Os} enum values or null.
*/
@@ -113,6 +118,16 @@ public class Archive implements IDescription { return null;
}
+
+ /** Returns true if this OS is compatible with the current one. */
+ public boolean isCompatible() {
+ if (this == ANY) {
+ return true;
+ }
+
+ Os os = getCurrentOs();
+ return this == os;
+ }
}
/** The Architecture that this archive can be downloaded on. */
@@ -133,6 +148,11 @@ public class Archive implements IDescription { return mUiName;
}
+ /** Returns the XML name of the architecture. */
+ public String getXmlName() {
+ return toString().toLowerCase();
+ }
+
/**
* Returns the current architecture as one of the {@link Arch} enum values or null.
*/
@@ -154,6 +174,16 @@ public class Archive implements IDescription { return null;
}
+
+ /** Returns true if this architecture is compatible with the current one. */
+ public boolean isCompatible() {
+ if (this == ANY) {
+ return true;
+ }
+
+ Arch arch = getCurrentArch();
+ return this == arch;
+ }
}
private final Os mOs;
@@ -324,27 +354,7 @@ public class Archive implements IDescription { * Returns true if this archive can be installed on the current platform.
*/
public boolean isCompatible() {
- // Check OS
- Os os = getOs();
-
- if (os != Os.ANY) {
- Os os2 = Os.getCurrentOs();
- if (os2 != os) {
- return false;
- }
- }
-
- // Check Arch
- Arch arch = getArch();
-
- if (arch != Arch.ANY) {
- Arch arch2 = Arch.getCurrentArch();
- if (arch2 != arch) {
- return false;
- }
- }
-
- return true;
+ return getOs().isCompatible() && getArch().isCompatible();
}
/**
@@ -1053,8 +1063,7 @@ public class Archive implements IDescription { /**
* Sets the executable Unix permission (0777) on a file or folder.
* @param file The file to set permissions on.
- * @param unixMode the permissions as received from {@link ZipArchiveEntry#getUnixMode()}.
- * @throws IOException
+ * @throws IOException If an I/O error occurs
*/
private void setExecutablePermission(File file) throws IOException {
Runtime.getRuntime().exec(new String[] {
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java index 657bb14..b43acc7 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java @@ -211,12 +211,13 @@ public abstract class Package implements IDescription { ArrayList<Archive> archives = new ArrayList<Archive>();
if (archivesNode != null) {
+ String nsUri = archivesNode.getNamespaceURI();
for(Node child = archivesNode.getFirstChild();
child != null;
child = child.getNextSibling()) {
if (child.getNodeType() == Node.ELEMENT_NODE &&
- SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI()) &&
+ nsUri.equals(child.getNamespaceURI()) &&
SdkRepository.NODE_ARCHIVE.equals(child.getLocalName())) {
archives.add(parseArchive(child));
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java index 573454d..6e8d984 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/RepoSource.java @@ -16,9 +16,13 @@ package com.android.sdklib.internal.repository;
+import com.android.sdklib.internal.repository.Archive.Arch;
+import com.android.sdklib.internal.repository.Archive.Os;
import com.android.sdklib.repository.SdkRepository;
import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@@ -30,6 +34,7 @@ import java.io.InputStream; import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.regex.Pattern;
import javax.net.ssl.SSLKeyException;
import javax.xml.XMLConstants;
@@ -156,15 +161,23 @@ public class RepoSource implements IDescription { mFetchError = null;
Exception[] exception = new Exception[] { null };
ByteArrayInputStream xml = fetchUrl(url, exception);
- boolean validated = false;
+ Document validatedDoc = null;
+ String validatedUri = null;
if (xml != null) {
monitor.setDescription("Validate XML");
- validated = validateXml(xml, url, monitor);
+ String uri = validateXml(xml, url, monitor);
+ if (uri != null) {
+ validatedDoc = getDocument(xml, monitor);
+ validatedUri = uri;
+ } else {
+ validatedDoc = findAlternateToolsXml(xml);
+ validatedUri = SdkRepository.NS_SDK_REPOSITORY;
+ }
}
// If we failed the first time and the URL doesn't explicitly end with
// our filename, make another tentative after changing the URL.
- if (!validated && !url.endsWith(SdkRepository.URL_DEFAULT_XML_FILE)) {
+ if (validatedDoc == null && !url.endsWith(SdkRepository.URL_DEFAULT_XML_FILE)) {
if (!url.endsWith("/")) { //$NON-NLS-1$
url += "/"; //$NON-NLS-1$
}
@@ -172,10 +185,17 @@ public class RepoSource implements IDescription { xml = fetchUrl(url, exception);
if (xml != null) {
- validated = validateXml(xml, url, monitor);
+ String uri = validateXml(xml, url, monitor);
+ if (uri != null) {
+ validatedDoc = getDocument(xml, monitor);
+ validatedUri = uri;
+ } else {
+ validatedDoc = findAlternateToolsXml(xml);
+ validatedUri = SdkRepository.NS_SDK_REPOSITORY;
+ }
}
- if (validated) {
+ if (validatedDoc != null) {
// If the second tentative succeeded, indicate it in the console
// with the URL that worked.
monitor.setResult("Repository found at %1$s", url);
@@ -209,7 +229,7 @@ public class RepoSource implements IDescription { }
// Stop here if we failed to validate the XML. We don't want to load it.
- if (!validated) {
+ if (validatedDoc == null) {
return;
}
@@ -218,7 +238,7 @@ public class RepoSource implements IDescription { if (xml != null) {
monitor.setDescription("Parse XML");
monitor.incProgress(1);
- parsePackages(xml, monitor);
+ parsePackages(validatedDoc, validatedUri, monitor);
if (mPackages == null || mPackages.length == 0) {
mDescription += "\nNo packages found.";
} else if (mPackages.length == 1) {
@@ -293,43 +313,324 @@ public class RepoSource implements IDescription { }
/**
- * Validates this XML against the SDK Repository schema.
- * Returns true if the XML was correctly validated.
+ * Validates this XML against one of the possible SDK Repository schema, starting
+ * by the most recent one.
+ * If the XML was correctly validated, returns the schema that worked.
+ * If no schema validated the XML, returns null.
*/
- private boolean validateXml(ByteArrayInputStream xml, String url, ITaskMonitor monitor) {
+ private String validateXml(ByteArrayInputStream xml, String url, ITaskMonitor monitor) {
- try {
- Validator validator = getValidator();
+ String lastError = null;
+ String extraError = null;
+ for (int version = SdkRepository.XSD_LATEST_VERSION; version >= 1; version--) {
+ try {
+ Validator validator = getValidator(version);
+
+ if (validator == null) {
+ lastError = "XML verification failed for %1$s.\nNo suitable XML Schema Validator could be found in your Java environment. Please consider updating your version of Java.";
+ continue;
+ }
+
+ xml.reset();
+ // Validation throws a bunch of possible Exceptions on failure.
+ validator.validate(new StreamSource(xml));
+ return SdkRepository.getSchemaUri(version);
- if (validator == null) {
- monitor.setResult(
- "XML verification failed for %1$s.\nNo suitable XML Schema Validator could be found in your Java environment. Please consider updating your version of Java.",
- url);
- return false;
+ } catch (Exception e) {
+ lastError = "XML verification failed for %1$s.\nError: %2$s";
+ extraError = e.getMessage();
+ if (extraError == null) {
+ extraError = e.getClass().getName();
+ }
}
+ }
+
+ if (lastError != null) {
+ monitor.setResult(lastError, url, extraError);
+ }
+ return null;
+ }
+ /**
+ * The purpose of this method is to support forward evolution of our schema.
+ * <p/>
+ * At this point, we know that xml does not point to any schema that this version of
+ * the tool know how to process, so it's not one of the possible 1..N versions of our
+ * XSD schema.
+ * <p/>
+ * We thus try to interpret the byte stream as a possible XML stream. It may not be
+ * one at all in the first place. If it looks anything line an XML schema, we try to
+ * find its <tool> elements. If we find any, we recreate a suitable document
+ * that conforms to what we expect from our XSD schema with only those elements.
+ * To be valid, the <tool> element must have at least one <archive>
+ * compatible with this platform.
+ *
+ * If we don't find anything suitable, we drop the whole thing.
+ *
+ * @param xml The input XML stream. Can be null.
+ * @return Either a new XML document conforming to our schema with at least one <tool>
+ * element or null.
+ */
+ protected Document findAlternateToolsXml(InputStream xml) {
+ // Note: protected for unit-test access
+
+ if (xml == null) {
+ return null;
+ }
+
+ // Reset the stream if it supports that operation.
+ // At runtime we use a ByteArrayInputStream which can be reset; however for unit tests
+ // we use a FileInputStream that doesn't support resetting and is read-once.
+ try {
xml.reset();
- validator.validate(new StreamSource(xml));
- return true;
+ } catch (IOException e1) {
+ // ignore if not supported
+ }
+
+ // Get an XML document
+
+ Document oldDoc = null;
+ Document newDoc = null;
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setIgnoringComments(false);
+ factory.setValidating(false);
+
+ // Parse the old document using a non namespace aware builder
+ factory.setNamespaceAware(false);
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ oldDoc = builder.parse(xml);
+
+ // Prepare a new document using a namespace aware builder
+ factory.setNamespaceAware(true);
+ builder = factory.newDocumentBuilder();
+ newDoc = builder.newDocument();
} catch (Exception e) {
- String s = e.getMessage();
- if (s == null) {
- s = e.getClass().getName();
+ // Failed to get builder factor
+ // Failed to create XML document builder
+ // Failed to parse XML document
+ // Failed to read XML document
+ }
+
+ if (oldDoc == null || newDoc == null) {
+ return null;
+ }
+
+
+ // Check the root element is an xsd-schema with at least the following properties:
+ // <sdk:sdk-repository
+ // xmlns:sdk="http://schemas.android.com/sdk/android/repository/$N">
+ //
+ // Note that we don't have namespace support enabled, we just do it manually.
+
+ Pattern nsPattern = Pattern.compile(SdkRepository.NS_SDK_REPOSITORY_PATTERN);
+
+ Node oldRoot = null;
+ String prefix = null;
+ for (Node child = oldDoc.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child.getNodeType() == Node.ELEMENT_NODE) {
+ prefix = null;
+ String name = child.getNodeName();
+ int pos = name.indexOf(':');
+ if (pos > 0 && pos < name.length() - 1) {
+ prefix = name.substring(0, pos);
+ name = name.substring(pos + 1);
+ }
+ if (SdkRepository.NODE_SDK_REPOSITORY.equals(name)) {
+ NamedNodeMap attrs = child.getAttributes();
+ String xmlns = "xmlns"; //$NON-NLS-1$
+ if (prefix != null) {
+ xmlns += ":" + prefix; //$NON-NLS-1$
+ }
+ Node attr = attrs.getNamedItem(xmlns);
+ if (attr != null) {
+ String uri = attr.getNodeValue();
+ if (uri != null && nsPattern.matcher(uri).matches()) {
+ oldRoot = child;
+ break;
+ }
+ }
+ }
}
- monitor.setResult("XML verification failed for %1$s.\nError: %2$s",
- url,
- s);
}
- return false;
+ // we must have found the root node, and it must have an XML namespace prefix.
+ if (oldRoot == null || prefix == null || prefix.length() == 0) {
+ return null;
+ }
+
+ final String ns = SdkRepository.NS_SDK_REPOSITORY;
+ Element newRoot = newDoc.createElementNS(ns, SdkRepository.NODE_SDK_REPOSITORY);
+ newRoot.setPrefix(prefix);
+ newDoc.appendChild(newRoot);
+ int numTool = 0;
+
+ // Find an inner <tool> node and extract its required parameters
+
+ Node tool = null;
+ while ((tool = findChild(oldRoot, tool, prefix, SdkRepository.NODE_TOOL)) != null) {
+ // To be valid, the tool element must have:
+ // - a <revision> element with a number
+ // - an optional <uses-license> node, which we'll skip right now.
+ // (if we add it later, we must find the license declaration element too)
+ // - an <archives> element with one or more <archive> elements inside
+ // - one of the <archive> elements must have an "os" and "arch" attributes
+ // compatible with the current platform. Only keep the first such element found.
+ // - the <archive> element must contain a <size>, a <checksum> and a <url>.
+
+ try {
+ Node revision = findChild(tool, null, prefix, SdkRepository.NODE_REVISION);
+ Node archives = findChild(tool, null, prefix, SdkRepository.NODE_ARCHIVES);
+
+ if (revision == null || archives == null) {
+ continue;
+ }
+
+ int rev = 0;
+ try {
+ String content = revision.getTextContent();
+ content = content.trim();
+ rev = Integer.parseInt(content);
+ if (rev < 1) {
+ continue;
+ }
+ } catch (NumberFormatException ignore) {
+ continue;
+ }
+
+ Element newTool = newDoc.createElementNS(ns, SdkRepository.NODE_TOOL);
+ newTool.setPrefix(prefix);
+ appendChild(newTool, ns, prefix,
+ SdkRepository.NODE_REVISION, Integer.toString(rev));
+ Element newArchives = appendChild(newTool, ns, prefix,
+ SdkRepository.NODE_ARCHIVES, null);
+ int numArchives = 0;
+
+ Node archive = null;
+ while ((archive = findChild(archives,
+ archive,
+ prefix,
+ SdkRepository.NODE_ARCHIVE)) != null) {
+ try {
+ Os os = (Os) XmlParserUtils.getEnumAttribute(archive,
+ SdkRepository.ATTR_OS,
+ Os.values(),
+ null /*default*/);
+ Arch arch = (Arch) XmlParserUtils.getEnumAttribute(archive,
+ SdkRepository.ATTR_ARCH,
+ Arch.values(),
+ Arch.ANY);
+ if (os == null || !os.isCompatible() ||
+ arch == null || !arch.isCompatible()) {
+ continue;
+ }
+
+ Node node = findChild(archive, null, prefix, SdkRepository.NODE_URL);
+ String url = node == null ? null : node.getTextContent().trim();
+ if (url == null || url.length() == 0) {
+ continue;
+ }
+
+ node = findChild(archive, null, prefix, SdkRepository.NODE_SIZE);
+ long size = 0;
+ try {
+ size = Long.parseLong(node.getTextContent());
+ } catch (Exception e) {
+ // pass
+ }
+ if (size < 1) {
+ continue;
+ }
+
+ node = findChild(archive, null, prefix, SdkRepository.NODE_CHECKSUM);
+ // double check that the checksum element contains a type=sha1 attribute
+ if (node == null) {
+ continue;
+ }
+ NamedNodeMap attrs = node.getAttributes();
+ Node typeNode = attrs.getNamedItem(SdkRepository.ATTR_TYPE);
+ if (typeNode == null ||
+ !SdkRepository.ATTR_TYPE.equals(typeNode.getNodeName()) ||
+ !SdkRepository.SHA1_TYPE.equals(typeNode.getNodeValue())) {
+ continue;
+ }
+ String sha1 = node == null ? null : node.getTextContent().trim();
+ if (sha1 == null || sha1.length() != SdkRepository.SHA1_CHECKSUM_LEN) {
+ continue;
+ }
+
+ // Use that archive for the new tool element
+ Element ar = appendChild(newArchives, ns, prefix,
+ SdkRepository.NODE_ARCHIVE, null);
+ ar.setAttributeNS(ns, SdkRepository.ATTR_OS, os.getXmlName());
+ ar.setAttributeNS(ns, SdkRepository.ATTR_ARCH, arch.getXmlName());
+
+ appendChild(ar, ns, prefix, SdkRepository.NODE_URL, url);
+ appendChild(ar, ns, prefix, SdkRepository.NODE_SIZE, Long.toString(size));
+ Element cs = appendChild(ar, ns, prefix, SdkRepository.NODE_CHECKSUM, sha1);
+ cs.setAttributeNS(ns, SdkRepository.ATTR_TYPE, SdkRepository.SHA1_TYPE);
+
+ numArchives++;
+
+ } catch (Exception ignore1) {
+ // pass
+ }
+ } // while <archive>
+
+ if (numArchives > 0) {
+ newRoot.appendChild(newTool);
+ numTool++;
+ }
+ } catch (Exception ignore2) {
+ // pass
+ }
+ } // while <tool>
+
+ return numTool > 0 ? newDoc : null;
}
/**
- * Helper method that returns a validator for our XSD
+ * Helper method used by {@link #findAlternateToolsXml(InputStream)} to find a given
+ * element child in a root XML node.
*/
- private Validator getValidator() throws SAXException {
- InputStream xsdStream = SdkRepository.getXsdStream();
+ private Node findChild(Node rootNode, Node after, String prefix, String nodeName) {
+ nodeName = prefix + ":" + nodeName;
+ Node child = after == null ? rootNode.getFirstChild() : after.getNextSibling();
+ for(; child != null; child = child.getNextSibling()) {
+ if (child.getNodeType() == Node.ELEMENT_NODE && nodeName.equals(child.getNodeName())) {
+ return child;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Helper method used by {@link #findAlternateToolsXml(InputStream)} to create a new
+ * XML element into a parent element.
+ */
+ private Element appendChild(Element rootNode, String namespaceUri,
+ String prefix, String nodeName,
+ String nodeValue) {
+ Element node = rootNode.getOwnerDocument().createElementNS(namespaceUri, nodeName);
+ node.setPrefix(prefix);
+ if (nodeValue != null) {
+ node.setTextContent(nodeValue);
+ }
+ rootNode.appendChild(node);
+ return node;
+ }
+
+
+ /**
+ * Helper method that returns a validator for our XSD, or null if the current Java
+ * implementation can't process XSD schemas.
+ *
+ * @param version The version of the XML Schema.
+ * See {@link SdkRepository#getXsdStream(int)}
+ */
+ private Validator getValidator(int version) throws SAXException {
+ InputStream xsdStream = SdkRepository.getXsdStream(version);
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
if (factory == null) {
@@ -349,84 +650,74 @@ public class RepoSource implements IDescription { * Parse all packages defined in the SDK Repository XML and creates
* a new mPackages array with them.
*/
- private boolean parsePackages(ByteArrayInputStream xml, ITaskMonitor monitor) {
-
- try {
- Document doc = getDocument(xml);
-
- Node root = getFirstChild(doc, SdkRepository.NODE_SDK_REPOSITORY);
- if (root != null) {
-
- ArrayList<Package> packages = new ArrayList<Package>();
-
- // Parse license definitions
- HashMap<String, String> licenses = new HashMap<String, String>();
- for (Node child = root.getFirstChild();
- child != null;
- child = child.getNextSibling()) {
- if (child.getNodeType() == Node.ELEMENT_NODE &&
- SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI()) &&
- child.getLocalName().equals(SdkRepository.NODE_LICENSE)) {
- Node id = child.getAttributes().getNamedItem(SdkRepository.ATTR_ID);
- if (id != null) {
- licenses.put(id.getNodeValue(), child.getTextContent());
- }
+ protected boolean parsePackages(Document doc, String nsUri, ITaskMonitor monitor) {
+ // protected for unit-test acces
+
+ assert doc != null;
+
+ Node root = getFirstChild(doc, nsUri, SdkRepository.NODE_SDK_REPOSITORY);
+ if (root != null) {
+
+ ArrayList<Package> packages = new ArrayList<Package>();
+
+ // Parse license definitions
+ HashMap<String, String> licenses = new HashMap<String, String>();
+ for (Node child = root.getFirstChild();
+ child != null;
+ child = child.getNextSibling()) {
+ if (child.getNodeType() == Node.ELEMENT_NODE &&
+ nsUri.equals(child.getNamespaceURI()) &&
+ child.getLocalName().equals(SdkRepository.NODE_LICENSE)) {
+ Node id = child.getAttributes().getNamedItem(SdkRepository.ATTR_ID);
+ if (id != null) {
+ licenses.put(id.getNodeValue(), child.getTextContent());
}
}
+ }
- // Parse packages
- for (Node child = root.getFirstChild();
- child != null;
- child = child.getNextSibling()) {
- if (child.getNodeType() == Node.ELEMENT_NODE &&
- SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI())) {
- String name = child.getLocalName();
- Package p = null;
+ // Parse packages
+ for (Node child = root.getFirstChild();
+ child != null;
+ child = child.getNextSibling()) {
+ if (child.getNodeType() == Node.ELEMENT_NODE &&
+ nsUri.equals(child.getNamespaceURI())) {
+ String name = child.getLocalName();
+ Package p = null;
- try {
- // We can load addon and extra packages from all sources, either
- // internal or user sources.
- if (SdkRepository.NODE_ADD_ON.equals(name)) {
- p = new AddonPackage(this, child, licenses);
-
- } else if (SdkRepository.NODE_EXTRA.equals(name)) {
- p = new ExtraPackage(this, child, licenses);
-
- } else if (!mUserSource) {
- // We only load platform, doc and tool packages from internal
- // sources, never from user sources.
- if (SdkRepository.NODE_PLATFORM.equals(name)) {
- p = new PlatformPackage(this, child, licenses);
- } else if (SdkRepository.NODE_DOC.equals(name)) {
- p = new DocPackage(this, child, licenses);
- } else if (SdkRepository.NODE_TOOL.equals(name)) {
- p = new ToolPackage(this, child, licenses);
- }
+ try {
+ // We can load addon and extra packages from all sources, either
+ // internal or user sources.
+ if (SdkRepository.NODE_ADD_ON.equals(name)) {
+ p = new AddonPackage(this, child, licenses);
+
+ } else if (SdkRepository.NODE_EXTRA.equals(name)) {
+ p = new ExtraPackage(this, child, licenses);
+
+ } else if (!mUserSource) {
+ // We only load platform, doc and tool packages from internal
+ // sources, never from user sources.
+ if (SdkRepository.NODE_PLATFORM.equals(name)) {
+ p = new PlatformPackage(this, child, licenses);
+ } else if (SdkRepository.NODE_DOC.equals(name)) {
+ p = new DocPackage(this, child, licenses);
+ } else if (SdkRepository.NODE_TOOL.equals(name)) {
+ p = new ToolPackage(this, child, licenses);
}
+ }
- if (p != null) {
- packages.add(p);
- monitor.setDescription("Found %1$s", p.getShortDescription());
- }
- } catch (Exception e) {
- // Ignore invalid packages
+ if (p != null) {
+ packages.add(p);
+ monitor.setDescription("Found %1$s", p.getShortDescription());
}
+ } catch (Exception e) {
+ // Ignore invalid packages
}
}
-
- mPackages = packages.toArray(new Package[packages.size()]);
-
- return true;
}
- } catch (ParserConfigurationException e) {
- monitor.setResult("Failed to create XML document builder");
+ mPackages = packages.toArray(new Package[packages.size()]);
- } catch (SAXException e) {
- monitor.setResult("Failed to parse XML document");
-
- } catch (IOException e) {
- monitor.setResult("Failed to read XML document");
+ return true;
}
return false;
@@ -436,11 +727,11 @@ public class RepoSource implements IDescription { * Returns the first child element with the given XML local name.
* If xmlLocalName is null, returns the very first child element.
*/
- private Node getFirstChild(Node node, String xmlLocalName) {
+ private Node getFirstChild(Node node, String nsUri, String xmlLocalName) {
for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
if (child.getNodeType() == Node.ELEMENT_NODE &&
- SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI())) {
+ nsUri.equals(child.getNamespaceURI())) {
if (xmlLocalName == null || child.getLocalName().equals(xmlLocalName)) {
return child;
}
@@ -452,17 +743,30 @@ public class RepoSource implements IDescription { /**
* Takes an XML document as a string as parameter and returns a DOM for it.
+ *
+ * On error, returns null and prints a (hopefully) useful message on the monitor.
*/
- private Document getDocument(ByteArrayInputStream xml)
- throws ParserConfigurationException, SAXException, IOException {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- factory.setIgnoringComments(true);
- factory.setNamespaceAware(true);
+ private Document getDocument(ByteArrayInputStream xml, ITaskMonitor monitor) {
+ try {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setIgnoringComments(true);
+ factory.setNamespaceAware(true);
+
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ xml.reset();
+ Document doc = builder.parse(new InputSource(xml));
- DocumentBuilder builder = factory.newDocumentBuilder();
- xml.reset();
- Document doc = builder.parse(new InputSource(xml));
+ return doc;
+ } catch (ParserConfigurationException e) {
+ monitor.setResult("Failed to create XML document builder");
- return doc;
+ } catch (SAXException e) {
+ monitor.setResult("Failed to parse XML document");
+
+ } catch (IOException e) {
+ monitor.setResult("Failed to read XML document");
+ }
+
+ return null;
}
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/XmlParserUtils.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/XmlParserUtils.java index 7a8bc7d..7d3cd7e 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/XmlParserUtils.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/XmlParserUtils.java @@ -16,8 +16,6 @@ package com.android.sdklib.internal.repository;
-import com.android.sdklib.repository.SdkRepository;
-
import org.w3c.dom.Node;
/**
@@ -31,9 +29,10 @@ class XmlParserUtils { */
public static Node getFirstChild(Node node, String xmlLocalName) {
+ String nsUri = node.getNamespaceURI();
for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
if (child.getNodeType() == Node.ELEMENT_NODE &&
- SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI())) {
+ nsUri.equals(child.getNamespaceURI())) {
if (xmlLocalName == null || xmlLocalName.equals(child.getLocalName())) {
return child;
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java index 2bf87d7..2cfca6f 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/SdkRepository.java @@ -30,9 +30,26 @@ public class SdkRepository { public static final String URL_DEFAULT_XML_FILE = "repository.xml"; //$NON-NLS-1$
- /** The XML namespace of the sdk-repository XML. */
- public static final String NS_SDK_REPOSITORY =
- "http://schemas.android.com/sdk/android/repository/1"; //$NON-NLS-1$
+ /** The XML namespace of the sdk-repository XML version 1.
+ * @deprecated
+ */
+ public static final String NS_SDK_REPOSITORY_1 = getSchemaUri(1);
+
+ /** The XML namespace of the sdk-repository XML version 2.
+ * @deprecated
+ */
+ public static final String NS_SDK_REPOSITORY_2 = getSchemaUri(2);
+
+ /** The XML namespace of the latest sdk-repository XML. */
+ public static final String NS_SDK_REPOSITORY = NS_SDK_REPOSITORY_2;
+
+ /** The pattern of our XML namespace. */
+ public static final String NS_SDK_REPOSITORY_PATTERN =
+ "http://schemas.android.com/sdk/android/repository/[1-9][0-9]*"; //$NON-NLS-1$
+
+ /** The latest version of the sdk-repository XML Schema, currently 2.
+ * Valid version numbers are between 1 and this number, included. */
+ public static final int XSD_LATEST_VERSION = 2;
/** The root sdk-repository element */
public static final String NODE_SDK_REPOSITORY = "sdk-repository"; //$NON-NLS-1$
@@ -108,9 +125,33 @@ public class SdkRepository { /** A license reference. */
public static final String ATTR_REF = "ref"; //$NON-NLS-1$
+ /** Type of a sha1 checksum. */
+ public static final String SHA1_TYPE = "sha1"; //$NON-NLS-1$
+
+ /** Length of a string representing a SHA1 checksum; always 40 characters long. */
+ public static final int SHA1_CHECKSUM_LEN = 40;
+
+
+ /**
+ * Returns a stream to the requested repository XML Schema.
+ *
+ * @param version 1 for {@link #NS_SDK_REPOSITORY_1}, 2 for {@link #NS_SDK_REPOSITORY_2}.
+ * You can use {@link #XSD_LATEST_VERSION} to always get the latest version.
+ * @return An {@link InputStream} object for the local XSD file or
+ * null if there is no schema for the requested version.
+ */
+ public static InputStream getXsdStream(int version) {
+ String filename = String.format("sdk-repository-%d.xsd", version); //$NON-NLS-1$
+ return SdkRepository.class.getResourceAsStream(filename);
+ }
- public static InputStream getXsdStream() {
- return SdkRepository.class.getResourceAsStream("sdk-repository.xsd"); //$NON-NLS-1$
+ /**
+ * Returns the URI of the SDK Repository schema for the given version number.
+ * @param version Between 1 and {@link #XSD_LATEST_VERSION} included.
+ */
+ public static String getSchemaUri(int version) {
+ return String.format("http://schemas.android.com/sdk/android/repository/%d", //$NON-NLS-1$
+ version); //
}
}
diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository.xsd b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository-1.xsd index f00e337..f00e337 100755 --- a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository.xsd +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository-1.xsd diff --git a/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository-2.xsd b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository-2.xsd new file mode 100755 index 0000000..31b173f --- /dev/null +++ b/sdkmanager/libs/sdklib/src/com/android/sdklib/repository/sdk-repository-2.xsd @@ -0,0 +1,421 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Copyright (C) 2009 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. +--> +<xsd:schema + targetNamespace="http://schemas.android.com/sdk/android/repository/2" + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:sdk="http://schemas.android.com/sdk/android/repository/2" + elementFormDefault="qualified" + attributeFormDefault="unqualified" + version="1"> + + <!-- The repository contains a collection of downloadable items known as + "packages". Each package has a type and various attributes and contains + a list of file "archives" that can be downloaded for specific OSes. + + An Android SDK repository is a web site that contains a "repository.xml" + file that conforms to this XML Schema. + --> + + <xsd:element name="sdk-repository"> + <xsd:annotation> + <xsd:documentation> + The repository contains collections of downloadable packages. + </xsd:documentation> + </xsd:annotation> + + <xsd:complexType> + <xsd:choice minOccurs="0" maxOccurs="unbounded"> + + <!-- The definition of an SDK platform package. --> + + <xsd:element name="platform"> + <xsd:annotation> + <xsd:documentation>An SDK platform package.</xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:all> + <!-- The Android platform version. It is string such as "1.0". --> + <xsd:element name="version" type="xsd:normalizedString" /> + <!-- The Android API Level for the platform. An int > 0. --> + <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" /> + <!-- The optional license of this package. If present, users will have + to agree to it before downloading. --> + <xsd:element name="uses-license" type="sdk:licenseType" minOccurs="0" /> + <!-- The optional description of this package. --> + <xsd:element name="description" type="xsd:string" minOccurs="0" /> + <!-- The optional description URL of this package --> + <xsd:element name="desc-url" type="xsd:token" minOccurs="0" /> + <!-- The optional release note for this package. --> + <xsd:element name="release-note" type="xsd:string" minOccurs="0" /> + <!-- 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="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:all> + </xsd:complexType> + </xsd:element> + + + <!-- The definition of an SDK Add-on package. --> + + <xsd:element name="add-on"> + <xsd:annotation> + <xsd:documentation>An SDK add-on package.</xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:all> + <!-- The name of the add-on. --> + <xsd:element name="name" type="xsd:normalizedString" /> + <!-- The vendor of the add-on. --> + <xsd:element name="vendor" type="xsd:normalizedString" /> + <!-- The Android API Level for the add-on. An int > 0. --> + <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" /> + <!-- The optional license of this package. If present, users will have + to agree to it before downloading. --> + <xsd:element name="uses-license" type="sdk:licenseType" minOccurs="0" /> + <!-- The optional description of this package. --> + <xsd:element name="description" type="xsd:string" minOccurs="0" /> + <!-- The optional description URL of this package --> + <xsd:element name="desc-url" type="xsd:token" minOccurs="0" /> + <!-- The optional release note for this package. --> + <xsd:element name="release-note" type="xsd:string" minOccurs="0" /> + <!-- 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="sdk:archivesType" /> + + <!-- An add-on can declare 0 or more libraries. --> + + <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> + </xsd:all> + </xsd:complexType> + </xsd:element> + + + <!-- The definition of an SDK tool package. --> + + <xsd:element name="tool"> + <xsd:annotation> + <xsd:documentation>An SDK tool package.</xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:all> + <!-- 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="sdk:licenseType" minOccurs="0" /> + <!-- The optional description of this package. --> + <xsd:element name="description" type="xsd:string" minOccurs="0" /> + <!-- The optional description URL of this package --> + <xsd:element name="desc-url" type="xsd:token" minOccurs="0" /> + <!-- The optional release note for this package. --> + <xsd:element name="release-note" type="xsd:string" minOccurs="0" /> + <!-- 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="sdk:archivesType" /> + </xsd:all> + </xsd:complexType> + </xsd:element> + + + <!-- The definition of an SDK doc package. --> + + <xsd:element name="doc"> + <xsd:annotation> + <xsd:documentation>An SDK doc package.</xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:all> + <!-- The Android API Level for the documentation. An int > 0. --> + <xsd:element name="api-level" type="xsd:positiveInteger" /> + <!-- The optional codename for this doc, 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" /> + <!-- The optional license of this package. If present, users will have + to agree to it before downloading. --> + <xsd:element name="uses-license" type="sdk:licenseType" minOccurs="0" /> + <!-- The optional description of this package. --> + <xsd:element name="description" type="xsd:string" minOccurs="0" /> + <!-- The optional description URL of this package --> + <xsd:element name="desc-url" type="xsd:token" minOccurs="0" /> + <!-- The optional release note for this package. --> + <xsd:element name="release-note" type="xsd:string" minOccurs="0" /> + <!-- 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="sdk:archivesType" /> + </xsd:all> + </xsd:complexType> + </xsd:element> + + + <!-- 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. + --> + + <xsd:element name="extra"> + <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. + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <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. + --> + <xsd:element name="path"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:pattern value="[^/\\]+"/> + </xsd:restriction> + </xsd:simpleType> + </xsd:element> + + <!-- 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="sdk:licenseType" minOccurs="0" /> + <!-- The optional description of this package. --> + <xsd:element name="description" type="xsd:string" minOccurs="0" /> + <!-- The optional description URL of this package --> + <xsd:element name="desc-url" type="xsd:token" minOccurs="0" /> + <!-- The optional release note for this package. --> + <xsd:element name="release-note" type="xsd:string" minOccurs="0" /> + <!-- 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="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:all> + </xsd:complexType> + </xsd:element> + + + <!-- The definition of a sample package. + --> + + <xsd:element name="sample"> + <xsd:annotation> + <xsd:documentation> + An SDK sample package. + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:all> + <!-- STOPSHIP! TODO how do we link to the addon *or* platform? + e.g. api-level + codename + optional addon name+vendor? + api-level is mandatory, codename is optional; + if addon name+vendor is set, it's for that addon, otherwise + it's for a platform. + --> + <!-- The Android API Level for the documentation. An int > 0. --> + <xsd:element name="api-level" type="xsd:positiveInteger" /> + <!-- The optional codename for this doc, 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" /> + <!-- The optional license of this package. If present, users will have + to agree to it before downloading. --> + <xsd:element name="uses-license" type="sdk:licenseType" minOccurs="0" /> + <!-- The optional description of this package. --> + <xsd:element name="description" type="xsd:string" minOccurs="0" /> + <!-- The optional description URL of this package --> + <xsd:element name="desc-url" type="xsd:token" minOccurs="0" /> + <!-- The optional release note for this package. --> + <xsd:element name="release-note" type="xsd:string" minOccurs="0" /> + <!-- 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="sdk:archivesType" /> + </xsd:all> + </xsd:complexType> + </xsd:element> + + + <!-- The definition of a license to be referenced by the uses-license element. --> + + <xsd:element name="license"> + <xsd:annotation> + <xsd:documentation> + A license definition. Such a license must be used later as a reference + using a uses-license element in one of the package elements. + </xsd:documentation> + </xsd:annotation> + <xsd:complexType> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="id" type="xsd:ID" /> + <xsd:attribute name="type" type="xsd:token" fixed="text" /> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + </xsd:element> + </xsd:choice> + </xsd:complexType> + </xsd:element> + + + <!-- Type describing the license used by a package. + The license MUST be defined using a license node and referenced + using the ref attribute of the license element inside a package. + --> + + <xsd:complexType name="licenseType"> + <xsd:annotation> + <xsd:documentation> + Describes the license used by a package. The license MUST be defined + using a license node and referenced using the ref attribute of the + license element inside a package. + </xsd:documentation> + </xsd:annotation> + <xsd:attribute name="ref" type="xsd:IDREF" /> + </xsd:complexType> + + + <!-- A collection of files that can be downloaded for a given architecture. + The <archives> node is mandatory in the repository elements and the + collection must have at least one <archive> declared. + Each archive is a zip file that will be unzipped in a location that depends + on its package type. + --> + + <xsd:complexType name="archivesType"> + <xsd:annotation> + <xsd:documentation> + A collection of files that can be downloaded for a given architecture. + The <archives> node is mandatory in the repository packages and the + collection must have at least one <archive> declared. + Each archive is a zip file that will be unzipped in a location that depends + on its package type. + </xsd:documentation> + </xsd:annotation> + <xsd:sequence minOccurs="1" maxOccurs="unbounded"> + <!-- One archive file --> + <xsd:element name="archive"> + <xsd:complexType> + <!-- Properties of the archive file --> + <xsd:all> + <!-- 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="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:element name="url" type="xsd:token" /> + </xsd:all> + + <!-- Attributes that identify the OS and architecture --> + <xsd:attribute name="os" use="required"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="any" /> + <xsd:enumeration value="linux" /> + <xsd:enumeration value="macosx" /> + <xsd:enumeration value="windows" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + <xsd:attribute name="arch" use="optional"> + <xsd:simpleType> + <xsd:restriction base="xsd:token"> + <xsd:enumeration value="any" /> + <xsd:enumeration value="ppc" /> + <xsd:enumeration value="x86" /> + <xsd:enumeration value="x86_64" /> + </xsd:restriction> + </xsd:simpleType> + </xsd:attribute> + </xsd:complexType> + </xsd:element> + </xsd:sequence> + </xsd:complexType> + + + <!-- The definition of a file checksum --> + + <xsd:simpleType name="sha1Number"> + <xsd:annotation> + <xsd:documentation>A SHA1 checksum.</xsd:documentation> + </xsd:annotation> + <xsd:restriction base="xsd:string"> + <xsd:pattern value="([0-9a-fA-F]){40}"/> + </xsd:restriction> + </xsd:simpleType> + + <xsd:complexType name="checksumType"> + <xsd:annotation> + <xsd:documentation>A file checksum, currently only SHA1.</xsd:documentation> + </xsd:annotation> + <xsd:simpleContent> + <xsd:extension base="sdk:sha1Number"> + <xsd:attribute name="type" type="xsd:token" fixed="sha1" /> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + + +</xsd:schema> diff --git a/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/RepoSourceTest.java b/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/RepoSourceTest.java new file mode 100755 index 0000000..87da294 --- /dev/null +++ b/sdkmanager/libs/sdklib/tests/com/android/sdklib/internal/repository/RepoSourceTest.java @@ -0,0 +1,163 @@ +/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php
+ *
+ * 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;
+
+import com.android.sdklib.repository.SdkRepository;
+
+import org.w3c.dom.Document;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for {@link RepoSource}
+ */
+public class RepoSourceTest extends TestCase {
+
+ private static class MockMonitor implements ITaskMonitor {
+ public void setResult(String resultFormat, Object... args) {
+ }
+
+ public void setProgressMax(int max) {
+ }
+
+ public void setDescription(String descriptionFormat, Object... args) {
+ }
+
+ public boolean isCancelRequested() {
+ return false;
+ }
+
+ public void incProgress(int delta) {
+ }
+
+ public int getProgress() {
+ return 0;
+ }
+
+ public boolean displayPrompt(String title, String message) {
+ return false;
+ }
+
+ public ITaskMonitor createSubMonitor(int tickCount) {
+ return null;
+ }
+ }
+
+ /**
+ * An internal helper class to give us visibility to the protected members we want
+ * to test.
+ */
+ private static class MockRepoSource extends RepoSource {
+ public MockRepoSource() {
+ super("fake-url", false /*userSource*/);
+ }
+
+ public Document _findAlternateToolsXml(InputStream xml) {
+ return super.findAlternateToolsXml(xml);
+ }
+
+ public boolean _parsePackages(Document doc, String nsUri, ITaskMonitor monitor) {
+ return super.parsePackages(doc, nsUri, monitor);
+ }
+ }
+
+ private MockRepoSource mSource;
+
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+
+ mSource = new MockRepoSource();
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+
+ mSource = null;
+ }
+
+ public void testFindAlternateToolsXml_Errors() {
+ // Support null as input
+ Document result = mSource._findAlternateToolsXml(null);
+ assertNull(result);
+
+ // Support an empty input
+ String str = "";
+ ByteArrayInputStream input = new ByteArrayInputStream(str.getBytes());
+ result = mSource._findAlternateToolsXml(input);
+ assertNull(result);
+
+ // Support a random string as input
+ str = "Some random string, not even HTML nor XML";
+ input = new ByteArrayInputStream(str.getBytes());
+ result = mSource._findAlternateToolsXml(input);
+ assertNull(result);
+
+ // Support an HTML input, e.g. a typical 404 document as returned by DL
+ str = "<html><head> " +
+ "<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\"> " +
+ "<title>404 Not Found</title> " + "<style><!--" + "body {font-family: arial,sans-serif}" +
+ "div.nav { ... blah blah more css here ... color: green}" +
+ "//--></style> " + "<script><!--" + "var rc=404;" + "//-->" + "</script> " + "</head> " +
+ "<body text=#000000 bgcolor=#ffffff> " +
+ "<table border=0 cellpadding=2 cellspacing=0 width=100%><tr><td rowspan=3 width=1% nowrap> " +
+ "<b><font face=times color=#0039b6 size=10>G</font><font face=times color=#c41200 size=10>o</font><font face=times color=#f3c518 size=10>o</font><font face=times color=#0039b6 size=10>g</font><font face=times color=#30a72f size=10>l</font><font face=times color=#c41200 size=10>e</font> </b> " +
+ "<td> </td></tr> " +
+ "<tr><td bgcolor=\"#3366cc\"><font face=arial,sans-serif color=\"#ffffff\"><b>Error</b></td></tr> " +
+ "<tr><td> </td></tr></table> " + "<blockquote> " + "<H1>Not Found</H1> " +
+ "The requested URL <code>/404</code> was not found on this server." + " " + "<p> " +
+ "</blockquote> " +
+ "<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=\"#3366cc\"><img alt=\"\" width=1 height=4></td></tr></table> " +
+ "</body></html> ";
+ input = new ByteArrayInputStream(str.getBytes());
+ result = mSource._findAlternateToolsXml(input);
+ assertNull(result);
+
+ // Support some random XML document, totally unrelated to our sdk-repository schema
+ str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +
+ "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"" +
+ " package=\"some.cool.app\" android:versionName=\"1.6.04\" android:versionCode=\"1604\">" +
+ " <application android:label=\"@string/app_name\" android:icon=\"@drawable/icon\"/>" +
+ "</manifest>";
+ input = new ByteArrayInputStream(str.getBytes());
+ result = mSource._findAlternateToolsXml(input);
+ assertNull(result);
+ }
+
+ public void testFindAlternateToolsXml_1() {
+ InputStream xmlStream = this.getClass().getResourceAsStream(
+ "/com/android/sdklib/testdata/repository_sample_1.xml");
+
+ Document result = mSource._findAlternateToolsXml(xmlStream);
+ assertNotNull(result);
+ assertTrue(mSource._parsePackages(result,
+ SdkRepository.NS_SDK_REPOSITORY, new MockMonitor()));
+
+ // check the packages we found... we expected to find 2 tool packages with 1 archive each.
+ Package[] pkgs = mSource.getPackages();
+ assertEquals(2, pkgs.length);
+ for (Package p : pkgs) {
+ assertEquals(ToolPackage.class, p.getClass());
+ assertEquals(1, p.getArchives().length);
+ }
+ }
+
+}
diff --git a/sdkmanager/libs/sdklib/tests/com/android/sdklib/repository/TestSdkRepository.java b/sdkmanager/libs/sdklib/tests/com/android/sdklib/repository/SdkRepositoryTest.java index de50b6e..27f881e 100755 --- a/sdkmanager/libs/sdklib/tests/com/android/sdklib/repository/TestSdkRepository.java +++ b/sdkmanager/libs/sdklib/tests/com/android/sdklib/repository/SdkRepositoryTest.java @@ -38,7 +38,7 @@ import junit.framework.TestCase; * References:
* http://www.ibm.com/developerworks/xml/library/x-javaxmlvalidapi.html
*/
-public class TestSdkRepository extends TestCase {
+public class SdkRepositoryTest extends TestCase {
@Override
protected void setUp() throws Exception {
@@ -59,10 +59,12 @@ public class TestSdkRepository extends TestCase { private String mWarnings = "";
private String mErrors = "";
+ @SuppressWarnings("unused")
public String getErrors() {
return mErrors;
}
+ @SuppressWarnings("unused")
public String getWarnings() {
return mWarnings;
}
@@ -109,8 +111,8 @@ public class TestSdkRepository extends TestCase { // --- Helpers ------------
/** Helper method that returns a validator for our XSD */
- private Validator getValidator(CaptureErrorHandler handler) throws SAXException {
- InputStream xsdStream = SdkRepository.getXsdStream();
+ private Validator getValidator(int version, CaptureErrorHandler handler) throws SAXException {
+ InputStream xsdStream = SdkRepository.getXsdStream(version);
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema schema = factory.newSchema(new StreamSource(xsdStream));
Validator validator = schema.newValidator();
@@ -121,19 +123,6 @@ public class TestSdkRepository extends TestCase { return validator;
}
- /** Validate a valid sample using an InputStream */
- public void testValidateLocalRepositoryFile() throws Exception {
- InputStream xmlStream =
- this.getClass().getClassLoader().getResourceAsStream(
- "com/android/sdklib/testdata/repository_sample.xml");
- Source source = new StreamSource(xmlStream);
-
- CaptureErrorHandler handler = new CaptureErrorHandler();
- Validator validator = getValidator(handler);
- validator.validate(source);
- handler.verify();
- }
-
/** An helper that validates a string against an expected regexp. */
private void assertRegex(String expectedRegexp, String actualString) {
assertNotNull(actualString);
@@ -145,6 +134,49 @@ public class TestSdkRepository extends TestCase { // --- Tests ------------
+ /** Validate a valid sample using namespace version 1 using an InputStream */
+ public void testValidateLocalRepositoryFile1() throws Exception {
+ InputStream xmlStream = this.getClass().getResourceAsStream(
+ "/com/android/sdklib/testdata/repository_sample_1.xml");
+ Source source = new StreamSource(xmlStream);
+
+ CaptureErrorHandler handler = new CaptureErrorHandler();
+ Validator validator = getValidator(1, handler);
+ validator.validate(source);
+ handler.verify();
+ }
+
+ /** Validate a valid sample using namespace version 2 using an InputStream */
+ public void testValidateLocalRepositoryFile2() throws Exception {
+ InputStream xmlStream = this.getClass().getResourceAsStream(
+ "/com/android/sdklib/testdata/repository_sample_2.xml");
+ Source source = new StreamSource(xmlStream);
+
+ CaptureErrorHandler handler = new CaptureErrorHandler();
+ Validator validator = getValidator(2, handler);
+ validator.validate(source);
+ handler.verify();
+ }
+
+ /** Test that validating a v2 file using the v1 schema fails. */
+ public void testValidateFile2UsingNs1() throws Exception {
+ InputStream xmlStream = this.getClass().getResourceAsStream(
+ "/com/android/sdklib/testdata/repository_sample_2.xml");
+ Source source = new StreamSource(xmlStream);
+
+ Validator validator = getValidator(1, null); // validate v2 against v1... fail!
+
+ try {
+ validator.validate(source);
+ } catch (SAXParseException e) {
+ // We expect to get this specific exception message
+ assertRegex("cvc-elt.1: Cannot find the declaration of element 'sdk:sdk-repository'.*", e.getMessage());
+ return;
+ }
+ // We shouldn't get here
+ fail();
+ }
+
/** A document should at least have a root to be valid */
public void testEmptyXml() throws Exception {
String document = "<?xml version=\"1.0\"?>";
@@ -152,7 +184,7 @@ public class TestSdkRepository extends TestCase { Source source = new StreamSource(new StringReader(document));
CaptureErrorHandler handler = new CaptureErrorHandler();
- Validator validator = getValidator(handler);
+ Validator validator = getValidator(SdkRepository.XSD_LATEST_VERSION, handler);
try {
validator.validate(source);
@@ -166,15 +198,23 @@ public class TestSdkRepository extends TestCase { fail();
}
+ private static String OPEN_TAG =
+ "<r:sdk-repository xmlns:r=\"http://schemas.android.com/sdk/android/repository/" +
+ Integer.toString(SdkRepository.XSD_LATEST_VERSION) +
+ "\">";
+
+ private static String CLOSE_TAG = "</r:sdk-repository>";
+
/** A document with a root element containing no platform, addon, etc., is valid. */
public void testEmptyRootXml() throws Exception {
String document = "<?xml version=\"1.0\"?>" +
- "<r:sdk-repository xmlns:r=\"http://schemas.android.com/sdk/android/repository/1\" />";
+ OPEN_TAG +
+ CLOSE_TAG;
Source source = new StreamSource(new StringReader(document));
CaptureErrorHandler handler = new CaptureErrorHandler();
- Validator validator = getValidator(handler);
+ Validator validator = getValidator(SdkRepository.XSD_LATEST_VERSION, handler);
validator.validate(source);
handler.verify();
}
@@ -182,14 +222,14 @@ public class TestSdkRepository extends TestCase { /** A document with an unknown element. */
public void testUnknownContentXml() throws Exception {
String document = "<?xml version=\"1.0\"?>" +
- "<r:sdk-repository xmlns:r=\"http://schemas.android.com/sdk/android/repository/1\" >" +
+ OPEN_TAG +
"<r:unknown />" +
- "</r:sdk-repository>";
+ CLOSE_TAG;
Source source = new StreamSource(new StringReader(document));
// don't capture the validator errors, we want it to fail and catch the exception
- Validator validator = getValidator(null);
+ Validator validator = getValidator(SdkRepository.XSD_LATEST_VERSION, null);
try {
validator.validate(source);
} catch (SAXParseException e) {
@@ -204,14 +244,14 @@ public class TestSdkRepository extends TestCase { /** A document with an incomplete element. */
public void testIncompleteContentXml() throws Exception {
String document = "<?xml version=\"1.0\"?>" +
- "<r:sdk-repository xmlns:r=\"http://schemas.android.com/sdk/android/repository/1\" >" +
+ OPEN_TAG +
"<r:platform> <r:api-level>1</r:api-level> <r:libs /> </r:platform>" +
- "</r:sdk-repository>";
+ CLOSE_TAG;
Source source = new StreamSource(new StringReader(document));
// don't capture the validator errors, we want it to fail and catch the exception
- Validator validator = getValidator(null);
+ Validator validator = getValidator(SdkRepository.XSD_LATEST_VERSION, null);
try {
validator.validate(source);
} catch (SAXParseException e) {
@@ -226,14 +266,14 @@ public class TestSdkRepository extends TestCase { /** A document with a wrong type element. */
public void testWrongTypeContentXml() throws Exception {
String document = "<?xml version=\"1.0\"?>" +
- "<r:sdk-repository xmlns:r=\"http://schemas.android.com/sdk/android/repository/1\" >" +
+ OPEN_TAG +
"<r:platform> <r:api-level>NotAnInteger</r:api-level> <r:libs /> </r:platform>" +
- "</r:sdk-repository>";
+ CLOSE_TAG;
Source source = new StreamSource(new StringReader(document));
// don't capture the validator errors, we want it to fail and catch the exception
- Validator validator = getValidator(null);
+ Validator validator = getValidator(SdkRepository.XSD_LATEST_VERSION, null);
try {
validator.validate(source);
} catch (SAXParseException e) {
@@ -250,17 +290,17 @@ public class TestSdkRepository extends TestCase { public void testLicenseIdNotFound() throws Exception {
// we define a license named "lic1" and then reference "lic2" instead
String document = "<?xml version=\"1.0\"?>" +
- "<r:sdk-repository xmlns:r=\"http://schemas.android.com/sdk/android/repository/1\" >" +
+ OPEN_TAG +
"<r:license id=\"lic1\"> some license </r:license> " +
"<r:tool> <r:uses-license ref=\"lic2\" /> <r:revision>1</r:revision> " +
"<r:archives> <r:archive os=\"any\"> <r:size>1</r:size> <r:checksum>2822ae37115ebf13412bbef91339ee0d9454525e</r:checksum> " +
"<r:url>url</r:url> </r:archive> </r:archives> </r:tool>" +
- "</r:sdk-repository>";
+ CLOSE_TAG;
Source source = new StreamSource(new StringReader(document));
// don't capture the validator errors, we want it to fail and catch the exception
- Validator validator = getValidator(null);
+ Validator validator = getValidator(SdkRepository.XSD_LATEST_VERSION, null);
try {
validator.validate(source);
} catch (SAXParseException e) {
@@ -277,16 +317,16 @@ public class TestSdkRepository extends TestCase { public void testExtraPathWithSlash() throws Exception {
// we define a license named "lic1" and then reference "lic2" instead
String document = "<?xml version=\"1.0\"?>" +
- "<r:sdk-repository xmlns:r=\"http://schemas.android.com/sdk/android/repository/1\" >" +
+ OPEN_TAG +
"<r:extra> <r:revision>1</r:revision> <r:path>path/cannot\\contain\\segments</r:path> " +
"<r:archives> <r:archive os=\"any\"> <r:size>1</r:size> <r:checksum>2822ae37115ebf13412bbef91339ee0d9454525e</r:checksum> " +
"<r:url>url</r:url> </r:archive> </r:archives> </r:extra>" +
- "</r:sdk-repository>";
+ CLOSE_TAG;
Source source = new StreamSource(new StringReader(document));
// don't capture the validator errors, we want it to fail and catch the exception
- Validator validator = getValidator(null);
+ Validator validator = getValidator(SdkRepository.XSD_LATEST_VERSION, null);
try {
validator.validate(source);
} catch (SAXParseException e) {
diff --git a/sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/repository_sample.xml b/sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/repository_sample_1.xml index c90e18d..c90e18d 100755 --- a/sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/repository_sample.xml +++ b/sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/repository_sample_1.xml diff --git a/sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/repository_sample_2.xml b/sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/repository_sample_2.xml new file mode 100755 index 0000000..d5276e5 --- /dev/null +++ b/sdkmanager/libs/sdklib/tests/com/android/sdklib/testdata/repository_sample_2.xml @@ -0,0 +1,288 @@ +<?xml version="1.0"?>
+<!--
+ * Copyright (C) 2009 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.
+-->
+<sdk:sdk-repository
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:sdk="http://schemas.android.com/sdk/android/repository/2">
+
+ <!-- Define a couple of licenses. These will be referenced by uses-license later. -->
+
+ <sdk:license type="text" id="license1">
+ This is the license
+ for this platform.
+ </sdk:license>
+
+ <sdk:license id="license2">
+ Licenses are only of type 'text' right now, so this is implied.
+ </sdk:license>
+
+ <!-- Inner elements must be either platform, add-on, doc or tool.
+ There can be 0 or more of each, in any order. -->
+
+ <sdk:platform>
+ <sdk:version>1.0</sdk:version>
+ <sdk:api-level>1</sdk:api-level>
+ <sdk:revision>3</sdk:revision>
+ <sdk:uses-license ref="license1" />
+ <sdk:description>Some optional description</sdk:description>
+ <sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url>
+ <sdk:release-note>This is an optional release note
+ for this package. It's a free multi-line text.
+ </sdk:release-note>
+ <sdk:release-url>http://some/url/for/the/release/note.html</sdk:release-url>
+ <sdk:min-tools-rev>2</sdk:min-tools-rev>
+ <!-- The archives node is mandatory and it cannot be empty. -->
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/files/plat1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:platform>
+
+ <sdk:doc>
+ <sdk:api-level>1</sdk:api-level>
+ <sdk:revision>1</sdk:revision>
+ <!-- the license element is not mandatory. -->
+ <sdk:description>Some optional description</sdk:description>
+ <sdk:desc-url>http://www.example.com/docs.html</sdk:desc-url>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/docs/docs1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:doc>
+
+ <sdk:add-on>
+ <sdk:name>My First add-on</sdk:name>
+ <sdk:api-level>1</sdk:api-level>
+ <sdk:vendor>John Doe</sdk:vendor>
+ <sdk:revision>1</sdk:revision>
+ <sdk:uses-license ref="license2" />
+ <sdk:description>Some optional description</sdk:description>
+ <sdk:desc-url>http://www.example.com/myfirstaddon</sdk:desc-url>
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/add-ons/first.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <!-- The libs node is mandatory, however it can be empty. -->
+ <sdk:libs>
+ <sdk:lib>
+ <sdk:name>android.blah.somelib</sdk:name>
+ <sdk:description>The description for this library.</sdk:description>
+ </sdk:lib>
+ <sdk:lib>
+ <!-- sdk:description is optional, name is not -->
+ <sdk:name>com.android.mymaps</sdk:name>
+ </sdk:lib>
+ </sdk:libs>
+ </sdk:add-on>
+
+ <sdk:platform>
+ <sdk:version>1.1</sdk:version>
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:revision>12</sdk:revision>
+ <sdk:uses-license ref="license1" />
+ <!-- sdk:description and sdk:desc-url are optional -->
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <!-- arch attribute is optional -->
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-win.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx" arch="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-mac.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx" arch="ppc">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-mac.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux" arch="x86">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux" arch="x86_64">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/platform-2-12-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:platform>
+
+ <sdk:add-on>
+ <sdk:name>My Second add-on</sdk:name>
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:vendor>John Deer</sdk:vendor>
+ <sdk:revision>42</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/second-42-win.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/second-42-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:libs>
+ <sdk:lib>
+ <sdk:name>android.blah.somelib</sdk:name>
+ <sdk:description>The description for this library.</sdk:description>
+ </sdk:lib>
+ <sdk:lib>
+ <sdk:name>com.android.mymaps</sdk:name>
+ </sdk:lib>
+ </sdk:libs>
+ <sdk:uses-license ref="license2" />
+ </sdk:add-on>
+ + <sdk:platform> + <sdk:version>Pastry</sdk:version> + <sdk:api-level>5</sdk:api-level> + <sdk:codename>Pastry</sdk:codename> + <sdk:revision>3</sdk:revision> + <sdk:uses-license ref="license1" /> + <sdk:description>Preview version for Pastry</sdk:description> + <sdk:desc-url>http://www.example.com/platform1.html</sdk:desc-url> + <!-- The archives node is mandatory and it cannot be empty. --> + <sdk:archives> + <sdk:archive os="any"> + <sdk:size>65536</sdk:size> + <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum> + <sdk:url>http://www.example.com/files/plat1.zip</sdk:url> + </sdk:archive> + </sdk:archives> + </sdk:platform> +
+ <sdk:tool>
+ <sdk:revision>1</sdk:revision>
+ <sdk:description>Some optional description</sdk:description>
+ <sdk:desc-url>http://www.example.com/tools.html</sdk:desc-url>
+ <sdk:uses-license ref="license1" />
+ <sdk:archives>
+ <sdk:archive os="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>http://www.example.com/files/tools1.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:tool>
+
+ <sdk:doc>
+ <sdk:api-level>2</sdk:api-level>
+ <sdk:revision>42</sdk:revision>
+ <sdk:uses-license ref="license2" />
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/docs/2.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/docs2-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/docs2-mac.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:doc>
+
+ <sdk:tool>
+ <sdk:revision>42</sdk:revision>
+ <sdk:uses-license ref="license1" />
+ <sdk:archives>
+ <sdk:archive os="windows">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/tools/2.zip</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="linux">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/tools2-linux.tar.bz2</sdk:url>
+ </sdk:archive>
+ <sdk:archive os="macosx">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/tools2-mac.tar.bz2</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:tool>
+
+ <sdk:add-on>
+ <sdk:uses-license ref="license2" />
+ <sdk:name>This add-on has no libraries</sdk:name>
+ <sdk:api-level>4</sdk:api-level>
+ <sdk:vendor>Joe Bar</sdk:vendor>
+ <sdk:revision>3</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any" arch="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/imnotanarchiveimadoctorjim.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <!-- The libs node is mandatory, however it can be empty. -->
+ <sdk:libs />
+ </sdk:add-on>
+
+ <sdk:extra>
+ <sdk:path>usb_driver</sdk:path>
+ <sdk:uses-license ref="license2" />
+ <sdk:revision>43</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any" arch="any">
+ <sdk:size>65536</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d9454525e</sdk:checksum>
+ <sdk:url>distrib/extraduff.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:description>An Extra package for the USB driver, it will install in $SDK/usb_driver</sdk:description>
+ <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url>
+ <sdk:min-tools-rev>3</sdk:min-tools-rev>
+ </sdk:extra>
+
+ <sdk:sample>
+ <sdk:uses-license ref="license2" />
+ <sdk:api-level>1234</sdk:api-level>
+ <sdk:revision>314153</sdk:revision>
+ <sdk:archives>
+ <sdk:archive os="any" arch="any">
+ <sdk:size>123456</sdk:size>
+ <sdk:checksum type="sha1">2822ae37115ebf13412bbef91339ee0d94545228</sdk:checksum>
+ <sdk:url>archives/samples/dream-1234.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ </sdk:sample>
+
+</sdk:sdk-repository>
|
