Home | History | Annotate | Download | only in sdklib
      1 /*
      2  * Copyright (C) 2008 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;
     18 
     19 import java.io.File;
     20 import java.io.FileFilter;
     21 import java.util.Arrays;
     22 import java.util.HashSet;
     23 import java.util.Map;
     24 import java.util.Map.Entry;
     25 
     26 /**
     27  * Represents an add-on target in the SDK.
     28  * An add-on extends a standard {@link PlatformTarget}.
     29  */
     30 final class AddOnTarget implements IAndroidTarget {
     31     /**
     32      * String to compute hash for add-on targets.
     33      * Format is vendor:name:apiVersion
     34      * */
     35     private final static String ADD_ON_FORMAT = "%s:%s:%s"; //$NON-NLS-1$
     36 
     37     private final static class OptionalLibrary implements IOptionalLibrary {
     38         private final String mJarName;
     39         private final String mJarPath;
     40         private final String mName;
     41         private final String mDescription;
     42 
     43         OptionalLibrary(String jarName, String jarPath, String name, String description) {
     44             mJarName = jarName;
     45             mJarPath = jarPath;
     46             mName = name;
     47             mDescription = description;
     48         }
     49 
     50         public String getJarName() {
     51             return mJarName;
     52         }
     53 
     54         public String getJarPath() {
     55             return mJarPath;
     56         }
     57 
     58         public String getName() {
     59             return mName;
     60         }
     61 
     62         public String getDescription() {
     63             return mDescription;
     64         }
     65     }
     66 
     67     private final String mLocation;
     68     private final PlatformTarget mBasePlatform;
     69     private final String mName;
     70     private final String mVendor;
     71     private final int mRevision;
     72     private final String mDescription;
     73     private String[] mSkins;
     74     private String mDefaultSkin;
     75     private IOptionalLibrary[] mLibraries;
     76     private int mVendorId = NO_USB_ID;
     77 
     78     /**
     79      * Creates a new add-on
     80      * @param location the OS path location of the add-on
     81      * @param name the name of the add-on
     82      * @param vendor the vendor name of the add-on
     83      * @param revision the revision of the add-on
     84      * @param description the add-on description
     85      * @param libMap A map containing the optional libraries. The map key is the fully-qualified
     86      * library name. The value is a 2 string array with the .jar filename, and the description.
     87      * @param basePlatform the platform the add-on is extending.
     88      */
     89     AddOnTarget(String location, String name, String vendor, int revision, String description,
     90             Map<String, String[]> libMap, PlatformTarget basePlatform) {
     91         if (location.endsWith(File.separator) == false) {
     92             location = location + File.separator;
     93         }
     94 
     95         mLocation = location;
     96         mName = name;
     97         mVendor = vendor;
     98         mRevision = revision;
     99         mDescription = description;
    100         mBasePlatform = basePlatform;
    101 
    102         // handle the optional libraries.
    103         if (libMap != null) {
    104             mLibraries = new IOptionalLibrary[libMap.size()];
    105             int index = 0;
    106             for (Entry<String, String[]> entry : libMap.entrySet()) {
    107                 String jarFile = entry.getValue()[0];
    108                 String desc = entry.getValue()[1];
    109                 mLibraries[index++] = new OptionalLibrary(jarFile,
    110                         mLocation + SdkConstants.OS_ADDON_LIBS_FOLDER + jarFile,
    111                         entry.getKey(), desc);
    112             }
    113         }
    114     }
    115 
    116     public String getLocation() {
    117         return mLocation;
    118     }
    119 
    120     public String getName() {
    121         return mName;
    122     }
    123 
    124     public String getVendor() {
    125         return mVendor;
    126     }
    127 
    128     public String getFullName() {
    129         return String.format("%1$s (%2$s)", mName, mVendor);
    130     }
    131 
    132     public String getClasspathName() {
    133         return String.format("%1$s [%2$s]", mName, mBasePlatform.getName());
    134     }
    135 
    136     public String getDescription() {
    137         return mDescription;
    138     }
    139 
    140     public AndroidVersion getVersion() {
    141         // this is always defined by the base platform
    142         return mBasePlatform.getVersion();
    143     }
    144 
    145     public String getVersionName() {
    146         return mBasePlatform.getVersionName();
    147     }
    148 
    149     public int getRevision() {
    150         return mRevision;
    151     }
    152 
    153     public boolean isPlatform() {
    154         return false;
    155     }
    156 
    157     public IAndroidTarget getParent() {
    158         return mBasePlatform;
    159     }
    160 
    161     public String getPath(int pathId) {
    162         switch (pathId) {
    163             case IMAGES:
    164                 return mLocation + SdkConstants.OS_IMAGES_FOLDER;
    165             case SKINS:
    166                 return mLocation + SdkConstants.OS_SKINS_FOLDER;
    167             case DOCS:
    168                 return mLocation + SdkConstants.FD_DOCS + File.separator
    169                         + SdkConstants.FD_DOCS_REFERENCE;
    170             case SAMPLES:
    171                 // only return the add-on samples folder if there is actually a sample (or more)
    172                 File sampleLoc = new File(mLocation, SdkConstants.FD_SAMPLES);
    173                 if (sampleLoc.isDirectory()) {
    174                     File[] files = sampleLoc.listFiles(new FileFilter() {
    175                         public boolean accept(File pathname) {
    176                             return pathname.isDirectory();
    177                         }
    178 
    179                     });
    180                     if (files != null && files.length > 0) {
    181                         return sampleLoc.getAbsolutePath();
    182                     }
    183                 }
    184                 // INTENDED FALL-THROUGH
    185             default :
    186                 return mBasePlatform.getPath(pathId);
    187         }
    188     }
    189 
    190     public String[] getSkins() {
    191         return mSkins;
    192     }
    193 
    194     public String getDefaultSkin() {
    195         return mDefaultSkin;
    196     }
    197 
    198     public IOptionalLibrary[] getOptionalLibraries() {
    199         return mLibraries;
    200     }
    201 
    202     /**
    203      * Returns the list of libraries of the underlying platform.
    204      *
    205      * {@inheritDoc}
    206      */
    207     public String[] getPlatformLibraries() {
    208         return mBasePlatform.getPlatformLibraries();
    209     }
    210 
    211     public String getProperty(String name) {
    212         return mBasePlatform.getProperty(name);
    213     }
    214 
    215     public Integer getProperty(String name, Integer defaultValue) {
    216         return mBasePlatform.getProperty(name, defaultValue);
    217     }
    218 
    219     public Boolean getProperty(String name, Boolean defaultValue) {
    220         return mBasePlatform.getProperty(name, defaultValue);
    221     }
    222 
    223     public Map<String, String> getProperties() {
    224         return mBasePlatform.getProperties();
    225     }
    226 
    227     public int getUsbVendorId() {
    228         return mVendorId;
    229     }
    230 
    231     public boolean canRunOn(IAndroidTarget target) {
    232         // basic test
    233         if (target == this) {
    234             return true;
    235         }
    236 
    237         /*
    238          * The method javadoc indicates:
    239          * Returns whether the given target is compatible with the receiver.
    240          * <p/>A target is considered compatible if applications developed for the receiver can
    241          * run on the given target.
    242          */
    243 
    244         // The receiver is an add-on. There are 2 big use cases: The add-on has libraries
    245         // or the add-on doesn't (in which case we consider it a platform).
    246         if (mLibraries == null || mLibraries.length == 0) {
    247             return mBasePlatform.canRunOn(target);
    248         } else {
    249             // the only targets that can run the receiver are the same add-on in the same or later
    250             // versions.
    251             // first check: vendor/name
    252             if (mVendor.equals(target.getVendor()) == false ||
    253                             mName.equals(target.getName()) == false) {
    254                 return false;
    255             }
    256 
    257             // now check the version. At this point since we checked the add-on part,
    258             // we can revert to the basic check on version/codename which are done by the
    259             // base platform already.
    260             return mBasePlatform.canRunOn(target);
    261         }
    262 
    263     }
    264 
    265     public String hashString() {
    266         return String.format(ADD_ON_FORMAT, mVendor, mName,
    267                 mBasePlatform.getVersion().getApiString());
    268     }
    269 
    270     @Override
    271     public int hashCode() {
    272         return hashString().hashCode();
    273     }
    274 
    275     @Override
    276     public boolean equals(Object obj) {
    277         if (obj instanceof AddOnTarget) {
    278             AddOnTarget addon = (AddOnTarget)obj;
    279 
    280             return mVendor.equals(addon.mVendor) && mName.equals(addon.mName) &&
    281                 mBasePlatform.getVersion().equals(addon.mBasePlatform.getVersion());
    282         }
    283 
    284         return false;
    285     }
    286 
    287     /*
    288      * Order by API level (preview/n count as between n and n+1).
    289      * At the same API level, order as: Platform first, then add-on ordered by vendor and then name
    290      * (non-Javadoc)
    291      * @see java.lang.Comparable#compareTo(java.lang.Object)
    292      */
    293     public int compareTo(IAndroidTarget target) {
    294         // quick check.
    295         if (this == target) {
    296             return 0;
    297         }
    298 
    299         int versionDiff = getVersion().compareTo(target.getVersion());
    300 
    301         // only if the version are the same do we care about platform/add-ons.
    302         if (versionDiff == 0) {
    303             // platforms go before add-ons.
    304             if (target.isPlatform()) {
    305                 return +1;
    306             } else {
    307                 AddOnTarget targetAddOn = (AddOnTarget)target;
    308 
    309                 // both are add-ons of the same version. Compare per vendor then by name
    310                 int vendorDiff = mVendor.compareTo(targetAddOn.mVendor);
    311                 if (vendorDiff == 0) {
    312                     return mName.compareTo(targetAddOn.mName);
    313                 } else {
    314                     return vendorDiff;
    315                 }
    316             }
    317 
    318         }
    319 
    320         return versionDiff;
    321     }
    322 
    323     // ---- local methods.
    324 
    325     void setSkins(String[] skins, String defaultSkin) {
    326         mDefaultSkin = defaultSkin;
    327 
    328         // we mix the add-on and base platform skins
    329         HashSet<String> skinSet = new HashSet<String>();
    330         skinSet.addAll(Arrays.asList(skins));
    331         skinSet.addAll(Arrays.asList(mBasePlatform.getSkins()));
    332 
    333         mSkins = skinSet.toArray(new String[skinSet.size()]);
    334     }
    335 
    336     /**
    337      * Sets the USB vendor id in the add-on.
    338      */
    339     void setUsbVendorId(int vendorId) {
    340         if (vendorId == 0) {
    341             throw new IllegalArgumentException( "VendorId must be > 0");
    342         }
    343 
    344         mVendorId = vendorId;
    345     }
    346 }
    347