diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java index e273a5458..7908322a9 100755 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/AddonPackage.java @@ -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 element. */ diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java index 191ef1986..c34e859ea 100755 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Archive.java @@ -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; + } + + +} diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java index e7fa8936a..c1b8d1d3f 100755 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/DocPackage.java @@ -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. diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java index 9cd602c88..f9d375277 100755 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ExtraPackage.java @@ -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); } /** diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java index 91e264caf..0e3b204fe 100755 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/LocalSdkParser.java @@ -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 packages = new ArrayList(); + HashSet visited = new HashSet(); - 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 visited, + ArrayList 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: - // - // 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( - "", - 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 licenses = new HashMap(); - 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; - } } diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java index 0e11ef501..b28043a49 100755 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/Package.java @@ -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 diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java index 85dbbd0e1..1c0a63800 100755 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/PlatformPackage.java @@ -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; diff --git a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java index 107604965..b81d044ca 100755 --- a/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java +++ b/tools/sdkmanager/libs/sdklib/src/com/android/sdklib/internal/repository/ToolPackage.java @@ -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, diff --git a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalSdkAdapter.java b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalSdkAdapter.java index a92129f53..ab384b8e7 100755 --- a/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalSdkAdapter.java +++ b/tools/sdkmanager/libs/sdkuilib/src/com/android/sdkuilib/internal/repository/LocalSdkAdapter.java @@ -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) {