Home | History | Annotate | Download | only in repository
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.sdklib.internal.repository;
     18 
     19 import com.android.sdklib.AndroidVersion;
     20 import com.android.sdklib.SdkConstants;
     21 import com.android.sdklib.SdkManager;
     22 import com.android.sdklib.internal.repository.Archive.Arch;
     23 import com.android.sdklib.internal.repository.Archive.Os;
     24 import com.android.sdklib.repository.SdkRepoConstants;
     25 
     26 import org.w3c.dom.Node;
     27 
     28 import java.io.File;
     29 import java.util.Map;
     30 import java.util.Properties;
     31 
     32 /**
     33  * Represents a doc XML node in an SDK repository.
     34  * <p/>
     35  * Note that a doc package has a version and thus implements {@link IPackageVersion}.
     36  * However there is no mandatory dependency that limits installation so this does not
     37  * implement {@link IPlatformDependency}.
     38  */
     39 public class DocPackage extends Package implements IPackageVersion {
     40 
     41     private final AndroidVersion mVersion;
     42 
     43     /**
     44      * Creates a new doc package from the attributes and elements of the given XML node.
     45      * This constructor should throw an exception if the package cannot be created.
     46      *
     47      * @param source The {@link SdkSource} where this is loaded from.
     48      * @param packageNode The XML element being parsed.
     49      * @param nsUri The namespace URI of the originating XML document, to be able to deal with
     50      *          parameters that vary according to the originating XML schema.
     51      * @param licenses The licenses loaded from the XML originating document.
     52      */
     53     DocPackage(SdkSource source, Node packageNode, String nsUri, Map<String,String> licenses) {
     54         super(source, packageNode, nsUri, licenses);
     55 
     56         int apiLevel = XmlParserUtils.getXmlInt   (packageNode, SdkRepoConstants.NODE_API_LEVEL, 0);
     57         String codeName = XmlParserUtils.getXmlString(packageNode, SdkRepoConstants.NODE_CODENAME);
     58         if (codeName.length() == 0) {
     59             codeName = null;
     60         }
     61         mVersion = new AndroidVersion(apiLevel, codeName);
     62     }
     63 
     64     /**
     65      * Manually create a new package with one archive and the given attributes.
     66      * This is used to create packages from local directories in which case there must be
     67      * one archive which URL is the actual target location.
     68      * <p/>
     69      * By design, this creates a package with one and only one archive.
     70      */
     71     static Package create(SdkSource source,
     72             Properties props,
     73             int apiLevel,
     74             String codename,
     75             int revision,
     76             String license,
     77             String description,
     78             String descUrl,
     79             Os archiveOs,
     80             Arch archiveArch,
     81             String archiveOsPath) {
     82         return new DocPackage(source, props, apiLevel, codename, revision, license, description,
     83                 descUrl, archiveOs, archiveArch, archiveOsPath);
     84     }
     85 
     86     private DocPackage(SdkSource source,
     87             Properties props,
     88             int apiLevel,
     89             String codename,
     90             int revision,
     91             String license,
     92             String description,
     93             String descUrl,
     94             Os archiveOs,
     95             Arch archiveArch,
     96             String archiveOsPath) {
     97         super(source,
     98                 props,
     99                 revision,
    100                 license,
    101                 description,
    102                 descUrl,
    103                 archiveOs,
    104                 archiveArch,
    105                 archiveOsPath);
    106         mVersion = new AndroidVersion(props, apiLevel, codename);
    107     }
    108 
    109     /**
    110      * Save the properties of the current packages in the given {@link Properties} object.
    111      * These properties will later be give the constructor that takes a {@link Properties} object.
    112      */
    113     @Override
    114     void saveProperties(Properties props) {
    115         super.saveProperties(props);
    116 
    117         mVersion.saveProperties(props);
    118     }
    119 
    120     /**
    121      * Returns the version, for platform, add-on and doc packages.
    122      * Can be 0 if this is a local package of unknown api-level.
    123      */
    124     public AndroidVersion getVersion() {
    125         return mVersion;
    126     }
    127 
    128     /**
    129      * Returns a string identifier to install this package from the command line.
    130      * For docs, we use "doc-N" where N is the API or the preview codename.
    131      * <p/>
    132      * {@inheritDoc}
    133      */
    134     @Override
    135     public String installId() {
    136         return "doc-" + mVersion.getApiString();    //$NON-NLS-1$
    137     }
    138 
    139     /**
    140      * Returns a description of this package that is suitable for a list display.
    141      * <p/>
    142      * {@inheritDoc}
    143      */
    144     @Override
    145     public String getListDescription() {
    146         if (mVersion.isPreview()) {
    147             return String.format("Documentation for Android '%1$s' Preview SDK%2$s",
    148                     mVersion.getCodename(),
    149                     isObsolete() ? " (Obsolete)" : "");
    150         } else {
    151             return String.format("Documentation for Android SDK%2$s",
    152                     mVersion.getApiLevel(),
    153                     isObsolete() ? " (Obsolete)" : "");
    154         }
    155     }
    156 
    157     /**
    158      * Returns a short description for an {@link IDescription}.
    159      */
    160     @Override
    161     public String getShortDescription() {
    162         if (mVersion.isPreview()) {
    163             return String.format("Documentation for Android '%1$s' Preview SDK, revision %2$s%3$s",
    164                     mVersion.getCodename(),
    165                     getRevision(),
    166                     isObsolete() ? " (Obsolete)" : "");
    167         } else {
    168             return String.format("Documentation for Android SDK, API %1$d, revision %2$s%3$s",
    169                     mVersion.getApiLevel(),
    170                     getRevision(),
    171                     isObsolete() ? " (Obsolete)" : "");
    172         }
    173     }
    174 
    175     /**
    176      * Returns a long description for an {@link IDescription}.
    177      *
    178      * The long description is whatever the XML contains for the &lt;description&gt; field,
    179      * or the short description if the former is empty.
    180      */
    181     @Override
    182     public String getLongDescription() {
    183         String s = getDescription();
    184         if (s == null || s.length() == 0) {
    185             s = getShortDescription();
    186         }
    187 
    188         if (s.indexOf("revision") == -1) {
    189             s += String.format("\nRevision %1$d%2$s",
    190                     getRevision(),
    191                     isObsolete() ? " (Obsolete)" : "");
    192         }
    193 
    194         return s;
    195     }
    196 
    197     /**
    198      * Computes a potential installation folder if an archive of this package were
    199      * to be installed right away in the given SDK root.
    200      * <p/>
    201      * A "doc" package should always be located in SDK/docs.
    202      *
    203      * @param osSdkRoot The OS path of the SDK root folder.
    204      * @param sdkManager An existing SDK manager to list current platforms and addons.
    205      * @return A new {@link File} corresponding to the directory to use to install this package.
    206      */
    207     @Override
    208     public File getInstallFolder(String osSdkRoot, SdkManager sdkManager) {
    209         return new File(osSdkRoot, SdkConstants.FD_DOCS);
    210     }
    211 
    212     @Override
    213     public boolean sameItemAs(Package pkg) {
    214         // only one doc package so any doc package is the same item
    215         // and we explicitly don't check whether the version is the same.
    216         return pkg instanceof DocPackage;
    217     }
    218 
    219     /**
    220      * {@inheritDoc}
    221      *
    222      * The comparison between doc packages is a bit more complex so we override the default
    223      * implementation.
    224      * <p/>
    225      * Docs are upgrade if they have a higher api, or a similar api but a higher revision.
    226      * <p/>
    227      * What makes this more complex is handling codename.
    228      */
    229     @Override
    230     public UpdateInfo canBeUpdatedBy(Package replacementPackage) {
    231         if (replacementPackage == null) {
    232             return UpdateInfo.INCOMPATIBLE;
    233         }
    234 
    235         // check they are the same item.
    236         if (sameItemAs(replacementPackage) == false) {
    237             return UpdateInfo.INCOMPATIBLE;
    238         }
    239 
    240         DocPackage replacementDoc = (DocPackage)replacementPackage;
    241 
    242         AndroidVersion replacementVersion = replacementDoc.getVersion();
    243 
    244         // the new doc is an update if the api level is higher (no matter the codename on either)
    245         if (replacementVersion.getApiLevel() > mVersion.getApiLevel()) {
    246             return UpdateInfo.UPDATE;
    247         }
    248 
    249         // Check if they're the same exact (api and codename)
    250         if (replacementVersion.equals(mVersion)) {
    251             // exact same version, so check the revision level
    252             if (replacementPackage.getRevision() > this.getRevision()) {
    253                 return UpdateInfo.UPDATE;
    254             }
    255         } else {
    256             // not the same version? we check if they have the same api level and the new one
    257             // is a preview, in which case it's also an update (since preview have the api level
    258             // of the _previous_ version.)
    259             if (replacementVersion.getApiLevel() == mVersion.getApiLevel() &&
    260                     replacementVersion.isPreview()) {
    261                 return UpdateInfo.UPDATE;
    262             }
    263         }
    264 
    265         // not an upgrade but not incompatible either.
    266         return UpdateInfo.NOT_UPDATE;
    267     }
    268 
    269     @Override
    270     public int hashCode() {
    271         final int prime = 31;
    272         int result = super.hashCode();
    273         result = prime * result + ((mVersion == null) ? 0 : mVersion.hashCode());
    274         return result;
    275     }
    276 
    277     @Override
    278     public boolean equals(Object obj) {
    279         if (this == obj) {
    280             return true;
    281         }
    282         if (!super.equals(obj)) {
    283             return false;
    284         }
    285         if (!(obj instanceof DocPackage)) {
    286             return false;
    287         }
    288         DocPackage other = (DocPackage) obj;
    289         if (mVersion == null) {
    290             if (other.mVersion != null) {
    291                 return false;
    292             }
    293         } else if (!mVersion.equals(other.mVersion)) {
    294             return false;
    295         }
    296         return true;
    297     }
    298 }
    299