• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.IAndroidTarget;
20 import com.android.sdklib.ISdkLog;
21 import com.android.sdklib.SdkConstants;
22 import com.android.sdklib.SdkManager;
23 import com.android.sdklib.internal.repository.Archive.Arch;
24 import com.android.sdklib.internal.repository.Archive.Os;
25 
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.HashSet;
31 import java.util.Properties;
32 import java.util.Set;
33 
34 /**
35  * Scans a local SDK to find which packages are currently installed.
36  */
37 public class LocalSdkParser {
38 
39     static final String SOURCE_PROPERTIES = "source.properties";  //$NON-NLS-1$
40     private Package[] mPackages;
41 
LocalSdkParser()42     public LocalSdkParser() {
43         // pass
44     }
45 
46     /**
47      * Returns the packages found by the last call to
48      * {@link #parseSdk(String, SdkManager, ISdkLog)}.
49      * <p/>
50      * This returns initially returns null.
51      * Once the parseSdk() method has been called, this returns a possibly empty but non-null array.
52      */
getPackages()53     public Package[] getPackages() {
54         return mPackages;
55     }
56 
57     /**
58      * Clear the internal packages list. After this call, {@link #getPackages()} will return
59      * null till {@link #parseSdk(String, SdkManager, ISdkLog)} is called.
60      */
clearPackages()61     public void clearPackages() {
62         mPackages = null;
63     }
64 
65     /**
66      * Scan the give SDK to find all the packages already installed at this location.
67      * <p/>
68      * Store the packages internally. You can use {@link #getPackages()} to retrieve them
69      * at any time later.
70      *
71      * @param osSdkRoot The path to the SDK folder.
72      * @param sdkManager An existing SDK manager to list current platforms and addons.
73      * @param log An SDK logger object.
74      * @return The packages found. Can be retrieved later using {@link #getPackages()}.
75      */
parseSdk(String osSdkRoot, SdkManager sdkManager, ISdkLog log)76     public Package[] parseSdk(String osSdkRoot, SdkManager sdkManager, ISdkLog log) {
77         ArrayList<Package> packages = new ArrayList<Package>();
78         HashSet<File> visited = new HashSet<File>();
79 
80         File dir = new File(osSdkRoot, SdkConstants.FD_DOCS);
81         Package pkg = scanDoc(dir, log);
82         if (pkg != null) {
83             packages.add(pkg);
84             visited.add(dir);
85         }
86 
87         dir = new File(osSdkRoot, SdkConstants.FD_TOOLS);
88         pkg = scanTools(dir, log);
89         if (pkg != null) {
90             packages.add(pkg);
91             visited.add(dir);
92         }
93 
94         // for platforms and add-ons, rely on the SdkManager parser
95         for(IAndroidTarget target : sdkManager.getTargets()) {
96 
97             Properties props = parseProperties(new File(target.getLocation(), SOURCE_PROPERTIES));
98 
99             try {
100                 if (target.isPlatform()) {
101                     pkg = new PlatformPackage(target, props);
102                 } else {
103                     pkg = new AddonPackage(target, props);
104                 }
105             } catch (Exception e) {
106                 log.error(e, null);
107             }
108 
109             if (pkg != null) {
110                 packages.add(pkg);
111                 visited.add(new File(target.getLocation()));
112             }
113         }
114 
115         scanExtra(osSdkRoot, visited, packages, log);
116 
117         mPackages = packages.toArray(new Package[packages.size()]);
118         return mPackages;
119     }
120 
121     /**
122      * Find any other directory what we haven't successfully visited and
123      * assume they contain extra packages.
124      * @param log
125      */
scanExtra(String osSdkRoot, HashSet<File> visited, ArrayList<Package> packages, ISdkLog log)126     private void scanExtra(String osSdkRoot,
127             HashSet<File> visited,
128             ArrayList<Package> packages,
129             ISdkLog log) {
130         File root = new File(osSdkRoot);
131         for (File dir : root.listFiles()) {
132             if (dir.isDirectory() && !visited.contains(dir)) {
133 
134                 Properties props = parseProperties(new File(dir, SOURCE_PROPERTIES));
135                 if (props != null) {
136                     try {
137                         ExtraPackage pkg = new ExtraPackage(
138                                 null,                       //source
139                                 props,                      //properties
140                                 dir.getName(),              //path
141                                 0,                          //revision
142                                 null,                       //license
143                                 "Tools",                    //description
144                                 null,                       //descUrl
145                                 Os.getCurrentOs(),          //archiveOs
146                                 Arch.getCurrentArch(),      //archiveArch
147                                 dir.getPath()               //archiveOsPath
148                                 );
149 
150                         // We only accept this as an extra package if it has a valid local path.
151                         if (pkg.isPathValid()) {
152                             packages.add(pkg);
153                         }
154                     } catch (Exception e) {
155                         log.error(e, null);
156                     }
157                 }
158             }
159         }
160     }
161 
162     /**
163      * Try to find a tools package at the given location.
164      * Returns null if not found.
165      */
scanTools(File toolFolder, ISdkLog log)166     private Package scanTools(File toolFolder, ISdkLog log) {
167         // Can we find some properties?
168         Properties props = parseProperties(new File(toolFolder, SOURCE_PROPERTIES));
169 
170         // We're not going to check that all tools are present. At the very least
171         // we should expect to find adb, android and an emulator adapted to the current OS.
172         Set<String> names = new HashSet<String>();
173         for (File file : toolFolder.listFiles()) {
174             names.add(file.getName());
175         }
176         if (!names.contains(SdkConstants.FN_ADB) ||
177                 !names.contains(SdkConstants.androidCmdName()) ||
178                 !names.contains(SdkConstants.FN_EMULATOR)) {
179             return null;
180         }
181 
182         // Create are package. use the properties if we found any.
183         try {
184             ToolPackage pkg = new ToolPackage(
185                     null,                       //source
186                     props,                      //properties
187                     0,                          //revision
188                     null,                       //license
189                     "Tools",                    //description
190                     null,                       //descUrl
191                     Os.getCurrentOs(),          //archiveOs
192                     Arch.getCurrentArch(),      //archiveArch
193                     toolFolder.getPath()        //archiveOsPath
194                     );
195 
196             return pkg;
197         } catch (Exception e) {
198             log.error(e, null);
199         }
200         return null;
201     }
202 
203     /**
204      * Try to find a docs package at the given location.
205      * Returns null if not found.
206      */
scanDoc(File docFolder, ISdkLog log)207     private Package scanDoc(File docFolder, ISdkLog log) {
208         // Can we find some properties?
209         Properties props = parseProperties(new File(docFolder, SOURCE_PROPERTIES));
210 
211         // To start with, a doc folder should have an "index.html" to be acceptable.
212         // We don't actually check the content of the file.
213         if (new File(docFolder, "index.html").isFile()) {
214             try {
215                 DocPackage pkg = new DocPackage(
216                         null,                       //source
217                         props,                      //properties
218                         0,                          //apiLevel
219                         null,                       //codename
220                         0,                          //revision
221                         null,                       //license
222                         null,                       //description
223                         null,                       //descUrl
224                         Os.getCurrentOs(),          //archiveOs
225                         Arch.getCurrentArch(),      //archiveArch
226                         docFolder.getPath()         //archiveOsPath
227                         );
228 
229                 return pkg;
230             } catch (Exception e) {
231                 log.error(e, null);
232             }
233         }
234 
235         return null;
236     }
237 
238     /**
239      * Parses the given file as properties file if it exists.
240      * Returns null if the file does not exist, cannot be parsed or has no properties.
241      */
parseProperties(File propsFile)242     private Properties parseProperties(File propsFile) {
243         FileInputStream fis = null;
244         try {
245             if (propsFile.exists()) {
246                 fis = new FileInputStream(propsFile);
247 
248                 Properties props = new Properties();
249                 props.load(fis);
250 
251                 // To be valid, there must be at least one property in it.
252                 if (props.size() > 0) {
253                     return props;
254                 }
255             }
256 
257         } catch (IOException e) {
258             e.printStackTrace();
259         } finally {
260             if (fis != null) {
261                 try {
262                     fis.close();
263                 } catch (IOException e) {
264                 }
265             }
266         }
267         return null;
268     }
269 }
270