Merge change 5552 into donut
* changes: SDK Updater: Store local source properties when installing.
This commit is contained in:
@@ -29,12 +29,17 @@ import org.w3c.dom.Node;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Represents an add-on XML node in an SDK repository.
|
||||
*/
|
||||
public class AddonPackage extends Package {
|
||||
|
||||
private static final String PROP_API_LEVEL = "Addon.ApiLevel"; //$NON-NLS-1$
|
||||
private static final String PROP_NAME = "Addon.Name"; //$NON-NLS-1$
|
||||
private static final String PROP_VENDOR = "Addon.Vendor"; //$NON-NLS-1$
|
||||
|
||||
private final String mVendor;
|
||||
private final String mName;
|
||||
private final int mApiLevel;
|
||||
@@ -80,8 +85,9 @@ public class AddonPackage extends Package {
|
||||
* This is used to list local SDK folders in which case there is one archive which
|
||||
* URL is the actual target location.
|
||||
*/
|
||||
AddonPackage(IAndroidTarget target) {
|
||||
AddonPackage(IAndroidTarget target, Properties props) {
|
||||
super( null, //source
|
||||
props, //properties
|
||||
0, //revision
|
||||
null, //license
|
||||
target.getDescription(), //description
|
||||
@@ -106,6 +112,19 @@ public class AddonPackage extends Package {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the properties of the current packages in the given {@link Properties} object.
|
||||
* These properties will later be give the constructor that takes a {@link Properties} object.
|
||||
*/
|
||||
@Override
|
||||
void saveProperties(Properties props) {
|
||||
super.saveProperties(props);
|
||||
|
||||
props.setProperty(PROP_API_LEVEL, Integer.toString(mApiLevel));
|
||||
props.setProperty(PROP_NAME, mName);
|
||||
props.setProperty(PROP_VENDOR, mVendor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a <libs> element.
|
||||
*/
|
||||
|
||||
@@ -26,6 +26,7 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Properties;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
@@ -43,6 +44,8 @@ import java.util.zip.ZipInputStream;
|
||||
public class Archive implements IDescription {
|
||||
|
||||
public static final int NUM_MONITOR_INC = 100;
|
||||
private static final String PROP_OS = "Archive.Os"; //$NON-NLS-1$
|
||||
private static final String PROP_ARCH = "Archive.Arch"; //$NON-NLS-1$
|
||||
|
||||
/** The checksum type. */
|
||||
public enum ChecksumType {
|
||||
@@ -175,11 +178,14 @@ public class Archive implements IDescription {
|
||||
|
||||
/**
|
||||
* Creates a new local archive.
|
||||
* Uses the properties from props first, if possible. Props can be null.
|
||||
*/
|
||||
Archive(Package pkg, Os os, Arch arch, String localOsPath) {
|
||||
Archive(Package pkg, Properties props, Os os, Arch arch, String localOsPath) {
|
||||
mPackage = pkg;
|
||||
mOs = os;
|
||||
mArch = arch;
|
||||
|
||||
mOs = props == null ? os : Os.valueOf( props.getProperty(PROP_OS, os.toString()));
|
||||
mArch = props == null ? arch : Arch.valueOf(props.getProperty(PROP_ARCH, arch.toString()));
|
||||
|
||||
mUrl = null;
|
||||
mLocalOsPath = localOsPath;
|
||||
mSize = 0;
|
||||
@@ -187,6 +193,15 @@ public class Archive implements IDescription {
|
||||
mIsLocal = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the properties of the current archive in the give {@link Properties} object.
|
||||
* These properties will later be give the constructor that takes a {@link Properties} object.
|
||||
*/
|
||||
void saveProperties(Properties props) {
|
||||
props.setProperty(PROP_OS, mOs.toString());
|
||||
props.setProperty(PROP_ARCH, mArch.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this is a locally installed archive.
|
||||
* Returns false if this is a remote archive that needs to be downloaded.
|
||||
@@ -623,6 +638,10 @@ public class Archive implements IDescription {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!generateSourceProperties(unzipDestFolder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute destination directory
|
||||
destFolder = getParentPackage().getInstallFolder(
|
||||
osSdkRoot, zipRootFolder[0], sdkManager);
|
||||
@@ -848,5 +867,40 @@ public class Archive implements IDescription {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a source.properties in the destination folder that contains all the infos
|
||||
* relevant to this archive, this package and the source so that we can reload them
|
||||
* locally later.
|
||||
*/
|
||||
private boolean generateSourceProperties(File unzipDestFolder) {
|
||||
Properties props = new Properties();
|
||||
|
||||
saveProperties(props);
|
||||
mPackage.saveProperties(props);
|
||||
|
||||
FileOutputStream fos = null;
|
||||
try {
|
||||
File f = new File(unzipDestFolder, LocalSdkParser.SOURCE_PROPERTIES);
|
||||
|
||||
fos = new FileOutputStream(f);
|
||||
|
||||
props.store( fos, "## Android Tool: Source of this archive."); //$NON-NLS-1$
|
||||
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (fos != null) {
|
||||
try {
|
||||
fos.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -26,12 +26,15 @@ import org.w3c.dom.Node;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Represents a doc XML node in an SDK repository.
|
||||
*/
|
||||
public class DocPackage extends Package {
|
||||
|
||||
private static final String PROP_API_LEVEL = "Doc.ApiLevel"; //$NON-NLS-1$
|
||||
|
||||
private final int mApiLevel;
|
||||
|
||||
/**
|
||||
@@ -50,6 +53,7 @@ public class DocPackage extends Package {
|
||||
* one archive which URL is the actual target location.
|
||||
*/
|
||||
DocPackage(RepoSource source,
|
||||
Properties props,
|
||||
int apiLevel,
|
||||
int revision,
|
||||
String license,
|
||||
@@ -59,6 +63,7 @@ public class DocPackage extends Package {
|
||||
Arch archiveArch,
|
||||
String archiveOsPath) {
|
||||
super(source,
|
||||
props,
|
||||
revision,
|
||||
license,
|
||||
description,
|
||||
@@ -66,7 +71,19 @@ public class DocPackage extends Package {
|
||||
archiveOs,
|
||||
archiveArch,
|
||||
archiveOsPath);
|
||||
mApiLevel = apiLevel;
|
||||
mApiLevel = Integer.parseInt(
|
||||
getProperty(props, PROP_API_LEVEL, Integer.toString(apiLevel)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the properties of the current packages in the given {@link Properties} object.
|
||||
* These properties will later be give the constructor that takes a {@link Properties} object.
|
||||
*/
|
||||
@Override
|
||||
void saveProperties(Properties props) {
|
||||
super.saveProperties(props);
|
||||
|
||||
props.setProperty(PROP_API_LEVEL, Integer.toString(mApiLevel));
|
||||
}
|
||||
|
||||
/** Returns the api-level, an int > 0, for platform, add-on and doc packages.
|
||||
|
||||
@@ -26,12 +26,15 @@ import org.w3c.dom.Node;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Represents a extra XML node in an SDK repository.
|
||||
*/
|
||||
public class ExtraPackage extends Package {
|
||||
|
||||
private static final String PROP_PATH = "Extra.Path"; //$NON-NLS-1$
|
||||
|
||||
private final String mPath;
|
||||
|
||||
/**
|
||||
@@ -45,11 +48,12 @@ public class ExtraPackage extends Package {
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually create a new package with one archive and the given attributes.
|
||||
* Manually create a new package with one archive and the given attributes or properties.
|
||||
* This is used to create packages from local directories in which case there must be
|
||||
* one archive which URL is the actual target location.
|
||||
*/
|
||||
ExtraPackage(RepoSource source,
|
||||
Properties props,
|
||||
String path,
|
||||
int revision,
|
||||
String license,
|
||||
@@ -59,6 +63,7 @@ public class ExtraPackage extends Package {
|
||||
Arch archiveArch,
|
||||
String archiveOsPath) {
|
||||
super(source,
|
||||
props,
|
||||
revision,
|
||||
license,
|
||||
description,
|
||||
@@ -66,7 +71,19 @@ public class ExtraPackage extends Package {
|
||||
archiveOs,
|
||||
archiveArch,
|
||||
archiveOsPath);
|
||||
mPath = path;
|
||||
// The path argument comes before whatever could be in the properties
|
||||
mPath = path != null ? path : getProperty(props, PROP_PATH, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the properties of the current packages in the given {@link Properties} object.
|
||||
* These properties will later be give the constructor that takes a {@link Properties} object.
|
||||
*/
|
||||
@Override
|
||||
void saveProperties(Properties props) {
|
||||
super.saveProperties(props);
|
||||
|
||||
props.setProperty(PROP_PATH, mPath);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,45 +17,26 @@
|
||||
package com.android.sdklib.internal.repository;
|
||||
|
||||
import com.android.sdklib.IAndroidTarget;
|
||||
import com.android.sdklib.ISdkLog;
|
||||
import com.android.sdklib.SdkConstants;
|
||||
import com.android.sdklib.SdkManager;
|
||||
import com.android.sdklib.internal.repository.Archive.Arch;
|
||||
import com.android.sdklib.internal.repository.Archive.Os;
|
||||
import com.android.sdklib.repository.SdkRepository;
|
||||
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Node;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.xml.XMLConstants;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
import javax.xml.validation.Schema;
|
||||
import javax.xml.validation.SchemaFactory;
|
||||
import javax.xml.validation.Validator;
|
||||
|
||||
/**
|
||||
* Scans a local SDK to find which packages are currently installed.
|
||||
*/
|
||||
public class LocalSdkParser {
|
||||
|
||||
private static final String SOURCE_XML = "source.xml"; //$NON-NLS-1$ // TODO move to global constants
|
||||
static final String SOURCE_PROPERTIES = "source.properties"; //$NON-NLS-1$
|
||||
private Package[] mPackages;
|
||||
|
||||
public LocalSdkParser() {
|
||||
@@ -63,7 +44,7 @@ public class LocalSdkParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the packages found by the last call to {@link #parseSdk(String, SdkManager)}.
|
||||
* Returns the packages found by the last call to {@link #parseSdk(String, SdkManager, ISdkLog)}.
|
||||
*/
|
||||
public Package[] getPackages() {
|
||||
return mPackages;
|
||||
@@ -71,7 +52,7 @@ public class LocalSdkParser {
|
||||
|
||||
/**
|
||||
* Clear the internal packages list. After this call, {@link #getPackages()} will return
|
||||
* null till {@link #parseSdk(String, SdkManager)} is called.
|
||||
* null till {@link #parseSdk(String, SdkManager, ISdkLog)} is called.
|
||||
*/
|
||||
public void clearPackages() {
|
||||
mPackages = null;
|
||||
@@ -85,57 +66,102 @@ public class LocalSdkParser {
|
||||
*
|
||||
* @param osSdkRoot The path to the SDK folder.
|
||||
* @param sdkManager An existing SDK manager to list current platforms and addons.
|
||||
* @param log An SDK logger object.
|
||||
* @return The packages found. Can be retrieved later using {@link #getPackages()}.
|
||||
*/
|
||||
public Package[] parseSdk(String osSdkRoot, SdkManager sdkManager) {
|
||||
public Package[] parseSdk(String osSdkRoot, SdkManager sdkManager, ISdkLog log) {
|
||||
ArrayList<Package> packages = new ArrayList<Package>();
|
||||
HashSet<File> visited = new HashSet<File>();
|
||||
|
||||
Package pkg = scanDoc(new File(osSdkRoot, SdkConstants.FD_DOCS));
|
||||
File dir = new File(osSdkRoot, SdkConstants.FD_DOCS);
|
||||
Package pkg = scanDoc(dir, log);
|
||||
if (pkg != null) {
|
||||
packages.add(pkg);
|
||||
visited.add(dir);
|
||||
}
|
||||
|
||||
pkg = scanTools(new File(osSdkRoot, SdkConstants.FD_TOOLS));
|
||||
dir = new File(osSdkRoot, SdkConstants.FD_TOOLS);
|
||||
pkg = scanTools(dir, log);
|
||||
if (pkg != null) {
|
||||
packages.add(pkg);
|
||||
visited.add(dir);
|
||||
}
|
||||
|
||||
// for platforms and add-ons, rely on the SdkManager parser
|
||||
for(IAndroidTarget target : sdkManager.getTargets()) {
|
||||
pkg = null;
|
||||
|
||||
if (target.isPlatform()) {
|
||||
pkg = parseXml(new File(target.getLocation(), SOURCE_XML),
|
||||
SdkRepository.NODE_PLATFORM);
|
||||
if (pkg == null) {
|
||||
pkg = new PlatformPackage(target);
|
||||
}
|
||||
|
||||
} else {
|
||||
pkg = parseXml(new File(target.getLocation(), SOURCE_XML),
|
||||
SdkRepository.NODE_ADD_ON);
|
||||
|
||||
if (pkg == null) {
|
||||
pkg = new AddonPackage(target);
|
||||
Properties props = parseProperties(new File(target.getLocation(), SOURCE_PROPERTIES));
|
||||
|
||||
try {
|
||||
if (target.isPlatform()) {
|
||||
pkg = new PlatformPackage(target, props);
|
||||
} else {
|
||||
pkg = new AddonPackage(target, props);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e, null);
|
||||
}
|
||||
|
||||
if (pkg != null) {
|
||||
packages.add(pkg);
|
||||
visited.add(new File(target.getLocation()));
|
||||
}
|
||||
}
|
||||
|
||||
scanExtra(osSdkRoot, visited, packages, log);
|
||||
|
||||
mPackages = packages.toArray(new Package[packages.size()]);
|
||||
return mPackages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find any other directory what we haven't successfully visited and
|
||||
* assume they contain extra packages.
|
||||
* @param log
|
||||
*/
|
||||
private void scanExtra(String osSdkRoot,
|
||||
HashSet<File> visited,
|
||||
ArrayList<Package> packages,
|
||||
ISdkLog log) {
|
||||
File root = new File(osSdkRoot);
|
||||
for (File dir : root.listFiles()) {
|
||||
if (dir.isDirectory() && !visited.contains(dir)) {
|
||||
|
||||
Properties props = parseProperties(new File(dir, SOURCE_PROPERTIES));
|
||||
if (props != null) {
|
||||
try {
|
||||
ExtraPackage pkg = new ExtraPackage(
|
||||
null, //source
|
||||
props, //properties
|
||||
dir.getName(), //path
|
||||
0, //revision
|
||||
null, //license
|
||||
"Tools", //description
|
||||
null, //descUrl
|
||||
Os.getCurrentOs(), //archiveOs
|
||||
Arch.getCurrentArch(), //archiveArch
|
||||
dir.getPath() //archiveOsPath
|
||||
);
|
||||
|
||||
// We only accept this as an extra package if it has a valid local path.
|
||||
if (pkg.isPathValid()) {
|
||||
packages.add(pkg);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a tools package at the given location.
|
||||
* Returns null if not found.
|
||||
*/
|
||||
private Package scanTools(File toolFolder) {
|
||||
// Can we find a source.xml?
|
||||
Package pkg = parseXml(new File(toolFolder, SOURCE_XML), SdkRepository.NODE_TOOL);
|
||||
private Package scanTools(File toolFolder, ISdkLog log) {
|
||||
// Can we find some properties?
|
||||
Properties props = parseProperties(new File(toolFolder, SOURCE_PROPERTIES));
|
||||
|
||||
// We're not going to check that all tools are present. At the very least
|
||||
// we should expect to find adb, android and an emulator adapted to the current OS.
|
||||
@@ -149,10 +175,11 @@ public class LocalSdkParser {
|
||||
return null;
|
||||
}
|
||||
|
||||
// if we don't have the package info, make one up
|
||||
if (pkg == null) {
|
||||
pkg = new ToolPackage(
|
||||
// Create are package. use the properties if we found any.
|
||||
try {
|
||||
ToolPackage pkg = new ToolPackage(
|
||||
null, //source
|
||||
props, //properties
|
||||
0, //revision
|
||||
null, //license
|
||||
"Tools", //description
|
||||
@@ -161,77 +188,42 @@ public class LocalSdkParser {
|
||||
Arch.getCurrentArch(), //archiveArch
|
||||
toolFolder.getPath() //archiveOsPath
|
||||
);
|
||||
}
|
||||
|
||||
return pkg;
|
||||
return pkg;
|
||||
} catch (Exception e) {
|
||||
log.error(e, null);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to find a docs package at the given location.
|
||||
* Returns null if not found.
|
||||
*/
|
||||
private Package scanDoc(File docFolder) {
|
||||
// Can we find a source.xml?
|
||||
Package pkg = parseXml(new File(docFolder, SOURCE_XML), SdkRepository.NODE_DOC);
|
||||
private Package scanDoc(File docFolder, ISdkLog log) {
|
||||
// Can we find some properties?
|
||||
Properties props = parseProperties(new File(docFolder, SOURCE_PROPERTIES));
|
||||
|
||||
// To start with, a doc folder should have an "index.html" to be acceptable.
|
||||
String html = readFile(new File(docFolder, "index.html"));
|
||||
if (html != null) {
|
||||
// Try to find something that looks like this line:
|
||||
// <a href="./sdk/1.5_r1/index.html">
|
||||
// We should find one or more of these and we want the highest version
|
||||
// and release numbers. Note that unfortunately that doesn't give us
|
||||
// the api-level we care about for the doc package.
|
||||
|
||||
String found = null;
|
||||
Pattern re = Pattern.compile(
|
||||
"<a\\s+href=\"./sdk/(\\d\\.\\d_r\\d)/index.html\">",
|
||||
Pattern.DOTALL);
|
||||
Matcher m = re.matcher(html);
|
||||
while(m.find()) {
|
||||
String v = m.group(1);
|
||||
if (found == null || v.compareTo(found) == 1) {
|
||||
found = v;
|
||||
}
|
||||
}
|
||||
|
||||
if (found == null) {
|
||||
// That doesn't look like a doc folder.
|
||||
return null;
|
||||
}
|
||||
|
||||
// We found the line, so it seems like an SDK doc.
|
||||
// Create a pkg if we don't have one yet.
|
||||
|
||||
if (pkg == null) {
|
||||
pkg = new DocPackage(
|
||||
// We don't actually check the content of the file.
|
||||
if (new File(docFolder, "index.html").isFile()) {
|
||||
try {
|
||||
DocPackage pkg = new DocPackage(
|
||||
null, //source
|
||||
props, //properties
|
||||
0, //apiLevel
|
||||
0, //revision
|
||||
null, //license
|
||||
String.format("Documentation for %1$s", found), //description
|
||||
null, //description
|
||||
null, //descUrl
|
||||
Os.getCurrentOs(), //archiveOs
|
||||
Arch.getCurrentArch(), //archiveArch
|
||||
docFolder.getPath() //archiveOsPath
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return pkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given XML file for the specific element filter.
|
||||
* The element must one of the package type local names: doc, tool, platform or addon.
|
||||
* Returns null if no such package was found.
|
||||
*/
|
||||
private Package parseXml(File sourceXmlFile, String elementFilter) {
|
||||
|
||||
String xml = readFile(sourceXmlFile);
|
||||
if (xml != null) {
|
||||
if (validateXml(xml)) {
|
||||
return parsePackages(xml, elementFilter);
|
||||
return pkg;
|
||||
} catch (Exception e) {
|
||||
log.error(e, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,170 +231,34 @@ public class LocalSdkParser {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given XML to find the specific element filter.
|
||||
* The element must one of the package type local names: doc, tool, platform or addon.
|
||||
* Returns null if no such package was found.
|
||||
* Parses the given file as properties file if it exists.
|
||||
* Returns null if the file does not exist, cannot be parsed or has no properties.
|
||||
*/
|
||||
private Package parsePackages(String xml, String elementFilter) {
|
||||
|
||||
private Properties parseProperties(File propsFile) {
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
Document doc = getDocument(xml);
|
||||
if (propsFile.exists()) {
|
||||
fis = new FileInputStream(propsFile);
|
||||
|
||||
Node root = getFirstChild(doc, SdkRepository.NODE_SDK_REPOSITORY);
|
||||
if (root != null) {
|
||||
Properties props = new Properties();
|
||||
props.load(fis);
|
||||
|
||||
// Parse license definitions
|
||||
HashMap<String, String> licenses = new HashMap<String, String>();
|
||||
for (Node child = root.getFirstChild();
|
||||
child != null;
|
||||
child = child.getNextSibling()) {
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE &&
|
||||
SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI()) &&
|
||||
child.getLocalName().equals(SdkRepository.NODE_LICENSE)) {
|
||||
Node id = child.getAttributes().getNamedItem(SdkRepository.ATTR_ID);
|
||||
if (id != null) {
|
||||
licenses.put(id.getNodeValue(), child.getTextContent());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse packages
|
||||
for (Node child = root.getFirstChild();
|
||||
child != null;
|
||||
child = child.getNextSibling()) {
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE &&
|
||||
SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI()) &&
|
||||
elementFilter.equals(child.getLocalName())) {
|
||||
String name = child.getLocalName();
|
||||
|
||||
try {
|
||||
if (SdkRepository.NODE_ADD_ON.equals(name)) {
|
||||
return new AddonPackage(null /*source*/, child, licenses);
|
||||
|
||||
} else if (SdkRepository.NODE_PLATFORM.equals(name)) {
|
||||
return new PlatformPackage(null /*source*/, child, licenses);
|
||||
|
||||
} else if (SdkRepository.NODE_DOC.equals(name)) {
|
||||
return new DocPackage(null /*source*/, child, licenses);
|
||||
|
||||
} else if (SdkRepository.NODE_TOOL.equals(name)) {
|
||||
return new ToolPackage(null /*source*/, child, licenses);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Ignore invalid packages
|
||||
}
|
||||
}
|
||||
// To be valid, there must be at least one property in it.
|
||||
if (props.size() > 0) {
|
||||
return props;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a file as a string.
|
||||
* Returns null if the file could not be read.
|
||||
*/
|
||||
private String readFile(File sourceXmlFile) {
|
||||
FileReader fr = null;
|
||||
try {
|
||||
fr = new FileReader(sourceXmlFile);
|
||||
BufferedReader br = new BufferedReader(fr);
|
||||
StringBuilder dest = new StringBuilder();
|
||||
char[] buf = new char[65536];
|
||||
int n;
|
||||
while ((n = br.read(buf)) > 0) {
|
||||
if (n > 0) {
|
||||
dest.append(buf, 0, n);
|
||||
}
|
||||
}
|
||||
return dest.toString();
|
||||
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (fr != null) {
|
||||
if (fis != null) {
|
||||
try {
|
||||
fr.close();
|
||||
fis.close();
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates this XML against the SDK Repository schema.
|
||||
* Returns true if the XML was correctly validated.
|
||||
*/
|
||||
private boolean validateXml(String xml) {
|
||||
|
||||
try {
|
||||
Validator validator = getValidator();
|
||||
validator.validate(new StreamSource(new StringReader(xml)));
|
||||
return true;
|
||||
|
||||
} catch (SAXException e) {
|
||||
// ignore
|
||||
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that returns a validator for our XSD
|
||||
*/
|
||||
private Validator getValidator() throws SAXException {
|
||||
InputStream xsdStream = SdkRepository.getXsdStream();
|
||||
SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
|
||||
|
||||
// This may throw a SAX Exception if the schema itself is not a valid XSD
|
||||
Schema schema = factory.newSchema(new StreamSource(xsdStream));
|
||||
|
||||
Validator validator = schema.newValidator();
|
||||
|
||||
return validator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first child element with the given XML local name.
|
||||
* If xmlLocalName is null, returns the very first child element.
|
||||
*/
|
||||
private Node getFirstChild(Node node, String xmlLocalName) {
|
||||
|
||||
for(Node child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
|
||||
if (child.getNodeType() == Node.ELEMENT_NODE &&
|
||||
SdkRepository.NS_SDK_REPOSITORY.equals(child.getNamespaceURI())) {
|
||||
if (xmlLocalName == null || child.getLocalName().equals(xmlLocalName)) {
|
||||
return child;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes an XML document as a string as parameter and returns a DOM for it.
|
||||
*/
|
||||
private Document getDocument(String xml)
|
||||
throws ParserConfigurationException, SAXException, IOException {
|
||||
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
||||
factory.setIgnoringComments(true);
|
||||
factory.setNamespaceAware(true);
|
||||
|
||||
DocumentBuilder builder = factory.newDocumentBuilder();
|
||||
Document doc = builder.parse(new InputSource(new StringReader(xml)));
|
||||
|
||||
return doc;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.w3c.dom.Node;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* A {@link Package} is the base class for "something" that can be downloaded from
|
||||
@@ -41,6 +42,12 @@ import java.util.Map;
|
||||
*/
|
||||
public abstract class Package implements IDescription {
|
||||
|
||||
private static final String PROP_REVISION = "Pkg.Revision"; //$NON-NLS-1$
|
||||
private static final String PROP_LICENSE = "Pkg.License"; //$NON-NLS-1$
|
||||
private static final String PROP_DESC = "Pkg.Desc"; //$NON-NLS-1$
|
||||
private static final String PROP_DESC_URL = "Pkg.DescUrl"; //$NON-NLS-1$
|
||||
private static final String PROP_SOURCE_URL = "Pkg.SourceUrl"; //$NON-NLS-1$
|
||||
private static final String PROP_USER_SOURCE = "Pkg.UserSrc"; //$NON-NLS-1$
|
||||
private final int mRevision;
|
||||
private final String mLicense;
|
||||
private final String mDescription;
|
||||
@@ -68,8 +75,12 @@ public abstract class Package implements IDescription {
|
||||
* Manually create a new package with one archive and the given attributes.
|
||||
* This is used to create packages from local directories in which case there must be
|
||||
* one archive which URL is the actual target location.
|
||||
*
|
||||
* Properties from props are used first when possible, e.g. if props is non null.
|
||||
*/
|
||||
public Package(RepoSource source,
|
||||
public Package(
|
||||
RepoSource source,
|
||||
Properties props,
|
||||
int revision,
|
||||
String license,
|
||||
String description,
|
||||
@@ -77,18 +88,58 @@ public abstract class Package implements IDescription {
|
||||
Os archiveOs,
|
||||
Arch archiveArch,
|
||||
String archiveOsPath) {
|
||||
|
||||
mRevision = Integer.parseInt(getProperty(props, PROP_REVISION, Integer.toString(revision)));
|
||||
mLicense = getProperty(props, PROP_LICENSE, license);
|
||||
mDescription = getProperty(props, PROP_DESC, description);
|
||||
mDescUrl = getProperty(props, PROP_DESC_URL, descUrl);
|
||||
|
||||
// If source is null and we can find a source URL in the properties, generate
|
||||
// a dummy source just to store the URL. This allows us to easily remember where
|
||||
// a package comes from.
|
||||
String srcUrl = getProperty(props, PROP_SOURCE_URL, null);
|
||||
if (props != null && source == null && srcUrl != null) {
|
||||
boolean isUser = Boolean.parseBoolean(props.getProperty(PROP_USER_SOURCE,
|
||||
Boolean.TRUE.toString()));
|
||||
source = new RepoSource(srcUrl, isUser);
|
||||
}
|
||||
mSource = source;
|
||||
mRevision = revision;
|
||||
mLicense = license;
|
||||
mDescription = description;
|
||||
mDescUrl = descUrl;
|
||||
|
||||
mArchives = new Archive[1];
|
||||
mArchives[0] = new Archive(this,
|
||||
props,
|
||||
archiveOs,
|
||||
archiveArch,
|
||||
archiveOsPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility method that returns a property from a {@link Properties} object.
|
||||
* Returns the default value if props is null or if the property is not defined.
|
||||
*/
|
||||
protected String getProperty(Properties props, String propKey, String defaultValue) {
|
||||
if (props == null) {
|
||||
return defaultValue;
|
||||
}
|
||||
return props.getProperty(propKey, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the properties of the current packages in the given {@link Properties} object.
|
||||
* These properties will later be give the constructor that takes a {@link Properties} object.
|
||||
*/
|
||||
void saveProperties(Properties props) {
|
||||
props.setProperty(PROP_REVISION, Integer.toString(mRevision));
|
||||
props.setProperty(PROP_LICENSE, mLicense);
|
||||
props.setProperty(PROP_DESC, mDescription);
|
||||
props.setProperty(PROP_DESC_URL, mDescUrl);
|
||||
|
||||
if (mSource != null) {
|
||||
props.setProperty(PROP_SOURCE_URL, mSource.getUrl());
|
||||
props.setProperty(PROP_USER_SOURCE, Boolean.toString(mSource.isUserSource()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the uses-licence node of this package, if any, and returns the license
|
||||
* definition if there's one. Returns null if there's no uses-license element or no
|
||||
|
||||
@@ -27,12 +27,16 @@ import org.w3c.dom.Node;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Represents a platform XML node in an SDK repository.
|
||||
*/
|
||||
public class PlatformPackage extends Package {
|
||||
|
||||
private static final String PROP_API_LEVEL = "Platform.ApiLevel"; //$NON-NLS-1$
|
||||
private static final String PROP_VERSION = "Platform.Version"; //$NON-NLS-1$
|
||||
|
||||
private final String mVersion;
|
||||
private final int mApiLevel;
|
||||
|
||||
@@ -53,8 +57,9 @@ public class PlatformPackage extends Package {
|
||||
* This is used to list local SDK folders in which case there is one archive which
|
||||
* URL is the actual target location.
|
||||
*/
|
||||
PlatformPackage(IAndroidTarget target) {
|
||||
PlatformPackage(IAndroidTarget target, Properties props) {
|
||||
super( null, //source
|
||||
props, //properties
|
||||
0, //revision
|
||||
null, //license
|
||||
target.getDescription(), //description
|
||||
@@ -68,6 +73,18 @@ public class PlatformPackage extends Package {
|
||||
mVersion = target.getApiVersionName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the properties of the current packages in the given {@link Properties} object.
|
||||
* These properties will later be give the constructor that takes a {@link Properties} object.
|
||||
*/
|
||||
@Override
|
||||
void saveProperties(Properties props) {
|
||||
super.saveProperties(props);
|
||||
|
||||
props.setProperty(PROP_API_LEVEL, Integer.toString(mApiLevel));
|
||||
props.setProperty(PROP_VERSION, mVersion);
|
||||
}
|
||||
|
||||
/** Returns the version, a string, for platform packages. */
|
||||
public String getVersion() {
|
||||
return mVersion;
|
||||
|
||||
@@ -25,6 +25,7 @@ import org.w3c.dom.Node;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Represents a tool XML node in an SDK repository.
|
||||
@@ -41,11 +42,13 @@ public class ToolPackage extends Package {
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually create a new package with one archive and the given attributes.
|
||||
* Manually create a new package with one archive and the given attributes or properties.
|
||||
* This is used to create packages from local directories in which case there must be
|
||||
* one archive which URL is the actual target location.
|
||||
*/
|
||||
ToolPackage(RepoSource source,
|
||||
ToolPackage(
|
||||
RepoSource source,
|
||||
Properties props,
|
||||
int revision,
|
||||
String license,
|
||||
String description,
|
||||
@@ -54,6 +57,7 @@ public class ToolPackage extends Package {
|
||||
Arch archiveArch,
|
||||
String archiveOsPath) {
|
||||
super(source,
|
||||
props,
|
||||
revision,
|
||||
license,
|
||||
description,
|
||||
|
||||
@@ -101,8 +101,10 @@ class LocalSdkAdapter {
|
||||
|
||||
if (packages == null) {
|
||||
// load on demand the first time
|
||||
packages = parser.parseSdk(mUpdaterData.getOsSdkRoot(),
|
||||
mUpdaterData.getSdkManager());
|
||||
packages = parser.parseSdk(
|
||||
mUpdaterData.getOsSdkRoot(),
|
||||
mUpdaterData.getSdkManager(),
|
||||
mUpdaterData.getSdkLog());
|
||||
}
|
||||
|
||||
if (packages != null) {
|
||||
|
||||
Reference in New Issue
Block a user