* When decorating a method, this denotes the method might legitimately return null.
* <p/>
* This is a marker annotation and it has no specific attributes.
+ *
+ * @deprecated TODO use the version moved into sdklib instead
*/
+@Deprecated
@Retention(RetentionPolicy.SOURCE)
public @interface Nullable {
}
* The <code>visibility</code> argument can be used to specific what the original
* visibility should have been if it had not been made public or package-private for testing.
* The default is to consider the element private.
+ *
+ * @deprecated TODO use the version moved into sdklib instead
*/
+@Deprecated
@Retention(RetentionPolicy.SOURCE)
public @interface VisibleForTesting {
/**
import com.android.sdklib.internal.project.ProjectCreator.OutputLevel;
import com.android.sdklib.internal.project.ProjectProperties.PropertyType;
import com.android.sdklib.io.FileWrapper;
-import com.android.sdklib.repository.SdkRepository;
+import com.android.sdklib.repository.SdkRepoConstants;
import com.android.sdklib.xml.AndroidXPathFactory;
import com.android.sdkmanager.internal.repository.AboutPage;
import com.android.sdkmanager.internal.repository.SettingsPage;
t = t.trim();
if (t.length() > 0) {
boolean found = false;
- for (String t2 : SdkRepository.NODES) {
+ for (String t2 : SdkRepoConstants.NODES) {
if (t2.equals(t)) {
pkgFilter.add(t2);
found = true;
errorAndExit(
"Unknown package filter type '%1$s'.\nAccepted values are: %2$s",
t,
- Arrays.toString(SdkRepository.NODES));
+ Arrays.toString(SdkRepoConstants.NODES));
return;
}
}
import com.android.sdklib.ISdkLog;
import com.android.sdklib.SdkManager;
-import com.android.sdklib.repository.SdkRepository;
+import com.android.sdklib.repository.SdkRepoConstants;
import java.util.Arrays;
define(Mode.STRING, false,
VERB_UPDATE, OBJECT_SDK, "t", KEY_FILTER,
"A filter that limits the update to the specified types of packages in the form of\n" +
- " a comma-separated list of " + Arrays.toString(SdkRepository.NODES),
+ " a comma-separated list of " + Arrays.toString(SdkRepoConstants.NODES),
null);
define(Mode.BOOLEAN, false,
\r
import com.android.sdklib.SdkConstants;\r
import com.android.sdklib.internal.repository.Package;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
import com.android.sdkmanager.*;\r
import org.eclipse.swt.SWT;\r
import org.eclipse.swt.graphics.Image;\r
"Repository XML Schema #%2$d\n" +\r
"Copyright (C) 2009-2010 The Android Open Source Project.",\r
getRevision(),\r
- SdkRepository.NS_LATEST_VERSION));\r
+ SdkRepoConstants.NS_LATEST_VERSION));\r
}\r
\r
@Override\r
--- /dev/null
+/*
+ * Copyright (C) 2010 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.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denotes a parameter or field can be null.
+ * <p/>
+ * When decorating a method call parameter, this denotes the parameter can
+ * legitimately be null and the method will gracefully deal with it. Typically used
+ * on optional parameters.
+ * <p/>
+ * When decorating a method, this denotes the method might legitimately return null.
+ * <p/>
+ * This is a marker annotation and it has no specific attributes.
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface Nullable {
+}
--- /dev/null
+/*
+ * Copyright (C) 2010 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.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Denotes that the class, method or field has its visibility relaxed so
+ * that unit tests can access it.
+ * <p/>
+ * The <code>visibility</code> argument can be used to specific what the original
+ * visibility should have been if it had not been made public or package-private for testing.
+ * The default is to consider the element private.
+ */
+@Retention(RetentionPolicy.SOURCE)
+public @interface VisibleForTesting {
+ /**
+ * Intended visibility if the element had not been made public or package-private for
+ * testing.
+ */
+ enum Visibility {
+ /** The element should be considered protected. */
+ PROTECTED,
+ /** The element should be considered package-private. */
+ PACKAGE,
+ /** The element should be considered private. */
+ PRIVATE
+ }
+
+ /**
+ * Intended visibility if the element had not been made public or package-private for testing.
+ * If not specified, one should assume the element originally intended to be private.
+ */
+ Visibility visibility() default Visibility.PRIVATE;
+}
import com.android.sdklib.IAndroidTarget.IOptionalLibrary;\r
import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Node;\r
\r
\r
/**\r
* Creates a new add-on package from the attributes and elements of the given XML node.\r
- * <p/>\r
* This constructor should throw an exception if the package cannot be created.\r
+ *\r
+ * @param source The {@link SdkSource} where this is loaded from.\r
+ * @param packageNode The XML element being parsed.\r
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with\r
+ * parameters that vary according to the originating XML schema.\r
+ * @param licenses The licenses loaded from the XML originating document.\r
*/\r
- AddonPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {\r
- super(source, packageNode, licenses);\r
- mVendor = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_VENDOR);\r
- mName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_NAME);\r
- int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_API_LEVEL, 0);\r
- String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_CODENAME);\r
+ AddonPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
+ super(source, packageNode, nsUri, licenses);\r
+ mVendor = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_VENDOR);\r
+ mName = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_NAME);\r
+ int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0);\r
+ String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME);\r
if (codeName.length() == 0) {\r
codeName = null;\r
}\r
mVersion = new AndroidVersion(apiLevel, codeName);\r
\r
- mLibs = parseLibs(XmlParserUtils.getFirstChild(packageNode, SdkRepository.NODE_LIBS));\r
+ mLibs = parseLibs(XmlParserUtils.getFirstChild(packageNode, SdkRepoConstants.NODE_LIBS));\r
}\r
\r
/**\r
\r
if (child.getNodeType() == Node.ELEMENT_NODE &&\r
nsUri.equals(child.getNamespaceURI()) &&\r
- SdkRepository.NODE_LIB.equals(child.getLocalName())) {\r
+ SdkRepoConstants.NODE_LIB.equals(child.getLocalName())) {\r
libs.add(parseLib(child));\r
}\r
}\r
* Parses a <lib> element from a <libs> container.\r
*/\r
private Lib parseLib(Node libNode) {\r
- return new Lib(XmlParserUtils.getXmlString(libNode, SdkRepository.NODE_NAME),\r
- XmlParserUtils.getXmlString(libNode, SdkRepository.NODE_DESCRIPTION));\r
+ return new Lib(XmlParserUtils.getXmlString(libNode, SdkRepoConstants.NODE_NAME),\r
+ XmlParserUtils.getXmlString(libNode, SdkRepoConstants.NODE_DESCRIPTION));\r
}\r
\r
/** Returns the vendor, a string, for add-on packages. */\r
* A package has some attributes (revision, description) and a list of archives\r
* which represent the downloadable bits.\r
* <p/>\r
- * Packages are offered by a {@link RepoSource} (a download site).\r
+ * Packages are offered by a {@link SdkSource} (a download site).\r
*/\r
public class Archive implements IDescription {\r
\r
&& !link.startsWith("ftp://")) { //$NON-NLS-1$\r
// Make the URL absolute by prepending the source\r
Package pkg = getParentPackage();\r
- RepoSource src = pkg.getParentSource();\r
+ SdkSource src = pkg.getParentSource();\r
if (src == null) {\r
monitor.setResult("Internal error: no source for archive %1$s", name);\r
return null;\r
import com.android.sdklib.SdkManager;\r
import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Node;\r
\r
\r
/**\r
* Creates a new doc package from the attributes and elements of the given XML node.\r
- * <p/>\r
* This constructor should throw an exception if the package cannot be created.\r
+ *\r
+ * @param source The {@link SdkSource} where this is loaded from.\r
+ * @param packageNode The XML element being parsed.\r
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with\r
+ * parameters that vary according to the originating XML schema.\r
+ * @param licenses The licenses loaded from the XML originating document.\r
*/\r
- DocPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {\r
- super(source, packageNode, licenses);\r
+ DocPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
+ super(source, packageNode, nsUri, licenses);\r
\r
- int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_API_LEVEL, 0);\r
- String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_CODENAME);\r
+ int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0);\r
+ String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME);\r
if (codeName.length() == 0) {\r
codeName = null;\r
}\r
* <p/>\r
* By design, this creates a package with one and only one archive.\r
*/\r
- DocPackage(RepoSource source,\r
+ DocPackage(SdkSource source,\r
Properties props,\r
int apiLevel,\r
String codename,\r
import com.android.sdklib.SdkManager;\r
import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Node;\r
\r
\r
/**\r
* Creates a new tool package from the attributes and elements of the given XML node.\r
- * <p/>\r
* This constructor should throw an exception if the package cannot be created.\r
+ *\r
+ * @param source The {@link SdkSource} where this is loaded from.\r
+ * @param packageNode The XML element being parsed.\r
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with\r
+ * parameters that vary according to the originating XML schema.\r
+ * @param licenses The licenses loaded from the XML originating document.\r
*/\r
- ExtraPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {\r
- super(source, packageNode, licenses);\r
+ ExtraPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
+ super(source, packageNode, nsUri, licenses);\r
\r
- mPath = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_PATH);\r
+ mPath = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_PATH);\r
\r
- mMinApiLevel = XmlParserUtils.getXmlInt(packageNode, SdkRepository.NODE_MIN_API_LEVEL,\r
+ mMinApiLevel = XmlParserUtils.getXmlInt(packageNode, SdkRepoConstants.NODE_MIN_API_LEVEL,\r
MIN_API_LEVEL_NOT_SPECIFIED);\r
}\r
\r
* <p/>\r
* By design, this creates a package with one and only one archive.\r
*/\r
- ExtraPackage(RepoSource source,\r
+ ExtraPackage(SdkSource source,\r
Properties props,\r
String path,\r
int revision,\r
package com.android.sdklib.internal.repository;
-import com.android.sdklib.repository.SdkRepository;
+import com.android.sdklib.repository.SdkRepoConstants;
/**
* Interface used to decorate a {@link Package} that has a dependency
public interface IMinApiLevelDependency {
/**
- * The value of {@link #getMinApiLevel()} when the {@link SdkRepository#NODE_MIN_API_LEVEL}
+ * The value of {@link #getMinApiLevel()} when the {@link SdkRepoConstants#NODE_MIN_API_LEVEL}
* was not specified in the XML source.
*/
public static final int MIN_API_LEVEL_NOT_SPECIFIED = 0;
package com.android.sdklib.internal.repository;
-import com.android.sdklib.repository.SdkRepository;
+import com.android.sdklib.repository.SdkRepoConstants;
/**
* Interface used to decorate a {@link Package} that has a dependency
/**
* The value of {@link #getMinPlatformToolsRevision()} when the
- * {@link SdkRepository#NODE_MIN_PLATFORM_TOOLS_REV} was not specified in the XML source.
+ * {@link SdkRepoConstants#NODE_MIN_PLATFORM_TOOLS_REV} was not specified in the XML source.
* Since this is a required attribute in the XML schema, it can only happen when dealing
* with an invalid repository XML.
*/
package com.android.sdklib.internal.repository;
-import com.android.sdklib.repository.SdkRepository;
+import com.android.sdklib.repository.SdkRepoConstants;
/**
* Interface used to decorate a {@link Package} that has a dependency
public interface IMinToolsDependency {
/**
- * The value of {@link #getMinToolsRevision()} when the {@link SdkRepository#NODE_MIN_TOOLS_REV}
- * was not specified in the XML source.
+ * The value of {@link #getMinToolsRevision()} when the
+ * {@link SdkRepoConstants#NODE_MIN_TOOLS_REV} was not specified in the XML source.
*/
public static final int MIN_TOOLS_REV_NOT_SPECIFIED = 0;
\r
// We're not going to check that all tools are present. At the very least\r
// we should expect to find adb, aidl, aapt and dx (adapted to the current OS).\r
+\r
+ if (platformToolsFolder.listFiles() == null) {\r
+ // ListFiles is null if the directory doesn't even exist.\r
+ // Not going to find anything in there...\r
+ return null;\r
+ }\r
+\r
Set<String> names = new HashSet<String>();\r
for (File file : platformToolsFolder.listFiles()) {\r
names.add(file.getName());\r
\r
import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Node;\r
\r
\r
/**\r
* Creates a new package from the attributes and elements of the given XML node.\r
- * <p/>\r
* This constructor should throw an exception if the package cannot be created.\r
+ *\r
+ * @param source The {@link SdkSource} where this is loaded from.\r
+ * @param packageNode The XML element being parsed.\r
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with\r
+ * parameters that vary according to the originating XML schema.\r
+ * @param licenses The licenses loaded from the XML originating document.\r
*/\r
- MinToolsPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {\r
- super(source, packageNode, licenses);\r
+ MinToolsPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
+ super(source, packageNode, nsUri, licenses);\r
\r
- mMinToolsRevision = XmlParserUtils.getXmlInt(packageNode, SdkRepository.NODE_MIN_TOOLS_REV,\r
+ mMinToolsRevision = XmlParserUtils.getXmlInt(packageNode,\r
+ SdkRepoConstants.NODE_MIN_TOOLS_REV,\r
MIN_TOOLS_REV_NOT_SPECIFIED);\r
}\r
\r
* By design, this creates a package with one and only one archive.\r
*/\r
public MinToolsPackage(\r
- RepoSource source,\r
+ SdkSource source,\r
Properties props,\r
int revision,\r
String license,\r
import com.android.sdklib.SdkManager;\r
import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Node;\r
\r
* A package has some attributes (revision, description) and a list of archives\r
* which represent the downloadable bits.\r
* <p/>\r
- * Packages are contained by a {@link RepoSource} (a download site).\r
+ * Packages are contained by a {@link SdkSource} (a download site).\r
* <p/>\r
* Derived classes must implement the {@link IDescription} methods.\r
*/\r
private final String mReleaseNote;\r
private final String mReleaseUrl;\r
private final Archive[] mArchives;\r
- private final RepoSource mSource;\r
+ private final SdkSource mSource;\r
\r
/**\r
* Enum for the result of {@link Package#canBeUpdatedBy(Package)}. This used so that we can\r
\r
/**\r
* Creates a new package from the attributes and elements of the given XML node.\r
- * <p/>\r
* This constructor should throw an exception if the package cannot be created.\r
+ *\r
+ * @param source The {@link SdkSource} where this is loaded from.\r
+ * @param packageNode The XML element being parsed.\r
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with\r
+ * parameters that vary according to the originating XML schema.\r
+ * @param licenses The licenses loaded from the XML originating document.\r
*/\r
- Package(RepoSource source, Node packageNode, Map<String,String> licenses) {\r
+ Package(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
mSource = source;\r
- mRevision = XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_REVISION, 0);\r
- mDescription = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_DESCRIPTION);\r
- mDescUrl = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_DESC_URL);\r
- mReleaseNote = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_RELEASE_NOTE);\r
- mReleaseUrl = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_RELEASE_URL);\r
+ mRevision = XmlParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_REVISION, 0);\r
+ mDescription = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_DESCRIPTION);\r
+ mDescUrl = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_DESC_URL);\r
+ mReleaseNote = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_RELEASE_NOTE);\r
+ mReleaseUrl = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_RELEASE_URL);\r
mObsolete = XmlParserUtils.getOptionalXmlString(\r
- packageNode, SdkRepository.NODE_OBSOLETE);\r
+ packageNode, SdkRepoConstants.NODE_OBSOLETE);\r
\r
mLicense = parseLicense(packageNode, licenses);\r
mArchives = parseArchives(XmlParserUtils.getFirstChild(\r
- packageNode, SdkRepository.NODE_ARCHIVES));\r
+ packageNode, SdkRepoConstants.NODE_ARCHIVES));\r
}\r
\r
/**\r
* By design, this creates a package with one and only one archive.\r
*/\r
public Package(\r
- RepoSource source,\r
+ SdkSource source,\r
Properties props,\r
int revision,\r
String license,\r
if (props != null && source == null && srcUrl != null) {\r
boolean isUser = Boolean.parseBoolean(props.getProperty(PROP_USER_SOURCE,\r
Boolean.TRUE.toString()));\r
- source = new RepoSource(srcUrl, isUser);\r
+ if (isUser || (this instanceof AddonPackage)) {\r
+ source = new SdkAddonSource(srcUrl, isUser);\r
+ } else {\r
+ source = new SdkRepoSource(srcUrl);\r
+ }\r
}\r
mSource = source;\r
\r
*/\r
private String parseLicense(Node packageNode, Map<String, String> licenses) {\r
Node usesLicense = XmlParserUtils.getFirstChild(\r
- packageNode, SdkRepository.NODE_USES_LICENSE);\r
+ packageNode, SdkRepoConstants.NODE_USES_LICENSE);\r
if (usesLicense != null) {\r
- Node ref = usesLicense.getAttributes().getNamedItem(SdkRepository.ATTR_REF);\r
+ Node ref = usesLicense.getAttributes().getNamedItem(SdkRepoConstants.ATTR_REF);\r
if (ref != null) {\r
String licenseRef = ref.getNodeValue();\r
return licenses.get(licenseRef);\r
\r
if (child.getNodeType() == Node.ELEMENT_NODE &&\r
nsUri.equals(child.getNamespaceURI()) &&\r
- SdkRepository.NODE_ARCHIVE.equals(child.getLocalName())) {\r
+ SdkRepoConstants.NODE_ARCHIVE.equals(child.getLocalName())) {\r
archives.add(parseArchive(child));\r
}\r
}\r
private Archive parseArchive(Node archiveNode) {\r
Archive a = new Archive(\r
this,\r
- (Os) XmlParserUtils.getEnumAttribute(archiveNode, SdkRepository.ATTR_OS,\r
+ (Os) XmlParserUtils.getEnumAttribute(archiveNode, SdkRepoConstants.ATTR_OS,\r
Os.values(), null),\r
- (Arch) XmlParserUtils.getEnumAttribute(archiveNode, SdkRepository.ATTR_ARCH,\r
+ (Arch) XmlParserUtils.getEnumAttribute(archiveNode, SdkRepoConstants.ATTR_ARCH,\r
Arch.values(), Arch.ANY),\r
- XmlParserUtils.getXmlString(archiveNode, SdkRepository.NODE_URL),\r
- XmlParserUtils.getXmlLong (archiveNode, SdkRepository.NODE_SIZE, 0),\r
- XmlParserUtils.getXmlString(archiveNode, SdkRepository.NODE_CHECKSUM)\r
+ XmlParserUtils.getXmlString(archiveNode, SdkRepoConstants.NODE_URL),\r
+ XmlParserUtils.getXmlLong (archiveNode, SdkRepoConstants.NODE_SIZE, 0),\r
+ XmlParserUtils.getXmlString(archiveNode, SdkRepoConstants.NODE_CHECKSUM)\r
);\r
\r
return a;\r
/**\r
* Returns the source that created (and owns) this package. Can be null.\r
*/\r
- public RepoSource getParentSource() {\r
+ public SdkSource getParentSource() {\r
return mSource;\r
}\r
\r
import com.android.sdklib.SdkManager;\r
import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Node;\r
\r
\r
/**\r
* Creates a new platform package from the attributes and elements of the given XML node.\r
- * <p/>\r
* This constructor should throw an exception if the package cannot be created.\r
+ *\r
+ * @param source The {@link SdkSource} where this is loaded from.\r
+ * @param packageNode The XML element being parsed.\r
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with\r
+ * parameters that vary according to the originating XML schema.\r
+ * @param licenses The licenses loaded from the XML originating document.\r
*/\r
- PlatformPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {\r
- super(source, packageNode, licenses);\r
+ PlatformPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
+ super(source, packageNode, nsUri, licenses);\r
\r
- mVersionName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_VERSION);\r
- int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_API_LEVEL, 0);\r
- String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_CODENAME);\r
+ mVersionName = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_VERSION);\r
+ int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0);\r
+ String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME);\r
if (codeName.length() == 0) {\r
codeName = null;\r
}\r
/**
* Creates a new platform-tool package from the attributes and elements of the given XML node.
- * <p/>
* This constructor should throw an exception if the package cannot be created.
+ *
+ * @param source The {@link SdkSource} where this is loaded from.
+ * @param packageNode The XML element being parsed.
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with
+ * parameters that vary according to the originating XML schema.
+ * @param licenses The licenses loaded from the XML originating document.
*/
- PlatformToolPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {
- super(source, packageNode, licenses);
+ PlatformToolPackage(SdkSource source, Node packageNode,
+ String nsUri, Map<String,String> licenses) {
+ super(source, packageNode, nsUri, licenses);
}
/**
* By design, this creates a package with one and only one archive.
*/
PlatformToolPackage(
- RepoSource source,
+ SdkSource source,
Properties props,
int revision,
String license,
import com.android.sdklib.AndroidVersion.AndroidVersionException;\r
import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Node;\r
\r
\r
/**\r
* Creates a new sample package from the attributes and elements of the given XML node.\r
- * <p/>\r
* This constructor should throw an exception if the package cannot be created.\r
+ *\r
+ * @param source The {@link SdkSource} where this is loaded from.\r
+ * @param packageNode The XML element being parsed.\r
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with\r
+ * parameters that vary according to the originating XML schema.\r
+ * @param licenses The licenses loaded from the XML originating document.\r
*/\r
- SamplePackage(RepoSource source, Node packageNode, Map<String,String> licenses) {\r
- super(source, packageNode, licenses);\r
+ SamplePackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
+ super(source, packageNode, nsUri, licenses);\r
\r
- int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepository.NODE_API_LEVEL, 0);\r
- String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepository.NODE_CODENAME);\r
+ int apiLevel = XmlParserUtils.getXmlInt (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0);\r
+ String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME);\r
if (codeName.length() == 0) {\r
codeName = null;\r
}\r
mVersion = new AndroidVersion(apiLevel, codeName);\r
\r
- mMinApiLevel = XmlParserUtils.getXmlInt(packageNode, SdkRepository.NODE_MIN_API_LEVEL,\r
+ mMinApiLevel = XmlParserUtils.getXmlInt(packageNode, SdkRepoConstants.NODE_MIN_API_LEVEL,\r
MIN_API_LEVEL_NOT_SPECIFIED);\r
}\r
\r
--- /dev/null
+/*\r
+ * Copyright (C) 2009 The Android Open Source Project\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package com.android.sdklib.internal.repository;\r
+\r
+import com.android.sdklib.annotations.Nullable;\r
+import com.android.sdklib.repository.SdkAddonConstants;\r
+\r
+import org.w3c.dom.Document;\r
+\r
+import java.io.InputStream;\r
+\r
+\r
+/**\r
+ * An sdk-addon source, i.e. a download site for addons and extra packages.\r
+ * A repository describes one or more {@link Package}s available for download.\r
+ */\r
+public class SdkAddonSource extends SdkSource {\r
+\r
+ /**\r
+ * Constructs a new source for the given repository URL.\r
+ * @param url The source URL. Cannot be null. If the URL ends with a /, the default\r
+ * repository.xml filename will be appended automatically.\r
+ * @param userSource True if this a user source (add-ons & packages only.)\r
+ */\r
+ public SdkAddonSource(String url, boolean userSource) {\r
+ super(url, false);\r
+ }\r
+\r
+ /**\r
+ * Returns true if this is an addon source.\r
+ * We only load addons and extras from these sources.\r
+ */\r
+ @Override\r
+ public boolean isAddonSource() {\r
+ return true;\r
+ }\r
+\r
+ @Override\r
+ protected String getUrlDefaultXmlFile() {\r
+ return SdkAddonConstants.URL_DEFAULT_XML_FILE;\r
+ }\r
+\r
+ @Override\r
+ protected int getNsLatestVersion() {\r
+ return SdkAddonConstants.NS_LATEST_VERSION;\r
+ }\r
+\r
+ @Override\r
+ protected String getNsUri() {\r
+ return SdkAddonConstants.NS_URI;\r
+ }\r
+\r
+ @Override\r
+ protected String getNsPattern() {\r
+ return SdkAddonConstants.NS_PATTERN;\r
+ }\r
+\r
+ @Override\r
+ protected String getSchemaUri(int version) {\r
+ return SdkAddonConstants.getSchemaUri(version);\r
+ }\r
+\r
+ @Override\r
+ protected String getRootElementName() {\r
+ return SdkAddonConstants.NODE_SDK_ADDON;\r
+ }\r
+\r
+ @Override\r
+ protected InputStream getXsdStream(int version) {\r
+ return SdkAddonConstants.getXsdStream(version);\r
+ }\r
+\r
+ /**\r
+ * There is no support forward evolution of the sdk-addon schema yet since we\r
+ * currently have only one version.\r
+ *\r
+ * @param xml The input XML stream. Can be null.\r
+ * @return Always null.\r
+ * @null This implementation always return null.\r
+ */\r
+ @Override\r
+ protected Document findAlternateToolsXml(@Nullable InputStream xml) {\r
+ return null;\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2009 The Android Open Source Project\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ */\r
+\r
+package com.android.sdklib.internal.repository;\r
+\r
+import com.android.sdklib.annotations.Nullable;\r
+import com.android.sdklib.internal.repository.Archive.Arch;\r
+import com.android.sdklib.internal.repository.Archive.Os;\r
+import com.android.sdklib.repository.CommonConstants;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
+\r
+import org.w3c.dom.Attr;\r
+import org.w3c.dom.Document;\r
+import org.w3c.dom.Element;\r
+import org.w3c.dom.NamedNodeMap;\r
+import org.w3c.dom.Node;\r
+import org.w3c.dom.Text;\r
+\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.util.regex.Pattern;\r
+\r
+import javax.xml.parsers.DocumentBuilder;\r
+import javax.xml.parsers.DocumentBuilderFactory;\r
+\r
+\r
+/**\r
+ * An sdk-repository source, i.e. a download site.\r
+ * A repository describes one or more {@link Package}s available for download.\r
+ */\r
+public class SdkRepoSource extends SdkSource {\r
+\r
+ /**\r
+ * Constructs a new source for the given repository URL.\r
+ * @param url The source URL. Cannot be null. If the URL ends with a /, the default\r
+ * repository.xml filename will be appended automatically.\r
+ */\r
+ public SdkRepoSource(String url) {\r
+ super(url, false);\r
+ }\r
+\r
+ /**\r
+ * Returns true if this is an addon source.\r
+ * We only load addons and extras from these sources.\r
+ */\r
+ @Override\r
+ public boolean isAddonSource() {\r
+ return false;\r
+ }\r
+\r
+ @Override\r
+ protected String getUrlDefaultXmlFile() {\r
+ return SdkRepoConstants.URL_DEFAULT_XML_FILE;\r
+ }\r
+\r
+ @Override\r
+ protected int getNsLatestVersion() {\r
+ return SdkRepoConstants.NS_LATEST_VERSION;\r
+ }\r
+\r
+ @Override\r
+ protected String getNsUri() {\r
+ return SdkRepoConstants.NS_URI;\r
+ }\r
+\r
+ @Override\r
+ protected String getNsPattern() {\r
+ return SdkRepoConstants.NS_PATTERN;\r
+ }\r
+\r
+ @Override\r
+ protected String getSchemaUri(int version) {\r
+ return SdkRepoConstants.getSchemaUri(version);\r
+ }\r
+\r
+ @Override\r
+ protected String getRootElementName() {\r
+ return SdkRepoConstants.NODE_SDK_REPOSITORY;\r
+ }\r
+\r
+ @Override\r
+ protected InputStream getXsdStream(int version) {\r
+ return SdkRepoConstants.getXsdStream(version);\r
+ }\r
+\r
+\r
+ /**\r
+ * The purpose of this method is to support forward evolution of our schema.\r
+ * <p/>\r
+ * At this point, we know that xml does not point to any schema that this version of\r
+ * the tool knows how to process, so it's not one of the possible 1..N versions of our\r
+ * XSD schema.\r
+ * <p/>\r
+ * We thus try to interpret the byte stream as a possible XML stream. It may not be\r
+ * one at all in the first place. If it looks anything line an XML schema, we try to\r
+ * find its <tool> and the <platform-tools> elements. If we find any,\r
+ * we recreate a suitable document that conforms to what we expect from our XSD schema\r
+ * with only those elements.\r
+ * <p/>\r
+ * To be valid, the <tool> and the <platform-tools> elements must have at\r
+ * least one <archive> compatible with this platform.\r
+ * <p/>\r
+ * Starting the sdk-repository schema v3, <tools> has a <min-platform-tools-rev>\r
+ * node, so technically the corresponding XML schema will be usable only if there's a\r
+ * <platform-tools> with the request revision number. We don't enforce that here, as\r
+ * this is done at install time.\r
+ * <p/>\r
+ * If we don't find anything suitable, we drop the whole thing.\r
+ *\r
+ * @param xml The input XML stream. Can be null.\r
+ * @return Either a new XML document conforming to our schema with at least one <tool>\r
+ * and <platform-tools> element or null.\r
+ * @throws IOException if InputStream.reset() fails\r
+ * @null Can return null on failure.\r
+ */\r
+ @Override\r
+ protected Document findAlternateToolsXml(@Nullable InputStream xml) throws IOException {\r
+ if (xml == null) {\r
+ return null;\r
+ }\r
+\r
+ // Reset the stream if it supports that operation.\r
+ xml.reset();\r
+\r
+ // Get an XML document\r
+\r
+ Document oldDoc = null;\r
+ Document newDoc = null;\r
+ try {\r
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();\r
+ factory.setIgnoringComments(false);\r
+ factory.setValidating(false);\r
+\r
+ // Parse the old document using a non namespace aware builder\r
+ factory.setNamespaceAware(false);\r
+ DocumentBuilder builder = factory.newDocumentBuilder();\r
+ oldDoc = builder.parse(xml);\r
+\r
+ // Prepare a new document using a namespace aware builder\r
+ factory.setNamespaceAware(true);\r
+ builder = factory.newDocumentBuilder();\r
+ newDoc = builder.newDocument();\r
+\r
+ } catch (Exception e) {\r
+ // Failed to get builder factor\r
+ // Failed to create XML document builder\r
+ // Failed to parse XML document\r
+ // Failed to read XML document\r
+ }\r
+\r
+ if (oldDoc == null || newDoc == null) {\r
+ return null;\r
+ }\r
+\r
+\r
+ // Check the root element is an XML with at least the following properties:\r
+ // <sdk:sdk-repository\r
+ // xmlns:sdk="http://schemas.android.com/sdk/android/repository/$N">\r
+ //\r
+ // Note that we don't have namespace support enabled, we just do it manually.\r
+\r
+ Pattern nsPattern = Pattern.compile(getNsPattern());\r
+\r
+ Node oldRoot = null;\r
+ String prefix = null;\r
+ for (Node child = oldDoc.getFirstChild(); child != null; child = child.getNextSibling()) {\r
+ if (child.getNodeType() == Node.ELEMENT_NODE) {\r
+ prefix = null;\r
+ String name = child.getNodeName();\r
+ int pos = name.indexOf(':');\r
+ if (pos > 0 && pos < name.length() - 1) {\r
+ prefix = name.substring(0, pos);\r
+ name = name.substring(pos + 1);\r
+ }\r
+ if (SdkRepoConstants.NODE_SDK_REPOSITORY.equals(name)) {\r
+ NamedNodeMap attrs = child.getAttributes();\r
+ String xmlns = "xmlns"; //$NON-NLS-1$\r
+ if (prefix != null) {\r
+ xmlns += ":" + prefix; //$NON-NLS-1$\r
+ }\r
+ Node attr = attrs.getNamedItem(xmlns);\r
+ if (attr != null) {\r
+ String uri = attr.getNodeValue();\r
+ if (uri != null && nsPattern.matcher(uri).matches()) {\r
+ oldRoot = child;\r
+ break;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ // we must have found the root node, and it must have an XML namespace prefix.\r
+ if (oldRoot == null || prefix == null || prefix.length() == 0) {\r
+ return null;\r
+ }\r
+\r
+ final String ns = getNsUri();\r
+ Element newRoot = newDoc.createElementNS(ns, getRootElementName());\r
+ newRoot.setPrefix(prefix);\r
+ newDoc.appendChild(newRoot);\r
+ int numTool = 0;\r
+\r
+ // Find any inner <tool> or <platform-tool> nodes and extract their required parameters\r
+\r
+ String[] elementNames = {\r
+ SdkRepoConstants.NODE_TOOL,\r
+ SdkRepoConstants.NODE_PLATFORM_TOOL,\r
+ SdkRepoConstants.NODE_LICENSE\r
+ };\r
+\r
+ Element element = null;\r
+ while ((element = findChild(oldRoot, element, prefix, elementNames)) != null) {\r
+ boolean isElementValid = false;\r
+\r
+ String name = element.getLocalName();\r
+ if (name == null) {\r
+ name = element.getNodeName();\r
+\r
+ int pos = name.indexOf(':');\r
+ if (pos > 0 && pos < name.length() - 1) {\r
+ name = name.substring(pos + 1);\r
+ }\r
+ }\r
+\r
+ // To be valid, the tool or platform-tool element must have:\r
+ // - a <revision> element with a number\r
+ // - a <min-platform-tools-rev> element with a number for a <tool> element\r
+ // - an <archives> element with one or more <archive> elements inside\r
+ // - one of the <archive> elements must have an "os" and "arch" attributes\r
+ // compatible with the current platform. Only keep the first such element found.\r
+ // - the <archive> element must contain a <size>, a <checksum> and a <url>.\r
+ // - none of the above for a license element\r
+\r
+ if (SdkRepoConstants.NODE_LICENSE.equals(name)) {\r
+ isElementValid = true;\r
+\r
+ } else {\r
+ try {\r
+ Node revision = findChild(element, null, prefix, CommonConstants.NODE_REVISION);\r
+ Node archives = findChild(element, null, prefix, CommonConstants.NODE_ARCHIVES);\r
+\r
+ if (revision == null || archives == null) {\r
+ continue;\r
+ }\r
+\r
+ // check revision contains a number\r
+ try {\r
+ String content = revision.getTextContent();\r
+ content = content.trim();\r
+ int rev = Integer.parseInt(content);\r
+ if (rev < 1) {\r
+ continue;\r
+ }\r
+ } catch (NumberFormatException ignore) {\r
+ continue;\r
+ }\r
+\r
+ if (SdkRepoConstants.NODE_TOOL.equals(name)) {\r
+ Node minPTRev = findChild(element, null, prefix,\r
+ CommonConstants.NODE_MIN_PLATFORM_TOOLS_REV);\r
+\r
+ if (minPTRev == null) {\r
+ continue;\r
+ }\r
+\r
+ // check min-platform-tools-rev contains a number\r
+ try {\r
+ String content = minPTRev.getTextContent();\r
+ content = content.trim();\r
+ int rev = Integer.parseInt(content);\r
+ if (rev < 1) {\r
+ continue;\r
+ }\r
+ } catch (NumberFormatException ignore) {\r
+ continue;\r
+ }\r
+ }\r
+\r
+ Node archive = null;\r
+ while ((archive = findChild(archives,\r
+ archive,\r
+ prefix,\r
+ CommonConstants.NODE_ARCHIVE)) != null) {\r
+ try {\r
+ Os os = (Os) XmlParserUtils.getEnumAttribute(archive,\r
+ CommonConstants.ATTR_OS,\r
+ Os.values(),\r
+ null /*default*/);\r
+ Arch arch = (Arch) XmlParserUtils.getEnumAttribute(archive,\r
+ CommonConstants.ATTR_ARCH,\r
+ Arch.values(),\r
+ Arch.ANY);\r
+ if (os == null || !os.isCompatible() ||\r
+ arch == null || !arch.isCompatible()) {\r
+ continue;\r
+ }\r
+\r
+ Node node = findChild(archive, null, prefix, CommonConstants.NODE_URL);\r
+ String url = node == null ? null : node.getTextContent().trim();\r
+ if (url == null || url.length() == 0) {\r
+ continue;\r
+ }\r
+\r
+ node = findChild(archive, null, prefix, CommonConstants.NODE_SIZE);\r
+ long size = 0;\r
+ try {\r
+ size = Long.parseLong(node.getTextContent());\r
+ } catch (Exception e) {\r
+ // pass\r
+ }\r
+ if (size < 1) {\r
+ continue;\r
+ }\r
+\r
+ node = findChild(archive, null, prefix, CommonConstants.NODE_CHECKSUM);\r
+ // double check that the checksum element contains a type=sha1 attribute\r
+ if (node == null) {\r
+ continue;\r
+ }\r
+ NamedNodeMap attrs = node.getAttributes();\r
+ Node typeNode = attrs.getNamedItem(CommonConstants.ATTR_TYPE);\r
+ if (typeNode == null ||\r
+ !CommonConstants.ATTR_TYPE.equals(typeNode.getNodeName()) ||\r
+ !CommonConstants.SHA1_TYPE.equals(typeNode.getNodeValue())) {\r
+ continue;\r
+ }\r
+ String sha1 = node == null ? null : node.getTextContent().trim();\r
+ if (sha1 == null ||\r
+ sha1.length() != CommonConstants.SHA1_CHECKSUM_LEN) {\r
+ continue;\r
+ }\r
+\r
+ isElementValid = true;\r
+\r
+ } catch (Exception ignore1) {\r
+ // pass\r
+ }\r
+ } // while <archive>\r
+ } catch (Exception ignore2) {\r
+ // For debugging it is useful to re-throw the exception.\r
+ // For end-users, not so much. It would be nice to make it\r
+ // happen automatically during unit tests.\r
+ if (System.getenv("TESTING") != null) {\r
+ throw new RuntimeException(ignore2);\r
+ }\r
+ }\r
+ }\r
+\r
+ if (isElementValid) {\r
+ duplicateNode(newRoot, element, SdkRepoConstants.NS_URI, prefix);\r
+ numTool++;\r
+ }\r
+ } // while <tool>\r
+\r
+ return numTool > 0 ? newDoc : null;\r
+ }\r
+\r
+ /**\r
+ * Helper method used by {@link #findAlternateToolsXml(InputStream)} to find a given\r
+ * element child in a root XML node.\r
+ */\r
+ private Element findChild(Node rootNode, Node after, String prefix, String[] nodeNames) {\r
+ for (int i = 0; i < nodeNames.length; i++) {\r
+ if (nodeNames[i].indexOf(':') < 0) {\r
+ nodeNames[i] = prefix + ":" + nodeNames[i];\r
+ }\r
+ }\r
+ Node child = after == null ? rootNode.getFirstChild() : after.getNextSibling();\r
+ for(; child != null; child = child.getNextSibling()) {\r
+ if (child.getNodeType() != Node.ELEMENT_NODE) {\r
+ continue;\r
+ }\r
+ for (String nodeName : nodeNames) {\r
+ if (nodeName.equals(child.getNodeName())) {\r
+ return (Element) child;\r
+ }\r
+ }\r
+ }\r
+ return null;\r
+ }\r
+\r
+ /**\r
+ * Helper method used by {@link #findAlternateToolsXml(InputStream)} to find a given\r
+ * element child in a root XML node.\r
+ */\r
+ private Node findChild(Node rootNode, Node after, String prefix, String nodeName) {\r
+ return findChild(rootNode, after, prefix, new String[] { nodeName });\r
+ }\r
+\r
+ /**\r
+ * Helper method used by {@link #findAlternateToolsXml(InputStream)} to duplicate a node\r
+ * and attach it to the given root in the new document.\r
+ */\r
+ private Element duplicateNode(Element newRootNode, Element oldNode,\r
+ String namespaceUri, String prefix) {\r
+ // The implementation here is more or less equivalent to\r
+ //\r
+ // newRoot.appendChild(newDoc.importNode(oldNode, deep=true))\r
+ //\r
+ // except we can't just use importNode() since we need to deal with the fact\r
+ // that the old document is not namespace-aware yet the new one is.\r
+\r
+ Document newDoc = newRootNode.getOwnerDocument();\r
+ Element newNode = null;\r
+\r
+ String nodeName = oldNode.getNodeName();\r
+ int pos = nodeName.indexOf(':');\r
+ if (pos > 0 && pos < nodeName.length() - 1) {\r
+ nodeName = nodeName.substring(pos + 1);\r
+ newNode = newDoc.createElementNS(namespaceUri, nodeName);\r
+ newNode.setPrefix(prefix);\r
+ } else {\r
+ newNode = newDoc.createElement(nodeName);\r
+ }\r
+\r
+ newRootNode.appendChild(newNode);\r
+\r
+ // Merge in all the attributes\r
+ NamedNodeMap attrs = oldNode.getAttributes();\r
+ for (int i = 0; i < attrs.getLength(); i++) {\r
+ Attr attr = (Attr) attrs.item(i);\r
+ Attr newAttr = null;\r
+\r
+ String attrName = oldNode.getNodeName();\r
+ pos = attrName.indexOf(':');\r
+ if (pos > 0 && pos < attrName.length() - 1) {\r
+ attrName = attrName.substring(pos + 1);\r
+ newAttr = newDoc.createAttributeNS(namespaceUri, attrName);\r
+ newAttr.setPrefix(prefix);\r
+ } else {\r
+ newAttr = newDoc.createAttribute(attrName);\r
+ }\r
+\r
+ newAttr.setNodeValue(attr.getNodeValue());\r
+\r
+ if (pos > 0) {\r
+ newNode.getAttributes().setNamedItemNS(newAttr);\r
+ } else {\r
+ newNode.getAttributes().setNamedItem(newAttr);\r
+ }\r
+ }\r
+\r
+ // Merge all child elements and texts\r
+ for (Node child = oldNode.getFirstChild(); child != null; child = child.getNextSibling()) {\r
+ if (child.getNodeType() == Node.ELEMENT_NODE) {\r
+ duplicateNode(newNode, (Element) child, namespaceUri, prefix);\r
+\r
+ } else if (child.getNodeType() == Node.TEXT_NODE) {\r
+ Text newText = newDoc.createTextNode(child.getNodeValue());\r
+ newNode.appendChild(newText);\r
+ }\r
+ }\r
+\r
+ return newNode;\r
+ }\r
+}\r
\r
package com.android.sdklib.internal.repository;\r
\r
-import com.android.sdklib.internal.repository.Archive.Arch;\r
-import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.annotations.Nullable;\r
+import com.android.sdklib.annotations.VisibleForTesting;\r
+import com.android.sdklib.annotations.VisibleForTesting.Visibility;\r
+import com.android.sdklib.repository.CommonConstants;\r
+import com.android.sdklib.repository.SdkAddonConstants;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Document;\r
-import org.w3c.dom.Element;\r
import org.w3c.dom.NamedNodeMap;\r
import org.w3c.dom.Node;\r
import org.xml.sax.InputSource;\r
import javax.xml.validation.Validator;\r
\r
/**\r
- * An sdk-repository source, i.e. a download site.\r
+ * An sdk-addon or sdk-repository source, i.e. a download site.\r
* It may be a full repository or an add-on only repository.\r
* A repository describes one or {@link Package}s available for download.\r
*/\r
-public class RepoSource implements IDescription {\r
+public abstract class SdkSource implements IDescription {\r
\r
private String mUrl;\r
private final boolean mUserSource;\r
* repository.xml filename will be appended automatically.\r
* @param userSource True if this a user source (add-ons & packages only.)\r
*/\r
- public RepoSource(String url, boolean userSource) {\r
+ public SdkSource(String url, boolean userSource) {\r
\r
// if the URL ends with a /, it must be "directory" resource,\r
// in which case we automatically add the default file that will\r
// looked for. This way it will be obvious to the user which\r
// resource we are actually trying to fetch.\r
if (url.endsWith("/")) { //$NON-NLS-1$\r
- url += SdkRepository.URL_DEFAULT_XML_FILE;\r
+ url += getUrlDefaultXmlFile();\r
}\r
\r
mUrl = url;\r
}\r
\r
/**\r
+ * Returns true if this is an addon source.\r
+ * We only load addons and extras from these sources.\r
+ */\r
+ public abstract boolean isAddonSource();\r
+\r
+ /** Returns SdkRepoConstants.URL_DEFAULT_XML_FILE or SdkAddonConstants.URL_DEFAULT_XML_FILE */\r
+ protected abstract String getUrlDefaultXmlFile();\r
+\r
+ /** Returns SdkRepoConstants.NS_LATEST_VERSION or SdkAddonConstants.NS_LATEST_VERSION. */\r
+ protected abstract int getNsLatestVersion();\r
+\r
+ /** Returns SdkRepoConstants.NS_URI or SdkAddonConstants.NS_URI. */\r
+ protected abstract String getNsUri();\r
+\r
+ /** Returns SdkRepoConstants.NS_PATTERN or SdkAddonConstants.NS_PATTERN. */\r
+ protected abstract String getNsPattern();\r
+\r
+ /** Returns SdkRepoConstants.getSchemaUri() or SdkAddonConstants.getSchemaUri(). */\r
+ protected abstract String getSchemaUri(int version);\r
+\r
+ /* Returns SdkRepoConstants.NODE_SDK_REPOSITORY or SdkAddonConstants.NODE_SDK_ADDON. */\r
+ protected abstract String getRootElementName();\r
+\r
+ /** Returns SdkRepoConstants.getXsdStream() or SdkAddonConstants.getXsdStream(). */\r
+ protected abstract InputStream getXsdStream(int version);\r
+\r
+ /**\r
+ * In case we fail to load an XML, examine the XML to see if it matches a <b>future</b>\r
+ * schema that as at least a <code>tools</code> node that we could load to update the\r
+ * SDK Manager.\r
+ *\r
+ * @param xml The input XML stream. Can be null.\r
+ * @return Null on failure, otherwise returns an XML DOM with just the tools we\r
+ * need to update this SDK Manager.\r
+ * @null Can return null on failure.\r
+ */\r
+ protected abstract Document findAlternateToolsXml(@Nullable InputStream xml)\r
+ throws IOException;\r
+\r
+ /**\r
* Two repo source are equal if they have the same userSource flag and the same URL.\r
*/\r
@Override\r
public boolean equals(Object obj) {\r
- if (obj instanceof RepoSource) {\r
- RepoSource rs = (RepoSource) obj;\r
+ if (obj instanceof SdkSource) {\r
+ SdkSource rs = (SdkSource) obj;\r
return rs.isUserSource() == this.isUserSource() && rs.getUrl().equals(this.getUrl());\r
}\r
return false;\r
return mUrl.hashCode() ^ Boolean.valueOf(mUserSource).hashCode();\r
}\r
\r
- /** Returns true if this is a user source. We only load addon and extra packages\r
- * from a user source and ignore the rest. */\r
+ /** Returns true if this is a user source. */\r
public boolean isUserSource() {\r
return mUserSource;\r
}\r
\r
- /** Returns the URL of the repository.xml file for this source. */\r
+ /** Returns the URL of the XML file for this source. */\r
public String getUrl() {\r
return mUrl;\r
}\r
\r
// If the original URL can't be fetched and the URL doesn't explicitly end with\r
// our filename, make another tentative after changing the URL.\r
- if (xml == null && !url.endsWith(SdkRepository.URL_DEFAULT_XML_FILE)) {\r
+ if (xml == null && !url.endsWith(getUrlDefaultXmlFile())) {\r
if (!url.endsWith("/")) { //$NON-NLS-1$\r
url += "/"; //$NON-NLS-1$\r
}\r
- url += SdkRepository.URL_DEFAULT_XML_FILE;\r
+ url += getUrlDefaultXmlFile();\r
\r
xml = fetchUrl(url, exception);\r
usingAlternateUrl = true;\r
// Explore the XML to find the potential XML schema version\r
int version = getXmlSchemaVersion(xml);\r
\r
- if (version >= 1 && version <= SdkRepository.NS_LATEST_VERSION) {\r
+ if (version >= 1 && version <= getNsLatestVersion()) {\r
// This should be a version we can handle. Try to validate it\r
// and report any error as invalid XML syntax,\r
\r
// what looks like a suitable root element with a suitable XMLNS\r
// so it must be a genuine error of an XML not conforming to the schema.\r
}\r
- } else if (version > SdkRepository.NS_LATEST_VERSION) {\r
+ } else if (version > getNsLatestVersion()) {\r
// The schema used is more recent than what is supported by this tool.\r
// Tell the user to upgrade, pointing him to the right version of the tool\r
// package.\r
\r
- validatedDoc = findAlternateToolsXml(xml);\r
+ try {\r
+ validatedDoc = findAlternateToolsXml(xml);\r
+ } catch (IOException e) {\r
+ // Failed, will be handled below.\r
+ }\r
if (validatedDoc != null) {\r
validationError[0] = null; // remove error from XML validation\r
- validatedUri = SdkRepository.NS_SDK_REPOSITORY;\r
+ validatedUri = getNsUri();\r
usingAlternateXml = true;\r
}\r
\r
// If we haven't already tried the alternate URL, let's do it now.\r
// We don't capture any fetch exception that happen during the second\r
// fetch in order to avoid hidding any previous fetch errors.\r
- if (!url.endsWith(SdkRepository.URL_DEFAULT_XML_FILE)) {\r
+ if (!url.endsWith(getUrlDefaultXmlFile())) {\r
if (!url.endsWith("/")) { //$NON-NLS-1$\r
url += "/"; //$NON-NLS-1$\r
}\r
- url += SdkRepository.URL_DEFAULT_XML_FILE;\r
+ url += getUrlDefaultXmlFile();\r
\r
xml = fetchUrl(url, null /*outException*/);\r
\r
/**\r
* Validates this XML against one of the requested SDK Repository schemas.\r
* If the XML was correctly validated, returns the schema that worked.\r
- * If it doesn't validate, returns null and store the error in outError[0].\r
+ * If it doesn't validate, returns null and stores the error in outError[0].\r
* If we can't find a validator, returns null and set validatorFound[0] to false.\r
*/\r
- private String validateXml(InputStream xml, String url, int version,\r
+ @VisibleForTesting(visibility=Visibility.PRIVATE)\r
+ protected String validateXml(InputStream xml, String url, int version,\r
String[] outError, Boolean[] validatorFound) {\r
\r
if (xml == null) {\r
\r
// Validation throws a bunch of possible Exceptions on failure.\r
validator.validate(new StreamSource(xml));\r
- return SdkRepository.getSchemaUri(version);\r
+ return getSchemaUri(version);\r
\r
} catch (SAXParseException e) {\r
outError[0] = String.format(\r
\r
} catch (Exception e) {\r
outError[0] = String.format(\r
- "XML verification failed for %1$s.\nError: %4$s",\r
+ "XML verification failed for %1$s.\nError: %2$s",\r
url,\r
e.toString());\r
}\r
* at the end of the xmlns:sdk="http://schemas.android.com/sdk/android/repository/$N"\r
* declaration.\r
*\r
- * @return 1..{@link SdkRepository#NS_LATEST_VERSION} for a valid schema version\r
+ * @return 1..{@link SdkRepoConstants#NS_LATEST_VERSION} for a valid schema version\r
* or 0 if no schema could be found.\r
*/\r
- private int getXmlSchemaVersion(InputStream xml) {\r
+ @VisibleForTesting(visibility=Visibility.PRIVATE)\r
+ protected int getXmlSchemaVersion(InputStream xml) {\r
if (xml == null) {\r
return 0;\r
}\r
//\r
// Note that we don't have namespace support enabled, we just do it manually.\r
\r
- Pattern nsPattern = Pattern.compile(SdkRepository.NS_SDK_REPOSITORY_PATTERN);\r
+ Pattern nsPattern = Pattern.compile(getNsPattern());\r
\r
String prefix = null;\r
for (Node child = doc.getFirstChild(); child != null; child = child.getNextSibling()) {\r
prefix = name.substring(0, pos);\r
name = name.substring(pos + 1);\r
}\r
- if (SdkRepository.NODE_SDK_REPOSITORY.equals(name)) {\r
+ if (getRootElementName().equals(name)) {\r
NamedNodeMap attrs = child.getAttributes();\r
String xmlns = "xmlns"; //$NON-NLS-1$\r
if (prefix != null) {\r
}\r
\r
/**\r
- * The purpose of this method is to support forward evolution of our schema.\r
- * <p/>\r
- * At this point, we know that xml does not point to any schema that this version of\r
- * the tool know how to process, so it's not one of the possible 1..N versions of our\r
- * XSD schema.\r
- * <p/>\r
- * We thus try to interpret the byte stream as a possible XML stream. It may not be\r
- * one at all in the first place. If it looks anything line an XML schema, we try to\r
- * find its <tool> elements. If we find any, we recreate a suitable document\r
- * that conforms to what we expect from our XSD schema with only those elements.\r
- * To be valid, the <tool> element must have at least one <archive>\r
- * compatible with this platform.\r
- *\r
- * If we don't find anything suitable, we drop the whole thing.\r
- *\r
- * @param xml The input XML stream. Can be null.\r
- * @return Either a new XML document conforming to our schema with at least one <tool>\r
- * element or null.\r
- */\r
- protected Document findAlternateToolsXml(InputStream xml) {\r
- // Note: protected for unit-test access\r
-\r
- if (xml == null) {\r
- return null;\r
- }\r
-\r
- // Reset the stream if it supports that operation.\r
- // At runtime we use a ByteArrayInputStream which can be reset; however for unit tests\r
- // we use a FileInputStream that doesn't support resetting and is read-once.\r
- try {\r
- xml.reset();\r
- } catch (IOException e1) {\r
- // ignore if not supported\r
- }\r
-\r
- // Get an XML document\r
-\r
- Document oldDoc = null;\r
- Document newDoc = null;\r
- try {\r
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();\r
- factory.setIgnoringComments(false);\r
- factory.setValidating(false);\r
-\r
- // Parse the old document using a non namespace aware builder\r
- factory.setNamespaceAware(false);\r
- DocumentBuilder builder = factory.newDocumentBuilder();\r
- oldDoc = builder.parse(xml);\r
-\r
- // Prepare a new document using a namespace aware builder\r
- factory.setNamespaceAware(true);\r
- builder = factory.newDocumentBuilder();\r
- newDoc = builder.newDocument();\r
-\r
- } catch (Exception e) {\r
- // Failed to get builder factor\r
- // Failed to create XML document builder\r
- // Failed to parse XML document\r
- // Failed to read XML document\r
- }\r
-\r
- if (oldDoc == null || newDoc == null) {\r
- return null;\r
- }\r
-\r
-\r
- // Check the root element is an XML with at least the following properties:\r
- // <sdk:sdk-repository\r
- // xmlns:sdk="http://schemas.android.com/sdk/android/repository/$N">\r
- //\r
- // Note that we don't have namespace support enabled, we just do it manually.\r
-\r
- Pattern nsPattern = Pattern.compile(SdkRepository.NS_SDK_REPOSITORY_PATTERN);\r
-\r
- Node oldRoot = null;\r
- String prefix = null;\r
- for (Node child = oldDoc.getFirstChild(); child != null; child = child.getNextSibling()) {\r
- if (child.getNodeType() == Node.ELEMENT_NODE) {\r
- prefix = null;\r
- String name = child.getNodeName();\r
- int pos = name.indexOf(':');\r
- if (pos > 0 && pos < name.length() - 1) {\r
- prefix = name.substring(0, pos);\r
- name = name.substring(pos + 1);\r
- }\r
- if (SdkRepository.NODE_SDK_REPOSITORY.equals(name)) {\r
- NamedNodeMap attrs = child.getAttributes();\r
- String xmlns = "xmlns"; //$NON-NLS-1$\r
- if (prefix != null) {\r
- xmlns += ":" + prefix; //$NON-NLS-1$\r
- }\r
- Node attr = attrs.getNamedItem(xmlns);\r
- if (attr != null) {\r
- String uri = attr.getNodeValue();\r
- if (uri != null && nsPattern.matcher(uri).matches()) {\r
- oldRoot = child;\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- // we must have found the root node, and it must have an XML namespace prefix.\r
- if (oldRoot == null || prefix == null || prefix.length() == 0) {\r
- return null;\r
- }\r
-\r
- final String ns = SdkRepository.NS_SDK_REPOSITORY;\r
- Element newRoot = newDoc.createElementNS(ns, SdkRepository.NODE_SDK_REPOSITORY);\r
- newRoot.setPrefix(prefix);\r
- newDoc.appendChild(newRoot);\r
- int numTool = 0;\r
-\r
- // Find an inner <tool> node and extract its required parameters\r
-\r
- Node tool = null;\r
- while ((tool = findChild(oldRoot, tool, prefix, SdkRepository.NODE_TOOL)) != null) {\r
- // To be valid, the tool element must have:\r
- // - a <revision> element with a number\r
- // - an optional <uses-license> node, which we'll skip right now.\r
- // (if we add it later, we must find the license declaration element too)\r
- // - an <archives> element with one or more <archive> elements inside\r
- // - one of the <archive> elements must have an "os" and "arch" attributes\r
- // compatible with the current platform. Only keep the first such element found.\r
- // - the <archive> element must contain a <size>, a <checksum> and a <url>.\r
-\r
- try {\r
- Node revision = findChild(tool, null, prefix, SdkRepository.NODE_REVISION);\r
- Node archives = findChild(tool, null, prefix, SdkRepository.NODE_ARCHIVES);\r
-\r
- if (revision == null || archives == null) {\r
- continue;\r
- }\r
-\r
- int rev = 0;\r
- try {\r
- String content = revision.getTextContent();\r
- content = content.trim();\r
- rev = Integer.parseInt(content);\r
- if (rev < 1) {\r
- continue;\r
- }\r
- } catch (NumberFormatException ignore) {\r
- continue;\r
- }\r
-\r
- Element newTool = newDoc.createElementNS(ns, SdkRepository.NODE_TOOL);\r
- newTool.setPrefix(prefix);\r
- appendChild(newTool, ns, prefix,\r
- SdkRepository.NODE_REVISION, Integer.toString(rev));\r
- Element newArchives = appendChild(newTool, ns, prefix,\r
- SdkRepository.NODE_ARCHIVES, null);\r
- int numArchives = 0;\r
-\r
- Node archive = null;\r
- while ((archive = findChild(archives,\r
- archive,\r
- prefix,\r
- SdkRepository.NODE_ARCHIVE)) != null) {\r
- try {\r
- Os os = (Os) XmlParserUtils.getEnumAttribute(archive,\r
- SdkRepository.ATTR_OS,\r
- Os.values(),\r
- null /*default*/);\r
- Arch arch = (Arch) XmlParserUtils.getEnumAttribute(archive,\r
- SdkRepository.ATTR_ARCH,\r
- Arch.values(),\r
- Arch.ANY);\r
- if (os == null || !os.isCompatible() ||\r
- arch == null || !arch.isCompatible()) {\r
- continue;\r
- }\r
-\r
- Node node = findChild(archive, null, prefix, SdkRepository.NODE_URL);\r
- String url = node == null ? null : node.getTextContent().trim();\r
- if (url == null || url.length() == 0) {\r
- continue;\r
- }\r
-\r
- node = findChild(archive, null, prefix, SdkRepository.NODE_SIZE);\r
- long size = 0;\r
- try {\r
- size = Long.parseLong(node.getTextContent());\r
- } catch (Exception e) {\r
- // pass\r
- }\r
- if (size < 1) {\r
- continue;\r
- }\r
-\r
- node = findChild(archive, null, prefix, SdkRepository.NODE_CHECKSUM);\r
- // double check that the checksum element contains a type=sha1 attribute\r
- if (node == null) {\r
- continue;\r
- }\r
- NamedNodeMap attrs = node.getAttributes();\r
- Node typeNode = attrs.getNamedItem(SdkRepository.ATTR_TYPE);\r
- if (typeNode == null ||\r
- !SdkRepository.ATTR_TYPE.equals(typeNode.getNodeName()) ||\r
- !SdkRepository.SHA1_TYPE.equals(typeNode.getNodeValue())) {\r
- continue;\r
- }\r
- String sha1 = node == null ? null : node.getTextContent().trim();\r
- if (sha1 == null || sha1.length() != SdkRepository.SHA1_CHECKSUM_LEN) {\r
- continue;\r
- }\r
-\r
- // Use that archive for the new tool element\r
- Element ar = appendChild(newArchives, ns, prefix,\r
- SdkRepository.NODE_ARCHIVE, null);\r
- ar.setAttributeNS(ns, SdkRepository.ATTR_OS, os.getXmlName());\r
- ar.setAttributeNS(ns, SdkRepository.ATTR_ARCH, arch.getXmlName());\r
-\r
- appendChild(ar, ns, prefix, SdkRepository.NODE_URL, url);\r
- appendChild(ar, ns, prefix, SdkRepository.NODE_SIZE, Long.toString(size));\r
- Element cs = appendChild(ar, ns, prefix, SdkRepository.NODE_CHECKSUM, sha1);\r
- cs.setAttributeNS(ns, SdkRepository.ATTR_TYPE, SdkRepository.SHA1_TYPE);\r
-\r
- numArchives++;\r
-\r
- } catch (Exception ignore1) {\r
- // pass\r
- }\r
- } // while <archive>\r
-\r
- if (numArchives > 0) {\r
- newRoot.appendChild(newTool);\r
- numTool++;\r
- }\r
- } catch (Exception ignore2) {\r
- // pass\r
- }\r
- } // while <tool>\r
-\r
- return numTool > 0 ? newDoc : null;\r
- }\r
-\r
- /**\r
- * Helper method used by {@link #findAlternateToolsXml(InputStream)} to find a given\r
- * element child in a root XML node.\r
- */\r
- private Node findChild(Node rootNode, Node after, String prefix, String nodeName) {\r
- nodeName = prefix + ":" + nodeName;\r
- Node child = after == null ? rootNode.getFirstChild() : after.getNextSibling();\r
- for(; child != null; child = child.getNextSibling()) {\r
- if (child.getNodeType() == Node.ELEMENT_NODE && nodeName.equals(child.getNodeName())) {\r
- return child;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * Helper method used by {@link #findAlternateToolsXml(InputStream)} to create a new\r
- * XML element into a parent element.\r
- */\r
- private Element appendChild(Element rootNode, String namespaceUri,\r
- String prefix, String nodeName,\r
- String nodeValue) {\r
- Element node = rootNode.getOwnerDocument().createElementNS(namespaceUri, nodeName);\r
- node.setPrefix(prefix);\r
- if (nodeValue != null) {\r
- node.setTextContent(nodeValue);\r
- }\r
- rootNode.appendChild(node);\r
- return node;\r
- }\r
-\r
-\r
- /**\r
* Helper method that returns a validator for our XSD, or null if the current Java\r
* implementation can't process XSD schemas.\r
*\r
* @param version The version of the XML Schema.\r
- * See {@link SdkRepository#getXsdStream(int)}\r
+ * See {@link SdkRepoConstants#getXsdStream(int)}\r
*/\r
private Validator getValidator(int version) throws SAXException {\r
- InputStream xsdStream = SdkRepository.getXsdStream(version);\r
+ InputStream xsdStream = getXsdStream(version);\r
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);\r
\r
if (factory == null) {\r
\r
assert doc != null;\r
\r
- Node root = getFirstChild(doc, nsUri, SdkRepository.NODE_SDK_REPOSITORY);\r
+ Node root = getFirstChild(doc, nsUri, getRootElementName());\r
if (root != null) {\r
\r
ArrayList<Package> packages = new ArrayList<Package>();\r
child = child.getNextSibling()) {\r
if (child.getNodeType() == Node.ELEMENT_NODE &&\r
nsUri.equals(child.getNamespaceURI()) &&\r
- child.getLocalName().equals(SdkRepository.NODE_LICENSE)) {\r
- Node id = child.getAttributes().getNamedItem(SdkRepository.ATTR_ID);\r
+ child.getLocalName().equals(CommonConstants.NODE_LICENSE)) {\r
+ Node id = child.getAttributes().getNamedItem(CommonConstants.ATTR_ID);\r
if (id != null) {\r
licenses.put(id.getNodeValue(), child.getTextContent());\r
}\r
try {\r
// We can load addon and extra packages from all sources, either\r
// internal or user sources.\r
- if (SdkRepository.NODE_ADD_ON.equals(name)) {\r
- p = new AddonPackage(this, child, licenses);\r
+ if (SdkAddonConstants.NODE_ADD_ON.equals(name)) {\r
+ p = new AddonPackage(this, child, nsUri, licenses);\r
\r
- } else if (SdkRepository.NODE_EXTRA.equals(name)) {\r
- p = new ExtraPackage(this, child, licenses);\r
+ } else if (CommonConstants.NODE_EXTRA.equals(name)) {\r
+ p = new ExtraPackage(this, child, nsUri, licenses);\r
\r
} else if (!mUserSource) {\r
// We only load platform, doc and tool packages from internal\r
// sources, never from user sources.\r
- if (SdkRepository.NODE_PLATFORM.equals(name)) {\r
- p = new PlatformPackage(this, child, licenses);\r
- } else if (SdkRepository.NODE_DOC.equals(name)) {\r
- p = new DocPackage(this, child, licenses);\r
- } else if (SdkRepository.NODE_TOOL.equals(name)) {\r
- p = new ToolPackage(this, child, licenses);\r
- } else if (SdkRepository.NODE_PLATFORM_TOOL.equals(name)) {\r
- p = new PlatformToolPackage(this, child, licenses);\r
- } else if (SdkRepository.NODE_SAMPLE.equals(name)) {\r
- p = new SamplePackage(this, child, licenses);\r
+ if (SdkRepoConstants.NODE_PLATFORM.equals(name)) {\r
+ p = new PlatformPackage(this, child, nsUri, licenses);\r
+ } else if (SdkRepoConstants.NODE_DOC.equals(name)) {\r
+ p = new DocPackage(this, child, nsUri, licenses);\r
+ } else if (SdkRepoConstants.NODE_TOOL.equals(name)) {\r
+ p = new ToolPackage(this, child, nsUri, licenses);\r
+ } else if (SdkRepoConstants.NODE_PLATFORM_TOOL.equals(name)) {\r
+ p = new PlatformToolPackage(this, child, nsUri, licenses);\r
+ } else if (SdkRepoConstants.NODE_SAMPLE.equals(name)) {\r
+ p = new SamplePackage(this, child, nsUri, licenses);\r
}\r
}\r
\r
}\r
} catch (Exception e) {\r
// Ignore invalid packages\r
+ monitor.setResult("Ignoring invalid %1$s element: %2$s",\r
+ name, e.toString());\r
}\r
}\r
}\r
*\r
* On error, returns null and prints a (hopefully) useful message on the monitor.\r
*/\r
- private Document getDocument(ByteArrayInputStream xml, ITaskMonitor monitor) {\r
+ @VisibleForTesting(visibility=Visibility.PRIVATE)\r
+ protected Document getDocument(InputStream xml, ITaskMonitor monitor) {\r
try {\r
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();\r
factory.setIgnoringComments(true);\r
import java.util.Properties;\r
\r
/**\r
- * A list of sdk-repository sources.\r
+ * A list of sdk-repository and sdk-addon sources.\r
*/\r
-public class RepoSources {\r
+public class SdkSources {\r
\r
private static final String KEY_COUNT = "count";\r
\r
\r
private static final String SRC_FILENAME = "repositories.cfg"; //$NON-NLS-1$\r
\r
- private ArrayList<RepoSource> mSources = new ArrayList<RepoSource>();\r
+ private ArrayList<SdkSource> mSources = new ArrayList<SdkSource>();\r
\r
- public RepoSources() {\r
+ public SdkSources() {\r
}\r
\r
/**\r
* Adds a new source to the Sources list.\r
*/\r
- public void add(RepoSource source) {\r
+ public void add(SdkSource source) {\r
mSources.add(source);\r
}\r
\r
/**\r
* Removes a source from the Sources list.\r
*/\r
- public void remove(RepoSource source) {\r
+ public void remove(SdkSource source) {\r
mSources.remove(source);\r
}\r
\r
/**\r
* Returns the sources list array. This is never null.\r
*/\r
- public RepoSource[] getSources() {\r
- return mSources.toArray(new RepoSource[mSources.size()]);\r
+ public SdkSource[] getSources() {\r
+ return mSources.toArray(new SdkSource[mSources.size()]);\r
}\r
\r
/**\r
public void loadUserSources(ISdkLog log) {\r
\r
// Remove all existing user sources\r
- for (Iterator<RepoSource> it = mSources.iterator(); it.hasNext(); ) {\r
- RepoSource s = it.next();\r
+ for (Iterator<SdkSource> it = mSources.iterator(); it.hasNext(); ) {\r
+ SdkSource s = it.next();\r
if (s.isUserSource()) {\r
it.remove();\r
}\r
for (int i = 0; i < count; i++) {\r
String url = props.getProperty(String.format("%s%02d", KEY_SRC, i)); //$NON-NLS-1$\r
if (url != null) {\r
- RepoSource s = new RepoSource(url, true /*userSource*/);\r
+ SdkSource s = new SdkAddonSource(url, true /*userSource*/);\r
if (!hasSource(s)) {\r
mSources.add(s);\r
}\r
* <p/>\r
* The search is O(N), which should be acceptable on the expectedly small source list.\r
*/\r
- public boolean hasSource(RepoSource source) {\r
- for (RepoSource s : mSources) {\r
+ public boolean hasSource(SdkSource source) {\r
+ for (SdkSource s : mSources) {\r
if (s.equals(source)) {\r
return true;\r
}\r
Properties props = new Properties();\r
\r
int count = 0;\r
- for (RepoSource s : mSources) {\r
+ for (SdkSource s : mSources) {\r
if (s.isUserSource()) {\r
count++;\r
props.setProperty(String.format("%s%02d", KEY_SRC, count), s.getUrl()); //$NON-NLS-1$\r
import com.android.sdklib.SdkManager;\r
import com.android.sdklib.internal.repository.Archive.Arch;\r
import com.android.sdklib.internal.repository.Archive.Os;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
\r
import org.w3c.dom.Node;\r
\r
import java.io.InputStreamReader;\r
import java.util.Map;\r
import java.util.Properties;\r
+import java.util.regex.Matcher;\r
+import java.util.regex.Pattern;\r
\r
/**\r
* Represents a tool XML node in an SDK repository.\r
\r
/**\r
* Creates a new tool package from the attributes and elements of the given XML node.\r
- * <p/>\r
* This constructor should throw an exception if the package cannot be created.\r
+ *\r
+ * @param source The {@link SdkSource} where this is loaded from.\r
+ * @param packageNode The XML element being parsed.\r
+ * @param nsUri The namespace URI of the originating XML document, to be able to deal with\r
+ * parameters that vary according to the originating XML schema.\r
+ * @param licenses The licenses loaded from the XML originating document.\r
*/\r
- ToolPackage(RepoSource source, Node packageNode, Map<String,String> licenses) {\r
- super(source, packageNode, licenses);\r
+ ToolPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {\r
+ super(source, packageNode, nsUri, licenses);\r
\r
mMinPlatformToolsRevision = XmlParserUtils.getXmlInt(\r
packageNode,\r
- SdkRepository.NODE_MIN_PLATFORM_TOOLS_REV,\r
+ SdkRepoConstants.NODE_MIN_PLATFORM_TOOLS_REV,\r
MIN_PLATFORM_TOOLS_REV_INVALID);\r
if (mMinPlatformToolsRevision == MIN_PLATFORM_TOOLS_REV_INVALID) {\r
- throw new IllegalArgumentException(\r
- String.format("Missing %1$s element in %2$s package",\r
- SdkRepository.NODE_MIN_PLATFORM_TOOLS_REV,\r
- SdkRepository.NODE_PLATFORM_TOOL));\r
+ // This revision number is mandatory starting with sdk-repository-3.xsd\r
+ // and did not exist before. Complain if the URI has level >= 3.\r
+\r
+ boolean needRevision = false;\r
+\r
+ Pattern nsPattern = Pattern.compile(SdkRepoConstants.NS_PATTERN);\r
+ Matcher m = nsPattern.matcher(nsUri);\r
+ if (m.matches()) {\r
+ String version = m.group(1);\r
+ try {\r
+ needRevision = Integer.parseInt(version) >= 3;\r
+ } catch (NumberFormatException e) {\r
+ // ignore. needRevision defaults to false\r
+ }\r
+ }\r
+\r
+ if (needRevision) {\r
+ throw new IllegalArgumentException(\r
+ String.format("Missing %1$s element in %2$s package",\r
+ SdkRepoConstants.NODE_MIN_PLATFORM_TOOLS_REV,\r
+ SdkRepoConstants.NODE_PLATFORM_TOOL));\r
+ }\r
}\r
}\r
\r
* By design, this creates a package with one and only one archive.\r
*/\r
ToolPackage(\r
- RepoSource source,\r
+ SdkSource source,\r
Properties props,\r
int revision,\r
String license,\r
/*\r
- * Copyright (C) 2009 The Android Open Source Project\r
+ * Copyright (C) 2010 The Android Open Source Project\r
*\r
* Licensed under the Eclipse Public License, Version 1.0 (the "License");\r
* you may not use this file except in compliance with the License.\r
package com.android.sdklib.repository;\r
\r
\r
-import java.io.InputStream;\r
\r
/**\r
- * Public constants for the sdk-repository XML Schema.\r
+ * Public constants common to the sdk-repository and sdk-addon XML Schemas.\r
*/\r
-public class SdkRepository {\r
-\r
- /** The URL of the official Google sdk-repository site. */\r
- public static final String URL_GOOGLE_SDK_REPO_SITE =\r
- "https://dl-ssl.google.com/android/repository/"; //$NON-NLS-1$\r
-\r
- public static final String URL_DEFAULT_XML_FILE = "repository.xml"; //$NON-NLS-1$\r
-\r
- /** The base of our XML namespace. */\r
- private static final String NS_SDK_REPOSITORY_BASE =\r
- "http://schemas.android.com/sdk/android/repository/"; //$NON-NLS-1$\r
-\r
- /** The pattern of our XML namespace. Matcher's group(1) is the schema version (integer). */\r
- public static final String NS_SDK_REPOSITORY_PATTERN =\r
- NS_SDK_REPOSITORY_BASE + "([1-9][0-9]*)"; //$NON-NLS-1$\r
-\r
- /** The latest version of the sdk-repository XML Schema.\r
- * Valid version numbers are between 1 and this number, included. */\r
- public static final int NS_LATEST_VERSION = 3;\r
-\r
- /** The XML namespace of the latest sdk-repository XML. */\r
- public static final String NS_SDK_REPOSITORY = getSchemaUri(NS_LATEST_VERSION);\r
-\r
- /** The root sdk-repository element */\r
- public static final String NODE_SDK_REPOSITORY = "sdk-repository"; //$NON-NLS-1$\r
-\r
- /** A platform package. */\r
- public static final String NODE_PLATFORM = "platform"; //$NON-NLS-1$\r
- /** An add-on package. */\r
- public static final String NODE_ADD_ON = "add-on"; //$NON-NLS-1$\r
- /** A tool package. */\r
- public static final String NODE_TOOL = "tool"; //$NON-NLS-1$\r
- /** A platform-tool package. */\r
- public static final String NODE_PLATFORM_TOOL = "platform-tool"; //$NON-NLS-1$\r
- /** A doc package. */\r
- public static final String NODE_DOC = "doc"; //$NON-NLS-1$\r
- /** A sample package. */\r
- public static final String NODE_SAMPLE = "sample"; //$NON-NLS-1$\r
+public class CommonConstants {\r
+\r
/** An extra package. */\r
public static final String NODE_EXTRA = "extra"; //$NON-NLS-1$\r
\r
- /**\r
- * List of possible nodes in a repository XML. Used to populate options automatically\r
- * in the no-GUI mode.\r
- */\r
- public static final String[] NODES = {\r
- NODE_PLATFORM,\r
- NODE_ADD_ON,\r
- NODE_TOOL,\r
- NODE_PLATFORM_TOOL,\r
- NODE_DOC,\r
- NODE_SAMPLE,\r
- NODE_EXTRA\r
- };\r
-\r
/** The license definition. */\r
public static final String NODE_LICENSE = "license"; //$NON-NLS-1$\r
/** The optional uses-license for all packages or for a lib. */\r
/** Length of a string representing a SHA1 checksum; always 40 characters long. */\r
public static final int SHA1_CHECKSUM_LEN = 40;\r
\r
-\r
- /**\r
- * Returns a stream to the requested repository XML Schema.\r
- *\r
- * @param version Between 1 and {@link #NS_LATEST_VERSION}, included.\r
- * @return An {@link InputStream} object for the local XSD file or\r
- * null if there is no schema for the requested version.\r
- */\r
- public static InputStream getXsdStream(int version) {\r
- String filename = String.format("sdk-repository-%d.xsd", version); //$NON-NLS-1$\r
- return SdkRepository.class.getResourceAsStream(filename);\r
- }\r
-\r
- /**\r
- * Returns the URI of the SDK Repository schema for the given version number.\r
- * @param version Between 1 and {@link #NS_LATEST_VERSION} included.\r
- */\r
- public static String getSchemaUri(int version) {\r
- return String.format(NS_SDK_REPOSITORY_BASE + "%d", version); //$NON-NLS-1$\r
- }\r
}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2010 The Android Open Source Project\r
+ *\r
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php\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.repository;\r
+\r
+\r
+import java.io.InputStream;\r
+\r
+/**\r
+ * Public constants for the sdk-addon XML Schema.\r
+ */\r
+public class SdkAddonConstants extends CommonConstants {\r
+\r
+ /** The URL of the official Google sdk-addon site. */\r
+ public static final String URL_GOOGLE_SDK_SITE =\r
+ "https://dl-ssl.google.com/android/repository/"; //$NON-NLS-1$\r
+\r
+ public static final String URL_DEFAULT_XML_FILE = "addon.xml"; //$NON-NLS-1$\r
+\r
+ /** The base of our sdk-addon XML namespace. */\r
+ private static final String NS_BASE =\r
+ "http://schemas.android.com/sdk/android/addon/"; //$NON-NLS-1$\r
+\r
+ /**\r
+ * The pattern of our sdk-addon XML namespace.\r
+ * Matcher's group(1) is the schema version (integer).\r
+ */\r
+ public static final String NS_PATTERN = NS_BASE + "([1-9][0-9]*)"; //$NON-NLS-1$\r
+\r
+ /** The latest version of the sdk-addon XML Schema.\r
+ * Valid version numbers are between 1 and this number, included. */\r
+ public static final int NS_LATEST_VERSION = 3;\r
+\r
+ /** The XML namespace of the latest sdk-addon XML. */\r
+ public static final String NS_URI = getSchemaUri(NS_LATEST_VERSION);\r
+\r
+ /** The root sdk-addon element */\r
+ public static final String NODE_SDK_ADDON = "sdk-addon"; //$NON-NLS-1$\r
+\r
+ /** An add-on package. */\r
+ public static final String NODE_ADD_ON = "add-on"; //$NON-NLS-1$\r
+\r
+ /**\r
+ * List of possible nodes in a repository XML. Used to populate options automatically\r
+ * in the no-GUI mode.\r
+ */\r
+ public static final String[] NODES = {\r
+ NODE_ADD_ON,\r
+ NODE_EXTRA\r
+ };\r
+\r
+ /**\r
+ * Returns a stream to the requested sdk-addon XML Schema.\r
+ *\r
+ * @param version Between 1 and {@link #NS_LATEST_VERSION}, included.\r
+ * @return An {@link InputStream} object for the local XSD file or\r
+ * null if there is no schema for the requested version.\r
+ */\r
+ public static InputStream getXsdStream(int version) {\r
+ String filename = String.format("sdk-addon-%d.xsd", version); //$NON-NLS-1$\r
+ return SdkAddonConstants.class.getResourceAsStream(filename);\r
+ }\r
+\r
+ /**\r
+ * Returns the URI of the sdk-addon schema for the given version number.\r
+ * @param version Between 1 and {@link #NS_LATEST_VERSION} included.\r
+ */\r
+ public static String getSchemaUri(int version) {\r
+ return String.format(NS_BASE + "%d", version); //$NON-NLS-1$\r
+ }\r
+}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2009 The Android Open Source Project\r
+ *\r
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php\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.repository;\r
+\r
+\r
+import java.io.InputStream;\r
+\r
+/**\r
+ * Public constants for the sdk-repository XML Schema.\r
+ */\r
+public class SdkRepoConstants extends CommonConstants {\r
+\r
+ /** The URL of the official Google sdk-repository site. */\r
+ public static final String URL_GOOGLE_SDK_SITE =\r
+ "https://dl-ssl.google.com/android/repository/"; //$NON-NLS-1$\r
+\r
+ public static final String URL_DEFAULT_XML_FILE = "repository.xml"; //$NON-NLS-1$\r
+\r
+ /** The base of our sdk-repository XML namespace. */\r
+ private static final String NS_BASE =\r
+ "http://schemas.android.com/sdk/android/repository/"; //$NON-NLS-1$\r
+\r
+ /**\r
+ * The pattern of our sdk-repository XML namespace.\r
+ * Matcher's group(1) is the schema version (integer).\r
+ */\r
+ public static final String NS_PATTERN = NS_BASE + "([1-9][0-9]*)"; //$NON-NLS-1$\r
+\r
+ /** The latest version of the sdk-repository XML Schema.\r
+ * Valid version numbers are between 1 and this number, included. */\r
+ public static final int NS_LATEST_VERSION = 3;\r
+\r
+ /** The XML namespace of the latest sdk-repository XML. */\r
+ public static final String NS_URI = getSchemaUri(NS_LATEST_VERSION);\r
+\r
+ /** The root sdk-repository element */\r
+ public static final String NODE_SDK_REPOSITORY = "sdk-repository"; //$NON-NLS-1$\r
+\r
+ /** A platform package. */\r
+ public static final String NODE_PLATFORM = "platform"; //$NON-NLS-1$\r
+ /** A tool package. */\r
+ public static final String NODE_TOOL = "tool"; //$NON-NLS-1$\r
+ /** A platform-tool package. */\r
+ public static final String NODE_PLATFORM_TOOL = "platform-tool"; //$NON-NLS-1$\r
+ /** A doc package. */\r
+ public static final String NODE_DOC = "doc"; //$NON-NLS-1$\r
+ /** A sample package. */\r
+ public static final String NODE_SAMPLE = "sample"; //$NON-NLS-1$\r
+\r
+ /**\r
+ * List of possible nodes in a repository XML. Used to populate options automatically\r
+ * in the no-GUI mode.\r
+ */\r
+ public static final String[] NODES = {\r
+ NODE_PLATFORM,\r
+ NODE_TOOL,\r
+ NODE_PLATFORM_TOOL,\r
+ NODE_DOC,\r
+ NODE_SAMPLE,\r
+ NODE_EXTRA\r
+ };\r
+\r
+ /**\r
+ * Returns a stream to the requested repository XML Schema.\r
+ *\r
+ * @param version Between 1 and {@link #NS_LATEST_VERSION}, included.\r
+ * @return An {@link InputStream} object for the local XSD file or\r
+ * null if there is no schema for the requested version.\r
+ */\r
+ public static InputStream getXsdStream(int version) {\r
+ String filename = String.format("sdk-repository-%d.xsd", version); //$NON-NLS-1$\r
+ return SdkRepoConstants.class.getResourceAsStream(filename);\r
+ }\r
+\r
+ /**\r
+ * Returns the URI of the SDK Repository schema for the given version number.\r
+ * @param version Between 1 and {@link #NS_LATEST_VERSION} included.\r
+ */\r
+ public static String getSchemaUri(int version) {\r
+ return String.format(NS_BASE + "%d", version); //$NON-NLS-1$\r
+ }\r
+}\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Copyright (C) 2010 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/addon/1"
+ xmlns:xsd="http://www.w3.org/2001/XMLSchema"
+ xmlns:sa1="http://schemas.android.com/sdk/android/addon/1"
+ 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 Addon repository is a web site that contains an "addon.xml"
+ file that conforms to this XML Schema.
+
+ History:
+ - v1 is used by the SDK Updater in Tools r8. It is split out of the
+ main SDK Repository XML Schema and can only contain <addon> and
+ <extra> packages.
+ -->
+
+ <xsd:element name="sdk-addon" type="sa1:repositoryType" />
+
+ <xsd:complexType name="repositoryType">
+ <xsd:annotation>
+ <xsd:documentation>
+ The repository contains a collection of downloadable packages.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:choice minOccurs="0" maxOccurs="unbounded">
+ <xsd:element name="add-on" type="sa1:addonType" />
+ <xsd:element name="extra" type="sa1:extraType" />
+ <xsd:element name="license" type="sa1:licenseType" />
+ </xsd:choice>
+ </xsd:complexType>
+
+ <!-- The definition of an SDK Add-on package. -->
+
+ <xsd:complexType name="addonType">
+ <xsd:annotation>
+ <xsd:documentation>An SDK add-on package.</xsd:documentation>
+ </xsd:annotation>
+ <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="sa1:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <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="sa1:archivesType" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+
+ <!-- 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>
+
+
+ <!-- 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:complexType name="extraType" >
+ <xsd:annotation>
+ <xsd:documentation>
+ An SDK extra package. This kind of package is for "free"
+ content and specifies in which fixed root directory it must be
+ installed.
+ The paths "add-ons", "platforms", "tools" and "docs" are
+ reserved and cannot be used.
+ </xsd:documentation>
+ </xsd:annotation>
+ <xsd:all>
+ <!-- The install folder name. It must be a single-segment path.
+ The paths "add-ons", "platforms", "tools" and "docs" are
+ reserved and cannot be used.
+ -->
+ <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="sa1:usesLicenseType" minOccurs="0" />
+ <!-- The optional description of this package. -->
+ <xsd:element name="description" type="xsd:string" minOccurs="0" />
+ <!-- The optional description URL of this package -->
+ <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="sa1:archivesType" />
+ <!-- The minimal revision of tools required by this package.
+ Optional. If present, must be an int > 0. -->
+ <xsd:element name="min-tools-rev" type="xsd:positiveInteger" minOccurs="0" />
+ <!-- The minimal API level required by this package.
+ Optional. If present, must be an int > 0. -->
+ <xsd:element name="min-api-level" type="xsd:positiveInteger" minOccurs="0" />
+
+ <!-- An optional element indicating the package is obsolete.
+ The string content is however currently not defined and ignored. -->
+ <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
+ </xsd:all>
+ </xsd:complexType>
+
+
+ <!-- The definition of a license to be referenced by the uses-license element. -->
+
+ <xsd:complexType name="licenseType">
+ <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: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>
+
+
+ <!-- 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="usesLicenseType">
+ <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="sa1: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="sa1:sha1Number">
+ <xsd:attribute name="type" type="xsd:token" fixed="sha1" />
+ </xsd:extension>
+ </xsd:simpleContent>
+ </xsd:complexType>
+
+</xsd:schema>
and platform-specific tools are installed in $SDK/platform-tools
- There's a new element <min-platform-tools-rev> in <tool>. The tool package now
requires that at least some minimal version of <platform-tool> be installed.
+ - It removes the <addon> repository type, which is now in its own XML Schema.
-->
<xsd:element name="sdk-repository" type="sr3:repositoryType" />
</xsd:annotation>
<xsd:choice minOccurs="0" maxOccurs="unbounded">
<xsd:element name="platform" type="sr3:platformType" />
- <xsd:element name="add-on" type="sr3:addonType" />
<xsd:element name="tool" type="sr3:toolType" />
<xsd:element name="platform-tool" type="sr3:platformToolType" />
<xsd:element name="doc" type="sr3:docType" />
</xsd:complexType>
- <!-- The definition of an SDK Add-on package. -->
-
- <xsd:complexType name="addonType">
- <xsd:annotation>
- <xsd:documentation>An SDK add-on package.</xsd:documentation>
- </xsd:annotation>
- <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="sr3:usesLicenseType" minOccurs="0" />
- <!-- The optional description of this package. -->
- <xsd:element name="description" type="xsd:string" minOccurs="0" />
- <!-- The optional description URL of this package -->
- <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="sr3:archivesType" />
-
- <!-- An optional element indicating the package is obsolete.
- The string content is however currently not defined and ignored. -->
- <xsd:element name="obsolete" type="xsd:string" minOccurs="0" />
-
- <!-- 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>
-
-
<!-- The definition of an SDK tool package. -->
<xsd:complexType name="toolType" >
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.
+ Path names matching existing package types here (e.g. "add-ons",
+ "platforms", "tools", "docs", etc.) are reserved and cannot be used.
</xsd:documentation>
</xsd:annotation>
<xsd:all>
\r
package com.android.sdklib.internal.repository;\r
\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkAddonConstants;\r
\r
import org.w3c.dom.Document;\r
\r
import java.io.ByteArrayInputStream;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
import java.io.InputStream;\r
\r
import junit.framework.TestCase;\r
\r
/**\r
- * Tests for {@link RepoSource}\r
+ * Tests for {@link SdkAddonSource}\r
*/\r
-public class RepoSourceTest extends TestCase {\r
+public class SdkAddonSourceTest extends TestCase {\r
\r
private static class MockMonitor implements ITaskMonitor {\r
+\r
+ String mCapturedResults = "";\r
+ String mCapturedDescriptions = "";\r
+\r
+ public String getCapturedResults() {\r
+ return mCapturedResults;\r
+ }\r
+\r
+ public String getCapturedDescriptions() {\r
+ return mCapturedDescriptions;\r
+ }\r
+\r
public void setResult(String resultFormat, Object... args) {\r
+ mCapturedResults += String.format(resultFormat, args) + "\n";\r
}\r
\r
public void setProgressMax(int max) {\r
}\r
\r
public void setDescription(String descriptionFormat, Object... args) {\r
+ mCapturedDescriptions += String.format(descriptionFormat, args) + "\n";\r
}\r
\r
public boolean isCancelRequested() {\r
* An internal helper class to give us visibility to the protected members we want\r
* to test.\r
*/\r
- private static class MockRepoSource extends RepoSource {\r
- public MockRepoSource() {\r
- super("fake-url", false /*userSource*/);\r
+ private static class MockSdkAddonSource extends SdkAddonSource {\r
+ public MockSdkAddonSource() {\r
+ super("fake-url", true /*userSource*/);\r
}\r
\r
public Document _findAlternateToolsXml(InputStream xml) {\r
public boolean _parsePackages(Document doc, String nsUri, ITaskMonitor monitor) {\r
return super.parsePackages(doc, nsUri, monitor);\r
}\r
+\r
+ public int _getXmlSchemaVersion(InputStream xml) {\r
+ return super.getXmlSchemaVersion(xml);\r
+ }\r
+\r
+ public String _validateXml(InputStream xml, String url, int version,\r
+ String[] outError, Boolean[] validatorFound) {\r
+ return super.validateXml(xml, url, version, outError, validatorFound);\r
+ }\r
+\r
+ public Document _getDocument(InputStream xml, ITaskMonitor monitor) {\r
+ return super.getDocument(xml, monitor);\r
+ }\r
+\r
}\r
\r
- private MockRepoSource mSource;\r
+ private MockSdkAddonSource mSource;\r
\r
@Override\r
protected void setUp() throws Exception {\r
super.setUp();\r
\r
- mSource = new MockRepoSource();\r
+ mSource = new MockSdkAddonSource();\r
}\r
\r
@Override\r
mSource = null;\r
}\r
\r
- public void testFindAlternateToolsXml_Errors() {\r
+ public void testFindAlternateToolsXml_Errors() throws Exception {\r
// Support null as input\r
Document result = mSource._findAlternateToolsXml(null);\r
assertNull(result);\r
assertNull(result);\r
}\r
\r
- public void testFindAlternateToolsXml_1() {\r
- InputStream xmlStream = this.getClass().getResourceAsStream(\r
- "/com/android/sdklib/testdata/repository_sample_1.xml");\r
+ /**\r
+ * Validate that findAlternateToolsXml doesn't work for addon even\r
+ * when trying to load a valid addon xml.\r
+ */\r
+ public void testFindAlternateToolsXml_1() throws Exception {\r
+ InputStream xmlStream = getTestResource("/com/android/sdklib/testdata/addon_sample_1.xml");\r
\r
Document result = mSource._findAlternateToolsXml(xmlStream);\r
- assertNotNull(result);\r
- assertTrue(mSource._parsePackages(result,\r
- SdkRepository.NS_SDK_REPOSITORY, new MockMonitor()));\r
+ assertNull(result);\r
+ }\r
\r
- // check the packages we found... we expected to find 2 tool packages with 1 archive each.\r
+ /**\r
+ * Validate we can still load a valid addon schema version 1\r
+ */\r
+ public void testLoadOldXml_1() throws Exception {\r
+ InputStream xmlStream = getTestResource("/com/android/sdklib/testdata/addon_sample_1.xml");\r
+\r
+ // guess the version from the XML document\r
+ int version = mSource._getXmlSchemaVersion(xmlStream);\r
+ assertEquals(1, version);\r
+\r
+ Boolean[] validatorFound = new Boolean[] { Boolean.FALSE };\r
+ String[] validationError = new String[] { null };\r
+ String url = "not-a-valid-url://" + SdkAddonConstants.URL_DEFAULT_XML_FILE;\r
+\r
+ String uri = mSource._validateXml(xmlStream, url, version, validationError, validatorFound);\r
+ assertEquals(Boolean.TRUE, validatorFound[0]);\r
+ assertEquals(null, validationError[0]);\r
+ assertEquals(SdkAddonConstants.getSchemaUri(1), uri);\r
+\r
+ // Validation was successful, load the document\r
+ MockMonitor monitor = new MockMonitor();\r
+ Document doc = mSource._getDocument(xmlStream, monitor);\r
+ assertNotNull(doc);\r
+\r
+ // Get the packages\r
+ assertTrue(mSource._parsePackages(doc, uri, monitor));\r
+\r
+ assertEquals("Found My First add-on by John Doe, Android API 1, revision 1\n" +\r
+ "Found My Second add-on by John Deer, Android API 2, revision 42\n" +\r
+ "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +\r
+ "Found Usb Driver package, revision 43 (Obsolete)\n" +\r
+ "Found Extra Api Dep package, revision 2 (Obsolete)\n",\r
+ monitor.getCapturedDescriptions());\r
+ assertEquals("", monitor.getCapturedResults());\r
+\r
+ // check the packages we found... we expected to find 11 packages with each at least\r
+ // one archive.\r
Package[] pkgs = mSource.getPackages();\r
- assertEquals(2, pkgs.length);\r
+ assertEquals(5, pkgs.length);\r
for (Package p : pkgs) {\r
- assertEquals(ToolPackage.class, p.getClass());\r
- assertEquals(1, p.getArchives().length);\r
+ assertTrue(p.getArchives().length >= 1);\r
}\r
}\r
\r
+ /**\r
+ * Returns an SdkLib file resource as a {@link ByteArrayInputStream},\r
+ * which has the advantage that we can use {@link InputStream#reset()} on it\r
+ * at any time to read it multiple times.\r
+ * <p/>\r
+ * The default for getResourceAsStream() is to return a {@link FileInputStream} that\r
+ * does not support reset(), yet we need it in the tested code.\r
+ *\r
+ * @throws IOException if some I/O read fails\r
+ */\r
+ private ByteArrayInputStream getTestResource(String filename) throws IOException {\r
+ InputStream xmlStream = this.getClass().getResourceAsStream(filename);\r
+\r
+ try {\r
+ byte[] data = new byte[8192];\r
+ int offset = 0;\r
+ int n;\r
+\r
+ while ((n = xmlStream.read(data, offset, data.length - offset)) != -1) {\r
+ offset += n;\r
+\r
+ if (offset == data.length) {\r
+ byte[] newData = new byte[offset + 8192];\r
+ System.arraycopy(data, 0, newData, 0, offset);\r
+ data = newData;\r
+ }\r
+ }\r
+\r
+ return new ByteArrayInputStream(data, 0, offset);\r
+ } finally {\r
+ if (xmlStream != null) {\r
+ xmlStream.close();\r
+ }\r
+ }\r
+ }\r
}\r
--- /dev/null
+/*\r
+ * Copyright (C) 2009 The Android Open Source Project\r
+ *\r
+ * Licensed under the Eclipse Public License, Version 1.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.eclipse.org/org/documents/epl-v10.php\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.SdkRepoConstants;\r
+\r
+import org.w3c.dom.Document;\r
+\r
+import java.io.ByteArrayInputStream;\r
+import java.io.FileInputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+\r
+import junit.framework.TestCase;\r
+\r
+/**\r
+ * Tests for {@link SdkRepoSource}\r
+ */\r
+public class SdkRepoSourceTest extends TestCase {\r
+\r
+ private static class MockMonitor implements ITaskMonitor {\r
+\r
+ String mCapturedResults = "";\r
+ String mCapturedDescriptions = "";\r
+\r
+ public String getCapturedResults() {\r
+ return mCapturedResults;\r
+ }\r
+\r
+ public String getCapturedDescriptions() {\r
+ return mCapturedDescriptions;\r
+ }\r
+\r
+ public void setResult(String resultFormat, Object... args) {\r
+ mCapturedResults += String.format(resultFormat, args) + "\n";\r
+ }\r
+\r
+ public void setProgressMax(int max) {\r
+ }\r
+\r
+ public void setDescription(String descriptionFormat, Object... args) {\r
+ mCapturedDescriptions += String.format(descriptionFormat, args) + "\n";\r
+ }\r
+\r
+ public boolean isCancelRequested() {\r
+ return false;\r
+ }\r
+\r
+ public void incProgress(int delta) {\r
+ }\r
+\r
+ public int getProgress() {\r
+ return 0;\r
+ }\r
+\r
+ public boolean displayPrompt(String title, String message) {\r
+ return false;\r
+ }\r
+\r
+ public ITaskMonitor createSubMonitor(int tickCount) {\r
+ return null;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * An internal helper class to give us visibility to the protected members we want\r
+ * to test.\r
+ */\r
+ private static class MockSdkRepoSource extends SdkRepoSource {\r
+ public MockSdkRepoSource() {\r
+ super("fake-url");\r
+ }\r
+\r
+ public Document _findAlternateToolsXml(InputStream xml) throws IOException {\r
+ return super.findAlternateToolsXml(xml);\r
+ }\r
+\r
+ public boolean _parsePackages(Document doc, String nsUri, ITaskMonitor monitor) {\r
+ return super.parsePackages(doc, nsUri, monitor);\r
+ }\r
+\r
+ public int _getXmlSchemaVersion(InputStream xml) {\r
+ return super.getXmlSchemaVersion(xml);\r
+ }\r
+\r
+ public String _validateXml(InputStream xml, String url, int version,\r
+ String[] outError, Boolean[] validatorFound) {\r
+ return super.validateXml(xml, url, version, outError, validatorFound);\r
+ }\r
+\r
+ public Document _getDocument(InputStream xml, ITaskMonitor monitor) {\r
+ return super.getDocument(xml, monitor);\r
+ }\r
+\r
+ }\r
+\r
+ private MockSdkRepoSource mSource;\r
+\r
+ @Override\r
+ protected void setUp() throws Exception {\r
+ super.setUp();\r
+\r
+ mSource = new MockSdkRepoSource();\r
+ }\r
+\r
+ @Override\r
+ protected void tearDown() throws Exception {\r
+ super.tearDown();\r
+\r
+ mSource = null;\r
+ }\r
+\r
+ public void testFindAlternateToolsXml_Errors() throws Exception {\r
+ // Support null as input\r
+ Document result = mSource._findAlternateToolsXml(null);\r
+ assertNull(result);\r
+\r
+ // Support an empty input\r
+ String str = "";\r
+ ByteArrayInputStream input = new ByteArrayInputStream(str.getBytes());\r
+ result = mSource._findAlternateToolsXml(input);\r
+ assertNull(result);\r
+\r
+ // Support a random string as input\r
+ str = "Some random string, not even HTML nor XML";\r
+ input = new ByteArrayInputStream(str.getBytes());\r
+ result = mSource._findAlternateToolsXml(input);\r
+ assertNull(result);\r
+\r
+ // Support an HTML input, e.g. a typical 404 document as returned by DL\r
+ str = "<html><head> " +\r
+ "<meta http-equiv=\"content-type\" content=\"text/html;charset=utf-8\"> " +\r
+ "<title>404 Not Found</title> " + "<style><!--" + "body {font-family: arial,sans-serif}" +\r
+ "div.nav { ... blah blah more css here ... color: green}" +\r
+ "//--></style> " + "<script><!--" + "var rc=404;" + "//-->" + "</script> " + "</head> " +\r
+ "<body text=#000000 bgcolor=#ffffff> " +\r
+ "<table border=0 cellpadding=2 cellspacing=0 width=100%><tr><td rowspan=3 width=1% nowrap> " +\r
+ "<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> " +\r
+ "<td> </td></tr> " +\r
+ "<tr><td bgcolor=\"#3366cc\"><font face=arial,sans-serif color=\"#ffffff\"><b>Error</b></td></tr> " +\r
+ "<tr><td> </td></tr></table> " + "<blockquote> " + "<H1>Not Found</H1> " +\r
+ "The requested URL <code>/404</code> was not found on this server." + " " + "<p> " +\r
+ "</blockquote> " +\r
+ "<table width=100% cellpadding=0 cellspacing=0><tr><td bgcolor=\"#3366cc\"><img alt=\"\" width=1 height=4></td></tr></table> " +\r
+ "</body></html> ";\r
+ input = new ByteArrayInputStream(str.getBytes());\r
+ result = mSource._findAlternateToolsXml(input);\r
+ assertNull(result);\r
+\r
+ // Support some random XML document, totally unrelated to our sdk-repository schema\r
+ str = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" +\r
+ "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"" +\r
+ " package=\"some.cool.app\" android:versionName=\"1.6.04\" android:versionCode=\"1604\">" +\r
+ " <application android:label=\"@string/app_name\" android:icon=\"@drawable/icon\"/>" +\r
+ "</manifest>";\r
+ input = new ByteArrayInputStream(str.getBytes());\r
+ result = mSource._findAlternateToolsXml(input);\r
+ assertNull(result);\r
+ }\r
+\r
+ /**\r
+ * Validate we can load a new schema version 3 using the "alternate future tool" mode.\r
+ */\r
+ public void testFindAlternateToolsXml_3() throws Exception {\r
+ InputStream xmlStream = getTestResource(\r
+ "/com/android/sdklib/testdata/repository_sample_3.xml");\r
+\r
+ Document result = mSource._findAlternateToolsXml(xmlStream);\r
+ assertNotNull(result);\r
+ MockMonitor mon = new MockMonitor();\r
+ assertTrue(mSource._parsePackages(result, SdkRepoConstants.NS_URI, mon));\r
+\r
+ assertEquals("Found Android SDK Tools, revision 1\n" +\r
+ "Found Android SDK Tools, revision 42\n" +\r
+ "Found Android SDK Platform-tools, revision 3\n",\r
+ mon.getCapturedDescriptions());\r
+ assertEquals("", mon.getCapturedResults());\r
+\r
+ // check the packages we found... we expected to find 2 tool packages and 1\r
+ // platform-tools package, with at least 1 archive each.\r
+ Package[] pkgs = mSource.getPackages();\r
+ assertEquals(3, pkgs.length);\r
+ for (Package p : pkgs) {\r
+ assertTrue((p instanceof ToolPackage) || (p instanceof PlatformToolPackage));\r
+ assertTrue(p.getArchives().length >= 1);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Validate we can still load an old repository in schema version 1\r
+ */\r
+ public void testLoadOldXml_1() throws Exception {\r
+ InputStream xmlStream = getTestResource(\r
+ "/com/android/sdklib/testdata/repository_sample_1.xml");\r
+\r
+ // guess the version from the XML document\r
+ int version = mSource._getXmlSchemaVersion(xmlStream);\r
+ assertEquals(1, version);\r
+\r
+ Boolean[] validatorFound = new Boolean[] { Boolean.FALSE };\r
+ String[] validationError = new String[] { null };\r
+ String url = "not-a-valid-url://" + SdkRepoConstants.URL_DEFAULT_XML_FILE;\r
+\r
+ String uri = mSource._validateXml(xmlStream, url, version, validationError, validatorFound);\r
+ assertEquals(Boolean.TRUE, validatorFound[0]);\r
+ assertEquals(null, validationError[0]);\r
+ assertEquals(SdkRepoConstants.getSchemaUri(1), uri);\r
+\r
+ // Validation was successful, load the document\r
+ MockMonitor monitor = new MockMonitor();\r
+ Document doc = mSource._getDocument(xmlStream, monitor);\r
+ assertNotNull(doc);\r
+\r
+ // Get the packages\r
+ assertTrue(mSource._parsePackages(doc, uri, monitor));\r
+\r
+ assertEquals("Found SDK Platform Android 1.0, API 1, revision 3\n" +\r
+ "Found Documentation for Android SDK, API 1, revision 1\n" +\r
+ "Found My First add-on by John Doe, Android API 1, revision 1\n" +\r
+ "Found SDK Platform Android 1.1, API 2, revision 12\n" +\r
+ "Found My Second add-on by John Deer, Android API 2, revision 42\n" +\r
+ "Found SDK Platform Android Pastry Preview, revision 3\n" +\r
+ "Found Android SDK Tools, revision 1\n" +\r
+ "Found Documentation for Android SDK, API 2, revision 42\n" +\r
+ "Found Android SDK Tools, revision 42\n" +\r
+ "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +\r
+ "Found Usb Driver package, revision 43\n",\r
+ monitor.getCapturedDescriptions());\r
+ assertEquals("", monitor.getCapturedResults());\r
+\r
+ // check the packages we found... we expected to find 11 packages with each at least\r
+ // one archive.\r
+ Package[] pkgs = mSource.getPackages();\r
+ assertEquals(11, pkgs.length);\r
+ for (Package p : pkgs) {\r
+ assertTrue(p.getArchives().length >= 1);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Validate we can still load an old repository in schema version 2\r
+ */\r
+ public void testLoadOldXml_2() throws Exception {\r
+ InputStream xmlStream = getTestResource(\r
+ "/com/android/sdklib/testdata/repository_sample_2.xml");\r
+\r
+ // guess the version from the XML document\r
+ int version = mSource._getXmlSchemaVersion(xmlStream);\r
+ assertEquals(2, version);\r
+\r
+ Boolean[] validatorFound = new Boolean[] { Boolean.FALSE };\r
+ String[] validationError = new String[] { null };\r
+ String url = "not-a-valid-url://" + SdkRepoConstants.URL_DEFAULT_XML_FILE;\r
+\r
+ String uri = mSource._validateXml(xmlStream, url, version, validationError, validatorFound);\r
+ assertEquals(Boolean.TRUE, validatorFound[0]);\r
+ assertEquals(null, validationError[0]);\r
+ assertEquals(SdkRepoConstants.getSchemaUri(2), uri);\r
+\r
+ // Validation was successful, load the document\r
+ MockMonitor monitor = new MockMonitor();\r
+ Document doc = mSource._getDocument(xmlStream, monitor);\r
+ assertNotNull(doc);\r
+\r
+ // Get the packages\r
+ assertTrue(mSource._parsePackages(doc, uri, monitor));\r
+\r
+ assertEquals("Found SDK Platform Android 1.0, API 1, revision 3\n" +\r
+ "Found Documentation for Android SDK, API 1, revision 1\n" +\r
+ "Found My First add-on by John Doe, Android API 1, revision 1\n" +\r
+ "Found SDK Platform Android 1.1, API 2, revision 12\n" +\r
+ "Found My Second add-on by John Deer, Android API 2, revision 42\n" +\r
+ "Found SDK Platform Android Pastry Preview, revision 3\n" +\r
+ "Found Android SDK Tools, revision 1\n" +\r
+ "Found Documentation for Android SDK, API 2, revision 42\n" +\r
+ "Found Android SDK Tools, revision 42\n" +\r
+ "Found This add-on has no libraries by Joe Bar, Android API 4, revision 3\n" +\r
+ "Found Usb Driver package, revision 43 (Obsolete)\n" +\r
+ "Found Extra Api Dep package, revision 2 (Obsolete)\n" +\r
+ "Found Samples for SDK API 14, revision 24 (Obsolete)\n",\r
+ monitor.getCapturedDescriptions());\r
+ assertEquals("", monitor.getCapturedResults());\r
+\r
+ // check the packages we found... we expected to find 13 packages with each at least\r
+ // one archive.\r
+ Package[] pkgs = mSource.getPackages();\r
+ assertEquals(13, pkgs.length);\r
+ for (Package p : pkgs) {\r
+ assertTrue(p.getArchives().length >= 1);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns an SdkLib file resource as a {@link ByteArrayInputStream},\r
+ * which has the advantage that we can use {@link InputStream#reset()} on it\r
+ * at any time to read it multiple times.\r
+ * <p/>\r
+ * The default for getResourceAsStream() is to return a {@link FileInputStream} that\r
+ * does not support reset(), yet we need it in the tested code.\r
+ *\r
+ * @throws IOException if some I/O read fails\r
+ */\r
+ private ByteArrayInputStream getTestResource(String filename) throws IOException {\r
+ InputStream xmlStream = this.getClass().getResourceAsStream(filename);\r
+\r
+ try {\r
+ byte[] data = new byte[8192];\r
+ int offset = 0;\r
+ int n;\r
+\r
+ while ((n = xmlStream.read(data, offset, data.length - offset)) != -1) {\r
+ offset += n;\r
+\r
+ if (offset == data.length) {\r
+ byte[] newData = new byte[offset + 8192];\r
+ System.arraycopy(data, 0, newData, 0, offset);\r
+ data = newData;\r
+ }\r
+ }\r
+\r
+ return new ByteArrayInputStream(data, 0, offset);\r
+ } finally {\r
+ if (xmlStream != null) {\r
+ xmlStream.close();\r
+ }\r
+ }\r
+ }\r
+}\r
\r
/** Helper method that returns a validator for our XSD */\r
private Validator getValidator(int version, CaptureErrorHandler handler) throws SAXException {\r
- InputStream xsdStream = SdkRepository.getXsdStream(version);\r
+ InputStream xsdStream = SdkRepoConstants.getXsdStream(version);\r
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);\r
Schema schema = factory.newSchema(new StreamSource(xsdStream));\r
Validator validator = schema.newValidator();\r
Source source = new StreamSource(new StringReader(document));\r
\r
CaptureErrorHandler handler = new CaptureErrorHandler();\r
- Validator validator = getValidator(SdkRepository.NS_LATEST_VERSION, handler);\r
+ Validator validator = getValidator(SdkRepoConstants.NS_LATEST_VERSION, handler);\r
\r
try {\r
validator.validate(source);\r
\r
private static String OPEN_TAG =\r
"<r:sdk-repository xmlns:r=\"http://schemas.android.com/sdk/android/repository/" +\r
- Integer.toString(SdkRepository.NS_LATEST_VERSION) +\r
+ Integer.toString(SdkRepoConstants.NS_LATEST_VERSION) +\r
"\">";\r
\r
private static String CLOSE_TAG = "</r:sdk-repository>";\r
Source source = new StreamSource(new StringReader(document));\r
\r
CaptureErrorHandler handler = new CaptureErrorHandler();\r
- Validator validator = getValidator(SdkRepository.NS_LATEST_VERSION, handler);\r
+ Validator validator = getValidator(SdkRepoConstants.NS_LATEST_VERSION, handler);\r
validator.validate(source);\r
handler.verify();\r
}\r
Source source = new StreamSource(new StringReader(document));\r
\r
// don't capture the validator errors, we want it to fail and catch the exception\r
- Validator validator = getValidator(SdkRepository.NS_LATEST_VERSION, null);\r
+ Validator validator = getValidator(SdkRepoConstants.NS_LATEST_VERSION, null);\r
try {\r
validator.validate(source);\r
} catch (SAXParseException e) {\r
Source source = new StreamSource(new StringReader(document));\r
\r
// don't capture the validator errors, we want it to fail and catch the exception\r
- Validator validator = getValidator(SdkRepository.NS_LATEST_VERSION, null);\r
+ Validator validator = getValidator(SdkRepoConstants.NS_LATEST_VERSION, null);\r
try {\r
validator.validate(source);\r
} catch (SAXParseException e) {\r
Source source = new StreamSource(new StringReader(document));\r
\r
// don't capture the validator errors, we want it to fail and catch the exception\r
- Validator validator = getValidator(SdkRepository.NS_LATEST_VERSION, null);\r
+ Validator validator = getValidator(SdkRepoConstants.NS_LATEST_VERSION, null);\r
try {\r
validator.validate(source);\r
} catch (SAXParseException e) {\r
Source source = new StreamSource(new StringReader(document));\r
\r
// don't capture the validator errors, we want it to fail and catch the exception\r
- Validator validator = getValidator(SdkRepository.NS_LATEST_VERSION, null);\r
+ Validator validator = getValidator(SdkRepoConstants.NS_LATEST_VERSION, null);\r
try {\r
validator.validate(source);\r
} catch (SAXParseException e) {\r
Source source = new StreamSource(new StringReader(document));\r
\r
// don't capture the validator errors, we want it to fail and catch the exception\r
- Validator validator = getValidator(SdkRepository.NS_LATEST_VERSION, null);\r
+ Validator validator = getValidator(SdkRepoConstants.NS_LATEST_VERSION, null);\r
try {\r
validator.validate(source);\r
} catch (SAXParseException e) {\r
--- /dev/null
+<?xml version="1.0"?>
+<!--
+ * Copyright (C) 2010 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-addon
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:sdk="http://schemas.android.com/sdk/android/addon/1">
+
+ <!-- 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: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: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: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:obsolete/>
+ </sdk:extra>
+
+ <sdk:extra>
+ <sdk:path>extra_api_dep</sdk:path>
+ <sdk:uses-license ref="license2" />
+ <sdk:revision>2</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/extra_mega_duff.zip</sdk:url>
+ </sdk:archive>
+ </sdk:archives>
+ <sdk:description>Some extra package that has a min-api-level of 42</sdk:description>
+ <sdk:desc-url>http://www.example.com/extra.html</sdk:desc-url>
+ <sdk:min-tools-rev>3</sdk:min-tools-rev>
+ <sdk:min-api-level>42</sdk:min-api-level>
+ <sdk:obsolete></sdk:obsolete>
+ </sdk:extra>
+
+</sdk:sdk-addon>
</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: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:archives>
</sdk:platform-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" />
\r
import com.android.sdklib.internal.repository.IDescription;\r
import com.android.sdklib.internal.repository.Package;\r
-import com.android.sdklib.internal.repository.RepoSource;\r
+import com.android.sdklib.internal.repository.SdkSource;\r
import com.android.sdkuilib.internal.repository.icons.ImageFactory;\r
\r
import org.eclipse.jface.viewers.IContentProvider;\r
/**\r
* Called to collect the root elements for the given input.\r
* The input here is a {@link LocalSdkAdapter} object, this returns an array\r
- * of {@link RepoSource}.\r
+ * of {@link SdkSource}.\r
*/\r
public Object[] getElements(Object inputElement) {\r
if (inputElement == LocalSdkAdapter.this) {\r
import com.android.sdklib.internal.repository.Archive;\r
import com.android.sdklib.internal.repository.IDescription;\r
import com.android.sdklib.internal.repository.Package;\r
-import com.android.sdklib.internal.repository.RepoSource;\r
+import com.android.sdklib.internal.repository.SdkAddonSource;\r
+import com.android.sdklib.internal.repository.SdkSource;\r
import com.android.sdkuilib.repository.UpdaterWindow.ISdkListener;\r
\r
import org.eclipse.jface.dialogs.IInputValidator;\r
(ITreeContentProvider) mTreeViewerSources.getContentProvider();\r
\r
// When selecting, we want to only select compatible archives.\r
- if (elem instanceof RepoSource) {\r
+ if (elem instanceof SdkSource) {\r
mTreeViewerSources.setExpandedState(elem, true);\r
for (Object pkg : provider.getChildren(elem)) {\r
mTreeViewerSources.setChecked(pkg, true);\r
\r
private void onAddSiteSelected() {\r
\r
- final RepoSource[] knowSources = mUpdaterData.getSources().getSources();\r
+ final SdkSource[] knowSources = mUpdaterData.getSources().getSources();\r
String title = "Add Add-on Site URL";\r
\r
String msg =\r
// Reject URLs that are already in the source list.\r
// URLs are generally case-insensitive (except for file:// where it all depends\r
// on the current OS so we'll ignore this case.)\r
- for (RepoSource s : knowSources) {\r
+ for (SdkSource s : knowSources) {\r
if (newText.equalsIgnoreCase(s.getUrl())) {\r
return "Error : This site is already listed.";\r
}\r
\r
if (dlg.open() == Window.OK) {\r
String url = dlg.getValue();\r
- mUpdaterData.getSources().add(new RepoSource(url, true /*userSource*/));\r
+ mUpdaterData.getSources().add(new SdkAddonSource(url, true /*userSource*/));\r
onRefreshSelected();\r
}\r
}\r
ISelection sel = mTreeViewerSources.getSelection();\r
if (mUpdaterData != null && sel instanceof ITreeSelection) {\r
for (Object c : ((ITreeSelection) sel).toList()) {\r
- if (c instanceof RepoSource && ((RepoSource) c).isUserSource()) {\r
- RepoSource source = (RepoSource) c;\r
+ if (c instanceof SdkSource && ((SdkSource) c).isUserSource()) {\r
+ SdkSource source = (SdkSource) c;\r
\r
String title = "Delete Add-on Site?";\r
\r
ISelection sel = mTreeViewerSources.getSelection();\r
if (sel instanceof ITreeSelection) {\r
for (Object c : ((ITreeSelection) sel).toList()) {\r
- if (c instanceof RepoSource &&\r
- ((RepoSource) c).isUserSource()) {\r
+ if (c instanceof SdkSource &&\r
+ ((SdkSource) c).isUserSource()) {\r
hasSelectedUserSource = true;\r
break;\r
}\r
import com.android.sdklib.internal.repository.ITask;\r
import com.android.sdklib.internal.repository.ITaskMonitor;\r
import com.android.sdklib.internal.repository.Package;\r
-import com.android.sdklib.internal.repository.RepoSource;\r
+import com.android.sdklib.internal.repository.SdkSource;\r
import com.android.sdklib.internal.repository.Package.UpdateInfo;\r
import com.android.sdkuilib.internal.repository.icons.ImageFactory;\r
\r
*/\r
public static class RepoSourceError implements IDescription {\r
\r
- private final RepoSource mSource;\r
+ private final SdkSource mSource;\r
\r
- public RepoSourceError(RepoSource source) {\r
+ public RepoSourceError(SdkSource source) {\r
mSource = source;\r
}\r
\r
*/\r
public static class RepoSourceEmpty implements IDescription {\r
\r
- private final RepoSource mSource;\r
+ private final SdkSource mSource;\r
private final boolean mEmptyBecauseOfUpdateOnly;\r
\r
- public RepoSourceEmpty(RepoSource source, boolean emptyBecauseOfUpdateOnly) {\r
+ public RepoSourceEmpty(SdkSource source, boolean emptyBecauseOfUpdateOnly) {\r
mSource = source;\r
mEmptyBecauseOfUpdateOnly = emptyBecauseOfUpdateOnly;\r
}\r
/**\r
* Called to collect the root elements for the given input.\r
* The input here is a {@link RepoSourcesAdapter} object, this returns an array\r
- * of {@link RepoSource}.\r
+ * of {@link SdkSource}.\r
*/\r
public Object[] getElements(Object inputElement) {\r
return getChildren(inputElement);\r
* Get the children of the given parent. This is requested on-demand as\r
* nodes are expanded.\r
*\r
- * For a {@link RepoSourcesAdapter} object, returns an array of {@link RepoSource}s.\r
- * For a {@link RepoSource}, returns an array of {@link Package}s.\r
+ * For a {@link RepoSourcesAdapter} object, returns an array of {@link SdkSource}s.\r
+ * For a {@link SdkSource}, returns an array of {@link Package}s.\r
* For a {@link Package}, returns an array of {@link Archive}s.\r
*/\r
public Object[] getChildren(Object parentElement) {\r
if (parentElement == RepoSourcesAdapter.this) {\r
return mUpdaterData.getSources().getSources();\r
\r
- } else if (parentElement instanceof RepoSource) {\r
- return getRepoSourceChildren((RepoSource) parentElement);\r
+ } else if (parentElement instanceof SdkSource) {\r
+ return getRepoSourceChildren((SdkSource) parentElement);\r
\r
} else if (parentElement instanceof Package) {\r
return getPackageChildren((Package) parentElement);\r
* only update packages. If the list is empty, returns a specific empty node. If there's\r
* an error, returns a specific error node.\r
*/\r
- private Object[] getRepoSourceChildren(final RepoSource source) {\r
+ private Object[] getRepoSourceChildren(final SdkSource source) {\r
Package[] packages = source.getPackages();\r
\r
if (packages == null && source.getFetchError() == null) {\r
\r
/**\r
* Returns the parent of a given element.\r
- * The input {@link RepoSourcesAdapter} is the parent of all {@link RepoSource} elements.\r
+ * The input {@link RepoSourcesAdapter} is the parent of all {@link SdkSource} elements.\r
*/\r
public Object getParent(Object element) {\r
\r
- if (element instanceof RepoSource) {\r
+ if (element instanceof SdkSource) {\r
return RepoSourcesAdapter.this;\r
\r
} else if (element instanceof Package) {\r
/**\r
* Returns true if a given element has children, which is used to display a\r
* "+/expand" box next to the tree node.\r
- * All {@link RepoSource} and {@link Package} are expandable, whether they actually\r
+ * All {@link SdkSource} and {@link Package} are expandable, whether they actually\r
* have any children or not.\r
*/\r
public boolean hasChildren(Object element) {\r
- return element instanceof RepoSource || element instanceof Package;\r
+ return element instanceof SdkSource || element instanceof Package;\r
}\r
}\r
\r
import com.android.sdklib.internal.repository.ITask;
import com.android.sdklib.internal.repository.ITaskFactory;
import com.android.sdklib.internal.repository.ITaskMonitor;
-import com.android.sdklib.repository.SdkRepository;
+import com.android.sdklib.repository.SdkRepoConstants;
import java.util.ArrayList;
/**
* Performs the actual update.
*
- * @param pkgFilter A list of {@link SdkRepository#NODES} to limit the type of packages
+ * @param pkgFilter A list of {@link SdkRepoConstants#NODES} to limit the type of packages
* we can update. A null or empty list means to update everything possible.
* @param includeObsoletes True to also list and install obsolete packages.
* @param dryMode True to check what would be updated/installed but do not actually
import com.android.sdklib.internal.repository.ITaskMonitor;\r
import com.android.sdklib.internal.repository.LocalSdkParser;\r
import com.android.sdklib.internal.repository.Package;\r
-import com.android.sdklib.internal.repository.RepoSource;\r
-import com.android.sdklib.internal.repository.RepoSources;\r
+import com.android.sdklib.internal.repository.SdkAddonSource;\r
+import com.android.sdklib.internal.repository.SdkRepoSource;\r
+import com.android.sdklib.internal.repository.SdkSource;\r
+import com.android.sdklib.internal.repository.SdkSources;\r
import com.android.sdklib.internal.repository.ToolPackage;\r
-import com.android.sdklib.repository.SdkRepository;\r
+import com.android.sdklib.repository.SdkAddonConstants;\r
+import com.android.sdklib.repository.SdkRepoConstants;\r
import com.android.sdkuilib.internal.repository.icons.ImageFactory;\r
import com.android.sdkuilib.repository.UpdaterWindow.ISdkListener;\r
\r
private AvdManager mAvdManager;\r
\r
private final LocalSdkParser mLocalSdkParser = new LocalSdkParser();\r
- private final RepoSources mSources = new RepoSources();\r
+ private final SdkSources mSources = new SdkSources();\r
\r
private final LocalSdkAdapter mLocalSdkAdapter = new LocalSdkAdapter(this);\r
private final RepoSourcesAdapter mSourcesAdapter = new RepoSourcesAdapter(this);\r
return mUserCanChangeSdkRoot;\r
}\r
\r
- public RepoSources getSources() {\r
+ public SdkSources getSources() {\r
return mSources;\r
}\r
\r
* - and finally the extra user repo URLs from the environment.\r
*/\r
public void setupDefaultSources() {\r
- RepoSources sources = getSources();\r
- sources.add(new RepoSource(SdkRepository.URL_GOOGLE_SDK_REPO_SITE, false /*userSource*/));\r
+ SdkSources sources = getSources();\r
+ sources.add(new SdkRepoSource(SdkRepoConstants.URL_GOOGLE_SDK_SITE));\r
+ sources.add(new SdkAddonSource(SdkAddonConstants.URL_GOOGLE_SDK_SITE, false /*userSource*/));\r
\r
// SDK_UPDATER_URLS is a semicolon-separated list of URLs that can be used to\r
// seed the SDK Updater list for full repositories.\r
String[] urls = str.split(";");\r
for (String url : urls) {\r
if (url != null && url.length() > 0) {\r
- RepoSource s = new RepoSource(url, false /*userSource*/);\r
+ SdkSource s = new SdkRepoSource(url);\r
+ if (!sources.hasSource(s)) {\r
+ sources.add(s);\r
+ }\r
+ s = new SdkAddonSource(url, false /*userSource*/);\r
if (!sources.hasSource(s)) {\r
sources.add(s);\r
}\r
String[] urls = str.split(";");\r
for (String url : urls) {\r
if (url != null && url.length() > 0) {\r
- RepoSource s = new RepoSource(url, true /*userSource*/);\r
+ SdkSource s = new SdkAddonSource(url, true /*userSource*/);\r
if (!sources.hasSource(s)) {\r
sources.add(s);\r
}\r
* This version is intended to run without a GUI and\r
* only outputs to the current {@link ISdkLog}.\r
*\r
- * @param pkgFilter A list of {@link SdkRepository#NODES} to limit the type of packages\r
+ * @param pkgFilter A list of {@link SdkRepoConstants#NODES} to limit the type of packages\r
* we can update. A null or empty list means to update everything possible.\r
* @param includeObsoletes True to also list and install obsolete packages.\r
* @param dryMode True to check what would be updated/installed but do not actually\r
// Automatically find the classes matching the node names\r
ClassLoader classLoader = getClass().getClassLoader();\r
String basePackage = Package.class.getPackage().getName();\r
- for (String node : SdkRepository.NODES) {\r
+ for (String node : SdkRepoConstants.NODES) {\r
// Capitalize the name\r
String name = node.substring(0, 1).toUpperCase() + node.substring(1);\r
\r
}\r
}\r
\r
- if (SdkRepository.NODES.length != pkgMap.size()) {\r
+ if (SdkRepoConstants.NODES.length != pkgMap.size()) {\r
// Sanity check in case we forget to update this node array.\r
// We don't cancel the operation though.\r
mSdkLog.printf(\r
\r
mTaskFactory.start("Refresh Sources", new ITask() {\r
public void run(ITaskMonitor monitor) {\r
- RepoSource[] sources = mSources.getSources();\r
+ SdkSource[] sources = mSources.getSources();\r
monitor.setProgressMax(sources.length);\r
- for (RepoSource source : sources) {\r
+ for (SdkSource source : sources) {\r
if (forceFetching ||\r
source.getPackages() != null ||\r
source.getFetchError() != null) {\r
import com.android.sdklib.internal.repository.Package;\r
import com.android.sdklib.internal.repository.PlatformPackage;\r
import com.android.sdklib.internal.repository.PlatformToolPackage;\r
-import com.android.sdklib.internal.repository.RepoSource;\r
-import com.android.sdklib.internal.repository.RepoSources;\r
+import com.android.sdklib.internal.repository.SdkSource;\r
+import com.android.sdklib.internal.repository.SdkSources;\r
import com.android.sdklib.internal.repository.SamplePackage;\r
import com.android.sdklib.internal.repository.ToolPackage;\r
import com.android.sdklib.internal.repository.Package.UpdateInfo;\r
*/\r
public ArrayList<ArchiveInfo> computeUpdates(\r
Collection<Archive> selectedArchives,\r
- RepoSources sources,\r
+ SdkSources sources,\r
Package[] localPkgs,\r
boolean includeObsoletes) {\r
\r
ArrayList<ArchiveInfo> archives = new ArrayList<ArchiveInfo>();\r
ArrayList<Package> remotePkgs = new ArrayList<Package>();\r
- RepoSource[] remoteSources = sources.getSources();\r
+ SdkSource[] remoteSources = sources.getSources();\r
\r
// Create ArchiveInfos out of local (installed) packages.\r
ArchiveInfo[] localArchives = createLocalArchives(localPkgs);\r
*/\r
public void addNewPlatforms(\r
ArrayList<ArchiveInfo> archives,\r
- RepoSources sources,\r
+ SdkSources sources,\r
Package[] localPkgs,\r
boolean includeObsoletes) {\r
\r
}\r
}\r
\r
- RepoSource[] remoteSources = sources.getSources();\r
+ SdkSource[] remoteSources = sources.getSources();\r
ArrayList<Package> remotePkgs = new ArrayList<Package>();\r
fetchRemotePackages(remotePkgs, remoteSources);\r
\r
private Collection<Archive> findUpdates(\r
ArchiveInfo[] localArchives,\r
ArrayList<Package> remotePkgs,\r
- RepoSource[] remoteSources,\r
+ SdkSource[] remoteSources,\r
boolean includeObsoletes) {\r
ArrayList<Archive> updates = new ArrayList<Archive>();\r
\r
ArrayList<ArchiveInfo> outArchives,\r
Collection<Archive> selectedArchives,\r
ArrayList<Package> remotePkgs,\r
- RepoSource[] remoteSources,\r
+ SdkSource[] remoteSources,\r
ArchiveInfo[] localArchives,\r
boolean automated) {\r
Package p = archive.getParentPackage();\r
ArrayList<ArchiveInfo> outArchives,\r
Collection<Archive> selectedArchives,\r
ArrayList<Package> remotePkgs,\r
- RepoSource[] remoteSources,\r
+ SdkSource[] remoteSources,\r
ArchiveInfo[] localArchives) {\r
\r
// Current dependencies can be:\r
ArrayList<ArchiveInfo> outArchives,\r
Collection<Archive> selectedArchives,\r
ArrayList<Package> remotePkgs,\r
- RepoSource[] remoteSources,\r
+ SdkSource[] remoteSources,\r
ArchiveInfo[] localArchives) {\r
// This is the requirement to match.\r
int rev = pkg.getMinToolsRevision();\r
ArrayList<ArchiveInfo> outArchives,\r
Collection<Archive> selectedArchives,\r
ArrayList<Package> remotePkgs,\r
- RepoSource[] remoteSources,\r
+ SdkSource[] remoteSources,\r
ArchiveInfo[] localArchives) {\r
// This is the requirement to match.\r
int rev = pkg.getMinPlatformToolsRevision();\r
ArrayList<ArchiveInfo> outArchives,\r
Collection<Archive> selectedArchives,\r
ArrayList<Package> remotePkgs,\r
- RepoSource[] remoteSources,\r
+ SdkSource[] remoteSources,\r
ArchiveInfo[] localArchives) {\r
// This is the requirement to match.\r
AndroidVersion v = pkg.getVersion();\r
ArrayList<ArchiveInfo> outArchives,\r
Collection<Archive> selectedArchives,\r
ArrayList<Package> remotePkgs,\r
- RepoSource[] remoteSources,\r
+ SdkSource[] remoteSources,\r
ArchiveInfo[] localArchives) {\r
\r
int api = pkg.getMinApiLevel();\r
}\r
\r
/** Fetch all remote packages only if really needed. */\r
- protected void fetchRemotePackages(ArrayList<Package> remotePkgs, RepoSource[] remoteSources) {\r
+ protected void fetchRemotePackages(ArrayList<Package> remotePkgs, SdkSource[] remoteSources) {\r
if (remotePkgs.size() > 0) {\r
return;\r
}\r
\r
- for (RepoSource remoteSrc : remoteSources) {\r
+ for (SdkSource remoteSrc : remoteSources) {\r
Package[] pkgs = remoteSrc.getPackages();\r
if (pkgs != null) {\r
nextPackage: for (Package pkg : pkgs) {\r
\r
import com.android.sdklib.internal.repository.Archive;\r
import com.android.sdklib.internal.repository.Package;\r
-import com.android.sdklib.internal.repository.RepoSource;\r
+import com.android.sdklib.internal.repository.SdkSource;\r
import com.android.sdkuilib.internal.repository.RepoSourcesAdapter;\r
\r
import org.eclipse.swt.SWTException;\r
/**\r
* Loads and returns the appropriate image for a given package, archive or source object.\r
*\r
- * @param object A {@link RepoSource} or {@link Package} or {@link Archive}.\r
+ * @param object A {@link SdkSource} or {@link Package} or {@link Archive}.\r
* @return A new or existing {@link Image}. The caller must NOT dispose the image (the\r
* image will disposed by {@link #dispose()}). The returned image can be null if the\r
* expected file is missing.\r
return getImageByName(name);\r
}\r
\r
- if (object instanceof RepoSource) {\r
+ if (object instanceof SdkSource) {\r
return getImageByName("source_icon16.png"); //$NON-NLS-1$\r
\r
} else if (object instanceof RepoSourcesAdapter.RepoSourceError) {\r
import com.android.sdklib.internal.repository.MockPlatformToolPackage;\r
import com.android.sdklib.internal.repository.MockToolPackage;\r
import com.android.sdklib.internal.repository.Package;\r
-import com.android.sdklib.internal.repository.RepoSource;\r
+import com.android.sdklib.internal.repository.SdkSource;\r
\r
import java.util.ArrayList;\r
import java.util.Arrays;\r
\r
@Override\r
protected void fetchRemotePackages(ArrayList<Package> remotePkgs,\r
- RepoSource[] remoteSources) {\r
+ SdkSource[] remoteSources) {\r
// Ignore remoteSources and instead uses the remotePackages list given to the\r
// constructor.\r
if (mRemotePackages != null) {\r
Package[] localPkgs = { p1, a1 };\r
ArchiveInfo[] locals = mul.createLocalArchives(localPkgs);\r
\r
- RepoSource[] sources = null;\r
+ SdkSource[] sources = null;\r
\r
// a2 now depends on a "fake" archive info with no newArchive that wraps the missing\r
// underlying platform.\r
Package[] localPkgs = { t1, pt1 };\r
ArchiveInfo[] locals = mul.createLocalArchives(localPkgs);\r
\r
- RepoSource[] sources = null;\r
+ SdkSource[] sources = null;\r
\r
// p2 now depends on a "fake" archive info with no newArchive that wraps the missing\r
// underlying tool\r
Package[] localPkgs = { t1 };\r
ArchiveInfo[] locals = mul.createLocalArchives(localPkgs);\r
\r
- RepoSource[] sources = null;\r
+ SdkSource[] sources = null;\r
\r
// p2 now depends on a "fake" archive info with no newArchive that wraps the missing\r
// underlying tool\r