am 6fe28b1f: Merge change 5552 into donut
Merge commit '6fe28b1f7fb5f4297210eb7e0de5cad7ba563551' * commit '6fe28b1f7fb5f4297210eb7e0de5cad7ba563551': SDK Updater: Store local source properties when installing.
This commit is contained in:
committed by
The Android Open Source Project
commit
9f93ab51ab
@@ -29,12 +29,17 @@ import org.w3c.dom.Node;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents an add-on XML node in an SDK repository.
|
* Represents an add-on XML node in an SDK repository.
|
||||||
*/
|
*/
|
||||||
public class AddonPackage extends Package {
|
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 mVendor;
|
||||||
private final String mName;
|
private final String mName;
|
||||||
private final int mApiLevel;
|
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
|
* This is used to list local SDK folders in which case there is one archive which
|
||||||
* URL is the actual target location.
|
* URL is the actual target location.
|
||||||
*/
|
*/
|
||||||
AddonPackage(IAndroidTarget target) {
|
AddonPackage(IAndroidTarget target, Properties props) {
|
||||||
super( null, //source
|
super( null, //source
|
||||||
|
props, //properties
|
||||||
0, //revision
|
0, //revision
|
||||||
null, //license
|
null, //license
|
||||||
target.getDescription(), //description
|
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.
|
* Parses a <libs> element.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import java.io.InputStream;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.zip.ZipInputStream;
|
import java.util.zip.ZipInputStream;
|
||||||
|
|
||||||
@@ -43,6 +44,8 @@ import java.util.zip.ZipInputStream;
|
|||||||
public class Archive implements IDescription {
|
public class Archive implements IDescription {
|
||||||
|
|
||||||
public static final int NUM_MONITOR_INC = 100;
|
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. */
|
/** The checksum type. */
|
||||||
public enum ChecksumType {
|
public enum ChecksumType {
|
||||||
@@ -175,11 +178,14 @@ public class Archive implements IDescription {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new local archive.
|
* 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;
|
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;
|
mUrl = null;
|
||||||
mLocalOsPath = localOsPath;
|
mLocalOsPath = localOsPath;
|
||||||
mSize = 0;
|
mSize = 0;
|
||||||
@@ -187,6 +193,15 @@ public class Archive implements IDescription {
|
|||||||
mIsLocal = true;
|
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 true if this is a locally installed archive.
|
||||||
* Returns false if this is a remote archive that needs to be downloaded.
|
* Returns false if this is a remote archive that needs to be downloaded.
|
||||||
@@ -623,6 +638,10 @@ public class Archive implements IDescription {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!generateSourceProperties(unzipDestFolder)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// Compute destination directory
|
// Compute destination directory
|
||||||
destFolder = getParentPackage().getInstallFolder(
|
destFolder = getParentPackage().getInstallFolder(
|
||||||
osSdkRoot, zipRootFolder[0], sdkManager);
|
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.io.File;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a doc XML node in an SDK repository.
|
* Represents a doc XML node in an SDK repository.
|
||||||
*/
|
*/
|
||||||
public class DocPackage extends Package {
|
public class DocPackage extends Package {
|
||||||
|
|
||||||
|
private static final String PROP_API_LEVEL = "Doc.ApiLevel"; //$NON-NLS-1$
|
||||||
|
|
||||||
private final int mApiLevel;
|
private final int mApiLevel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,6 +53,7 @@ public class DocPackage extends Package {
|
|||||||
* one archive which URL is the actual target location.
|
* one archive which URL is the actual target location.
|
||||||
*/
|
*/
|
||||||
DocPackage(RepoSource source,
|
DocPackage(RepoSource source,
|
||||||
|
Properties props,
|
||||||
int apiLevel,
|
int apiLevel,
|
||||||
int revision,
|
int revision,
|
||||||
String license,
|
String license,
|
||||||
@@ -59,6 +63,7 @@ public class DocPackage extends Package {
|
|||||||
Arch archiveArch,
|
Arch archiveArch,
|
||||||
String archiveOsPath) {
|
String archiveOsPath) {
|
||||||
super(source,
|
super(source,
|
||||||
|
props,
|
||||||
revision,
|
revision,
|
||||||
license,
|
license,
|
||||||
description,
|
description,
|
||||||
@@ -66,7 +71,19 @@ public class DocPackage extends Package {
|
|||||||
archiveOs,
|
archiveOs,
|
||||||
archiveArch,
|
archiveArch,
|
||||||
archiveOsPath);
|
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.
|
/** 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.io.File;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a extra XML node in an SDK repository.
|
* Represents a extra XML node in an SDK repository.
|
||||||
*/
|
*/
|
||||||
public class ExtraPackage extends Package {
|
public class ExtraPackage extends Package {
|
||||||
|
|
||||||
|
private static final String PROP_PATH = "Extra.Path"; //$NON-NLS-1$
|
||||||
|
|
||||||
private final String mPath;
|
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
|
* This is used to create packages from local directories in which case there must be
|
||||||
* one archive which URL is the actual target location.
|
* one archive which URL is the actual target location.
|
||||||
*/
|
*/
|
||||||
ExtraPackage(RepoSource source,
|
ExtraPackage(RepoSource source,
|
||||||
|
Properties props,
|
||||||
String path,
|
String path,
|
||||||
int revision,
|
int revision,
|
||||||
String license,
|
String license,
|
||||||
@@ -59,6 +63,7 @@ public class ExtraPackage extends Package {
|
|||||||
Arch archiveArch,
|
Arch archiveArch,
|
||||||
String archiveOsPath) {
|
String archiveOsPath) {
|
||||||
super(source,
|
super(source,
|
||||||
|
props,
|
||||||
revision,
|
revision,
|
||||||
license,
|
license,
|
||||||
description,
|
description,
|
||||||
@@ -66,7 +71,19 @@ public class ExtraPackage extends Package {
|
|||||||
archiveOs,
|
archiveOs,
|
||||||
archiveArch,
|
archiveArch,
|
||||||
archiveOsPath);
|
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;
|
package com.android.sdklib.internal.repository;
|
||||||
|
|
||||||
import com.android.sdklib.IAndroidTarget;
|
import com.android.sdklib.IAndroidTarget;
|
||||||
|
import com.android.sdklib.ISdkLog;
|
||||||
import com.android.sdklib.SdkConstants;
|
import com.android.sdklib.SdkConstants;
|
||||||
import com.android.sdklib.SdkManager;
|
import com.android.sdklib.SdkManager;
|
||||||
import com.android.sdklib.internal.repository.Archive.Arch;
|
import com.android.sdklib.internal.repository.Archive.Arch;
|
||||||
import com.android.sdklib.internal.repository.Archive.Os;
|
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.File;
|
||||||
import java.io.FileReader;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.StringReader;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
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.
|
* Scans a local SDK to find which packages are currently installed.
|
||||||
*/
|
*/
|
||||||
public class LocalSdkParser {
|
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;
|
private Package[] mPackages;
|
||||||
|
|
||||||
public LocalSdkParser() {
|
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() {
|
public Package[] getPackages() {
|
||||||
return mPackages;
|
return mPackages;
|
||||||
@@ -71,7 +52,7 @@ public class LocalSdkParser {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Clear the internal packages list. After this call, {@link #getPackages()} will return
|
* 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() {
|
public void clearPackages() {
|
||||||
mPackages = null;
|
mPackages = null;
|
||||||
@@ -85,57 +66,102 @@ public class LocalSdkParser {
|
|||||||
*
|
*
|
||||||
* @param osSdkRoot The path to the SDK folder.
|
* @param osSdkRoot The path to the SDK folder.
|
||||||
* @param sdkManager An existing SDK manager to list current platforms and addons.
|
* @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()}.
|
* @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>();
|
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) {
|
if (pkg != null) {
|
||||||
packages.add(pkg);
|
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) {
|
if (pkg != null) {
|
||||||
packages.add(pkg);
|
packages.add(pkg);
|
||||||
|
visited.add(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for platforms and add-ons, rely on the SdkManager parser
|
// for platforms and add-ons, rely on the SdkManager parser
|
||||||
for(IAndroidTarget target : sdkManager.getTargets()) {
|
for(IAndroidTarget target : sdkManager.getTargets()) {
|
||||||
pkg = null;
|
|
||||||
|
|
||||||
if (target.isPlatform()) {
|
Properties props = parseProperties(new File(target.getLocation(), SOURCE_PROPERTIES));
|
||||||
pkg = parseXml(new File(target.getLocation(), SOURCE_XML),
|
|
||||||
SdkRepository.NODE_PLATFORM);
|
try {
|
||||||
if (pkg == null) {
|
if (target.isPlatform()) {
|
||||||
pkg = new PlatformPackage(target);
|
pkg = new PlatformPackage(target, props);
|
||||||
}
|
} else {
|
||||||
|
pkg = new AddonPackage(target, props);
|
||||||
} else {
|
|
||||||
pkg = parseXml(new File(target.getLocation(), SOURCE_XML),
|
|
||||||
SdkRepository.NODE_ADD_ON);
|
|
||||||
|
|
||||||
if (pkg == null) {
|
|
||||||
pkg = new AddonPackage(target);
|
|
||||||
}
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pkg != null) {
|
if (pkg != null) {
|
||||||
packages.add(pkg);
|
packages.add(pkg);
|
||||||
|
visited.add(new File(target.getLocation()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
scanExtra(osSdkRoot, visited, packages, log);
|
||||||
|
|
||||||
mPackages = packages.toArray(new Package[packages.size()]);
|
mPackages = packages.toArray(new Package[packages.size()]);
|
||||||
return mPackages;
|
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.
|
* Try to find a tools package at the given location.
|
||||||
* Returns null if not found.
|
* Returns null if not found.
|
||||||
*/
|
*/
|
||||||
private Package scanTools(File toolFolder) {
|
private Package scanTools(File toolFolder, ISdkLog log) {
|
||||||
// Can we find a source.xml?
|
// Can we find some properties?
|
||||||
Package pkg = parseXml(new File(toolFolder, SOURCE_XML), SdkRepository.NODE_TOOL);
|
Properties props = parseProperties(new File(toolFolder, SOURCE_PROPERTIES));
|
||||||
|
|
||||||
// We're not going to check that all tools are present. At the very least
|
// 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.
|
// we should expect to find adb, android and an emulator adapted to the current OS.
|
||||||
@@ -149,10 +175,11 @@ public class LocalSdkParser {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// if we don't have the package info, make one up
|
// Create are package. use the properties if we found any.
|
||||||
if (pkg == null) {
|
try {
|
||||||
pkg = new ToolPackage(
|
ToolPackage pkg = new ToolPackage(
|
||||||
null, //source
|
null, //source
|
||||||
|
props, //properties
|
||||||
0, //revision
|
0, //revision
|
||||||
null, //license
|
null, //license
|
||||||
"Tools", //description
|
"Tools", //description
|
||||||
@@ -161,77 +188,42 @@ public class LocalSdkParser {
|
|||||||
Arch.getCurrentArch(), //archiveArch
|
Arch.getCurrentArch(), //archiveArch
|
||||||
toolFolder.getPath() //archiveOsPath
|
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.
|
* Try to find a docs package at the given location.
|
||||||
* Returns null if not found.
|
* Returns null if not found.
|
||||||
*/
|
*/
|
||||||
private Package scanDoc(File docFolder) {
|
private Package scanDoc(File docFolder, ISdkLog log) {
|
||||||
// Can we find a source.xml?
|
// Can we find some properties?
|
||||||
Package pkg = parseXml(new File(docFolder, SOURCE_XML), SdkRepository.NODE_DOC);
|
Properties props = parseProperties(new File(docFolder, SOURCE_PROPERTIES));
|
||||||
|
|
||||||
// To start with, a doc folder should have an "index.html" to be acceptable.
|
// To start with, a doc folder should have an "index.html" to be acceptable.
|
||||||
String html = readFile(new File(docFolder, "index.html"));
|
// We don't actually check the content of the file.
|
||||||
if (html != null) {
|
if (new File(docFolder, "index.html").isFile()) {
|
||||||
// Try to find something that looks like this line:
|
try {
|
||||||
// <a href="./sdk/1.5_r1/index.html">
|
DocPackage pkg = new DocPackage(
|
||||||
// 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(
|
|
||||||
null, //source
|
null, //source
|
||||||
|
props, //properties
|
||||||
0, //apiLevel
|
0, //apiLevel
|
||||||
0, //revision
|
0, //revision
|
||||||
null, //license
|
null, //license
|
||||||
String.format("Documentation for %1$s", found), //description
|
null, //description
|
||||||
null, //descUrl
|
null, //descUrl
|
||||||
Os.getCurrentOs(), //archiveOs
|
Os.getCurrentOs(), //archiveOs
|
||||||
Arch.getCurrentArch(), //archiveArch
|
Arch.getCurrentArch(), //archiveArch
|
||||||
docFolder.getPath() //archiveOsPath
|
docFolder.getPath() //archiveOsPath
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pkg;
|
return pkg;
|
||||||
}
|
} catch (Exception e) {
|
||||||
|
log.error(e, null);
|
||||||
/**
|
|
||||||
* 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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,170 +231,34 @@ public class LocalSdkParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the given XML to find the specific element filter.
|
* Parses the given file as properties file if it exists.
|
||||||
* The element must one of the package type local names: doc, tool, platform or addon.
|
* Returns null if the file does not exist, cannot be parsed or has no properties.
|
||||||
* Returns null if no such package was found.
|
|
||||||
*/
|
*/
|
||||||
private Package parsePackages(String xml, String elementFilter) {
|
private Properties parseProperties(File propsFile) {
|
||||||
|
FileInputStream fis = null;
|
||||||
try {
|
try {
|
||||||
Document doc = getDocument(xml);
|
if (propsFile.exists()) {
|
||||||
|
fis = new FileInputStream(propsFile);
|
||||||
|
|
||||||
Node root = getFirstChild(doc, SdkRepository.NODE_SDK_REPOSITORY);
|
Properties props = new Properties();
|
||||||
if (root != null) {
|
props.load(fis);
|
||||||
|
|
||||||
// Parse license definitions
|
// To be valid, there must be at least one property in it.
|
||||||
HashMap<String, String> licenses = new HashMap<String, String>();
|
if (props.size() > 0) {
|
||||||
for (Node child = root.getFirstChild();
|
return props;
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} 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) {
|
} catch (IOException e) {
|
||||||
// ignore
|
e.printStackTrace();
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
if (fr != null) {
|
if (fis != null) {
|
||||||
try {
|
try {
|
||||||
fr.close();
|
fis.close();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
// ignore
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
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.io.File;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A {@link Package} is the base class for "something" that can be downloaded from
|
* 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 {
|
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 int mRevision;
|
||||||
private final String mLicense;
|
private final String mLicense;
|
||||||
private final String mDescription;
|
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.
|
* 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
|
* This is used to create packages from local directories in which case there must be
|
||||||
* one archive which URL is the actual target location.
|
* 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,
|
int revision,
|
||||||
String license,
|
String license,
|
||||||
String description,
|
String description,
|
||||||
@@ -77,18 +88,58 @@ public abstract class Package implements IDescription {
|
|||||||
Os archiveOs,
|
Os archiveOs,
|
||||||
Arch archiveArch,
|
Arch archiveArch,
|
||||||
String archiveOsPath) {
|
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;
|
mSource = source;
|
||||||
mRevision = revision;
|
|
||||||
mLicense = license;
|
|
||||||
mDescription = description;
|
|
||||||
mDescUrl = descUrl;
|
|
||||||
mArchives = new Archive[1];
|
mArchives = new Archive[1];
|
||||||
mArchives[0] = new Archive(this,
|
mArchives[0] = new Archive(this,
|
||||||
|
props,
|
||||||
archiveOs,
|
archiveOs,
|
||||||
archiveArch,
|
archiveArch,
|
||||||
archiveOsPath);
|
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
|
* 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
|
* 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.io.File;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a platform XML node in an SDK repository.
|
* Represents a platform XML node in an SDK repository.
|
||||||
*/
|
*/
|
||||||
public class PlatformPackage extends Package {
|
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 String mVersion;
|
||||||
private final int mApiLevel;
|
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
|
* This is used to list local SDK folders in which case there is one archive which
|
||||||
* URL is the actual target location.
|
* URL is the actual target location.
|
||||||
*/
|
*/
|
||||||
PlatformPackage(IAndroidTarget target) {
|
PlatformPackage(IAndroidTarget target, Properties props) {
|
||||||
super( null, //source
|
super( null, //source
|
||||||
|
props, //properties
|
||||||
0, //revision
|
0, //revision
|
||||||
null, //license
|
null, //license
|
||||||
target.getDescription(), //description
|
target.getDescription(), //description
|
||||||
@@ -68,6 +73,18 @@ public class PlatformPackage extends Package {
|
|||||||
mVersion = target.getApiVersionName();
|
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. */
|
/** Returns the version, a string, for platform packages. */
|
||||||
public String getVersion() {
|
public String getVersion() {
|
||||||
return mVersion;
|
return mVersion;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import org.w3c.dom.Node;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a tool XML node in an SDK repository.
|
* 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
|
* This is used to create packages from local directories in which case there must be
|
||||||
* one archive which URL is the actual target location.
|
* one archive which URL is the actual target location.
|
||||||
*/
|
*/
|
||||||
ToolPackage(RepoSource source,
|
ToolPackage(
|
||||||
|
RepoSource source,
|
||||||
|
Properties props,
|
||||||
int revision,
|
int revision,
|
||||||
String license,
|
String license,
|
||||||
String description,
|
String description,
|
||||||
@@ -54,6 +57,7 @@ public class ToolPackage extends Package {
|
|||||||
Arch archiveArch,
|
Arch archiveArch,
|
||||||
String archiveOsPath) {
|
String archiveOsPath) {
|
||||||
super(source,
|
super(source,
|
||||||
|
props,
|
||||||
revision,
|
revision,
|
||||||
license,
|
license,
|
||||||
description,
|
description,
|
||||||
|
|||||||
@@ -101,8 +101,10 @@ class LocalSdkAdapter {
|
|||||||
|
|
||||||
if (packages == null) {
|
if (packages == null) {
|
||||||
// load on demand the first time
|
// load on demand the first time
|
||||||
packages = parser.parseSdk(mUpdaterData.getOsSdkRoot(),
|
packages = parser.parseSdk(
|
||||||
mUpdaterData.getSdkManager());
|
mUpdaterData.getOsSdkRoot(),
|
||||||
|
mUpdaterData.getSdkManager(),
|
||||||
|
mUpdaterData.getSdkLog());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (packages != null) {
|
if (packages != null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user