OSDN Git Service

merge from donut
[android-x86/development.git] / tools / sdkmanager / libs / sdklib / src / com / android / sdklib / AddOnTarget.java
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 int getUsbVendorId() {
212         return mVendorId;
213     }
214
215     public boolean isCompatibleBaseFor(IAndroidTarget target) {
216         // basic test
217         if (target == this) {
218             return true;
219         }
220
221         /*
222          * The method javadoc indicates:
223          * Returns whether the given target is compatible with the receiver.
224          * <p/>A target is considered compatible if applications developed for the receiver can
225          * run on the given target.
226          */
227
228         // The receiver is an add-on. There are 2 big use cases: The add-on has libraries
229         // or the add-on doesn't (in which case we consider it a platform).
230         if (mLibraries.length == 0) {
231             return mBasePlatform.isCompatibleBaseFor(target);
232         } else {
233             // the only targets that can run the receiver are the same add-on in the same or later
234             // versions.
235             // first check: vendor/name
236             if (mVendor.equals(target.getVendor()) == false ||
237                             mName.equals(target.getName()) == false) {
238                 return false;
239             }
240
241             // now check the version. At this point since we checked the add-on part,
242             // we can revert to the basic check on version/codename which are done by the
243             // base platform already.
244             return mBasePlatform.isCompatibleBaseFor(target);
245         }
246
247     }
248
249     public String hashString() {
250         return String.format(ADD_ON_FORMAT, mVendor, mName,
251                 mBasePlatform.getVersion().getApiString());
252     }
253
254     @Override
255     public int hashCode() {
256         return hashString().hashCode();
257     }
258
259     @Override
260     public boolean equals(Object obj) {
261         if (obj instanceof AddOnTarget) {
262             AddOnTarget addon = (AddOnTarget)obj;
263
264             return mVendor.equals(addon.mVendor) && mName.equals(addon.mName) &&
265                 mBasePlatform.getVersion().equals(addon.mBasePlatform.getVersion());
266         }
267
268         return false;
269     }
270
271     /*
272      * Always return +1 if the object we compare to is a platform.
273      * Otherwise, do vendor then name then api version comparison.
274      * (non-Javadoc)
275      * @see java.lang.Comparable#compareTo(java.lang.Object)
276      */
277     public int compareTo(IAndroidTarget target) {
278         if (target.isPlatform()) {
279             return +1;
280         }
281
282         // compare vendor
283         int value = mVendor.compareTo(target.getVendor());
284
285         // if same vendor, compare name
286         if (value == 0) {
287             value = mName.compareTo(target.getName());
288         }
289
290         // if same vendor/name, compare version
291         if (value == 0) {
292             if (getVersion().isPreview() == true) {
293                 value = target.getVersion().isPreview() == true ?
294                         getVersion().getApiString().compareTo(target.getVersion().getApiString()) :
295                         +1; // put the preview at the end.
296             } else {
297                 value = target.getVersion().isPreview() == true ?
298                         -1 : // put the preview at the end :
299                         getVersion().getApiLevel() - target.getVersion().getApiLevel();
300             }
301         }
302
303         return value;
304     }
305
306     // ---- local methods.
307
308     void setSkins(String[] skins, String defaultSkin) {
309         mDefaultSkin = defaultSkin;
310
311         // we mix the add-on and base platform skins
312         HashSet<String> skinSet = new HashSet<String>();
313         skinSet.addAll(Arrays.asList(skins));
314         skinSet.addAll(Arrays.asList(mBasePlatform.getSkins()));
315
316         mSkins = skinSet.toArray(new String[skinSet.size()]);
317     }
318
319     /**
320      * Sets the USB vendor id in the add-on.
321      */
322     void setUsbVendorId(int vendorId) {
323         if (vendorId == 0) {
324             throw new IllegalArgumentException( "VendorId must be > 0");
325         }
326
327         mVendorId = vendorId;
328     }
329 }