1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.codehaus.mojo.javascript.titanium;
15
16 import org.apache.maven.plugin.MojoExecutionException;
17 import org.apache.maven.plugin.logging.Log;
18 import org.codehaus.mojo.javascript.TitaniumPackageMojo;
19 import org.codehaus.mojo.javascript.TitaniumSettings;
20 import org.codehaus.mojo.javascript.VirtualDevice;
21
22 import java.io.*;
23 import java.util.ArrayList;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.regex.Matcher;
27 import java.util.regex.Pattern;
28
29
30
31
32
33 public class TitaniumUtils {
34
35
36
37 public static final String ENV_ANDROID_HOME = "ANDROID_HOME";
38
39
40
41
42
43
44 public static String getAndroidHome() throws MojoExecutionException {
45 final String androidHome = System.getenv(ENV_ANDROID_HOME);
46 if (androidHome == null || androidHome.isEmpty()) {
47 throw new MojoExecutionException("No Android SDK path could be found. You may configure it by setting the "
48 + ENV_ANDROID_HOME + " environment variable.");
49 }
50 final File androidHomeFile = new File(androidHome);
51 if (!androidHomeFile.exists() || !androidHomeFile.isDirectory()) {
52 throw new MojoExecutionException("The android SDK path is not valid");
53 }
54 return androidHome;
55 }
56
57
58
59
60
61
62
63 public static List<Integer> getAvailableAndroidPlatformVersions(File androidSdkHome) throws MojoExecutionException {
64 if (androidSdkHome == null) {
65 throw new MojoExecutionException("No android SDK home folder specified");
66 }
67 if (!androidSdkHome.exists()) {
68 throw new MojoExecutionException("The specified android SDK home folder doesn't exist: "
69 + androidSdkHome.getAbsolutePath());
70 }
71 if (!androidSdkHome.isDirectory()) {
72 throw new MojoExecutionException("The specified android sdk location is not a folder: "
73 + androidSdkHome.getAbsolutePath());
74 }
75 File sdk = new File(androidSdkHome, "platforms");
76 Pattern pattern = Pattern.compile("android-([0-9]+)");
77 List<Integer> result = new ArrayList<Integer>();
78 File[] sdkFiles = sdk.listFiles();
79 if (sdkFiles != null) {
80 for (File file : sdkFiles) {
81 if (file.isDirectory() && file.getName().startsWith("android-")) {
82 Matcher matcher = pattern.matcher(file.getName());
83 if (matcher.find()) {
84 result.add(new Integer(matcher.group(1)));
85 }
86 }
87 }
88 }
89 Collections.sort(result);
90 return result;
91 }
92
93
94
95
96
97
98
99 public static String getLatestAndroidPlatformVersion(File androidSdkHome) throws MojoExecutionException {
100 List<Integer> platforms = getAvailableAndroidPlatformVersions(androidSdkHome);
101 Integer lastVersion = platforms.get(platforms.size() - 1);
102 return lastVersion.toString();
103 }
104
105 public static boolean isAndroidEmulatorRunning(File androidSdkHome) throws IOException {
106 if (androidSdkHome == null) {
107 return false;
108 }
109
110 File adb = new File(androidSdkHome, "platform-tools" + File.separator + "adb");
111 if (!adb.exists()) {
112 return false;
113 }
114
115 boolean isEmulatorRunning = false;
116
117 ProcessBuilder pb = new ProcessBuilder(adb.getAbsolutePath(), "devices");
118 pb.redirectErrorStream(true);
119 Process p = pb.start();
120
121 BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
122 String line = null;
123
124 while ((line = reader.readLine()) != null) {
125 line = line.trim();
126 if (line.startsWith("List of devices")) {
127 continue;
128 }
129 else if (line.startsWith("emulator-")) {
130 String[] tokens = line.split("\\s");
131 String name = tokens[0];
132 String status = tokens[1];
133 int port = Integer.parseInt(name.substring(name.indexOf("-") + 1));
134 if (status.equals("device") && port == 5560) {
135 isEmulatorRunning = true;
136 }
137 }
138 }
139
140 return isEmulatorRunning;
141
142 }
143
144
145
146
147
148
149
150
151
152
153
154 public static boolean createAvd(File androidSdkHome,
155 String avdId, String skin, Log log) throws MojoExecutionException {
156 String avdName = "titanium_" + avdId + "_"
157 + skin;
158
159 String homeDir = System.getProperty("user.home");
160 File avdDir = new File(homeDir, ".android" + File.separator + "avd"
161 + File.separator + avdName + ".avd");
162
163 if (!avdDir.exists()) {
164 File androidCmd = new File(androidSdkHome, "tools" + File.separator + "android");
165 File sdCard = new File(homeDir, ".titanium" + File.separatorChar + avdName + ".sdcard");
166
167 createSdCard(androidSdkHome, sdCard, "64M");
168 ProcessBuilder pb = new ProcessBuilder(androidCmd.getAbsolutePath(), "--verbose",
169 "create", "avd",
170 "-n", avdName, "-t", avdId,
171 "-s", skin,
172 "--force",
173 "--sdcard", sdCard.getAbsolutePath());
174
175 try {
176 Process p = pb.start();
177 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
178
179
180 log.info("Sending no");
181 writer.write("no");
182 writer.write("\n");
183 writer.flush();
184 TitaniumBuilder.logProcess(p, log);
185 p.waitFor();
186 } catch (IOException ioe) {
187 throw new MojoExecutionException("Error while creating avd", ioe);
188 } catch (InterruptedException ie) {
189 throw new MojoExecutionException("Error while creating avd", ie);
190 }
191 return true;
192 } else {
193 return false;
194 }
195 }
196
197
198
199
200
201
202
203
204
205 private static void createSdCard(File androidSdkHome, File sdCard, String size)
206 throws MojoExecutionException {
207 File mkSdCardCmd = new File(androidSdkHome, "tools" + File.separatorChar + "mksdcard");
208
209 ProcessBuilder pb = new ProcessBuilder(mkSdCardCmd.getAbsolutePath(),
210 size, sdCard.getAbsolutePath());
211
212 try {
213 pb.start().waitFor();
214 } catch (Throwable t) {
215 throw new MojoExecutionException("Error while creating AVD SDCard", t);
216 }
217 }
218
219 private static boolean isWindows() {
220 return isOs("win");
221 }
222
223 private static boolean isMac() {
224 return isOs("mac");
225 }
226
227 private static boolean isUnix() {
228 return (isOs("nix") || isOs("nux"));
229 }
230
231 private static boolean isOs(final String osName) {
232 final String os = System.getProperty("os.name").toLowerCase();
233 return (os.indexOf(osName) >= 0);
234 }
235
236 public static String getOsClassifier() {
237 if (isWindows()) {
238 return "win32";
239 } else if (isMac()) {
240 return "osx";
241 } else if (isUnix()) {
242 return "linux";
243 } else {
244 return "";
245 }
246 }
247
248 public static String getTitaniumSdkPath(String version) {
249 final String homeFolder = System.getProperty("user.home");
250 String sdkPath = null;
251 File sdkFile = null;
252
253 if (isMac()) {
254 sdkPath = homeFolder + "/Library/Application Support/Titanium/mobilesdk/osx/" + version + "/";
255 sdkFile = new File(sdkPath);
256 if (!sdkFile.exists()) {
257 sdkPath = "/Library/Application Support/Titanium/mobilesdk/osx/" + version + "/";
258 sdkFile = new File(sdkPath);
259 if (!sdkFile.exists()) {
260 sdkPath = null;
261 }
262 }
263 } else if (isWindows()) {
264 final String userProfileFolder = System.getenv("ALLUSERSPROFILE");
265 sdkPath = userProfileFolder + "\\Titanium\\mobilesdk\\win32\\" + version + "\\";
266 sdkFile = new File(sdkPath);
267 if (!sdkFile.exists()) {
268 sdkPath = "C:\\Documents and Settings\\All Users\\Application Data\\Titanium\\mobilesdk\\win32\\" + version + "\\";
269 sdkFile = new File(sdkPath);
270 if (!sdkFile.exists()) {
271 sdkPath = null;
272 }
273 }
274 } else if (isUnix()) {
275 sdkPath = homeFolder + "/.titanium/mobilesdk/linux/" + version + "/";
276 sdkFile = new File(sdkPath);
277 if (!sdkFile.exists()) {
278 sdkPath = null;
279 }
280 }
281
282 return sdkPath;
283 }
284
285 public static String getTitaniumArtifactSdkPath(String version, File targetDir) {
286 File sdkPath = new File(targetDir, "mobilesdk" + File.separator
287 + TitaniumUtils.getOsClassifier() + File.separator
288 + version);
289
290 if (sdkPath.exists()) {
291 return sdkPath.getAbsolutePath();
292 } else {
293 return null;
294 }
295 }
296
297 public static boolean isAndroidVersionValid(File androidSdkHome, String version)
298 throws MojoExecutionException {
299 List<Integer> versions = getAvailableAndroidPlatformVersions(androidSdkHome);
300 for (Integer v : versions) {
301 if (v.toString().equals(version)) {
302 return true;
303 }
304 }
305 return false;
306 }
307
308 public static void checkVirtualDevice(String platform, TitaniumSettings settings, VirtualDevice virtualDevice) throws MojoExecutionException {
309 if (platform.equals("android")) {
310 if (virtualDevice.getAndroidAPI() == null) {
311 virtualDevice.setAndroidAPI(getLatestAndroidPlatformVersion(settings.getAndroidSdk()));
312 } else {
313 if (!isAndroidVersionValid(settings.getAndroidSdk(), virtualDevice.getAndroidAPI())) {
314 throw new MojoExecutionException("The specified android version is not present");
315 }
316 }
317
318 if (virtualDevice.getSkin() == null) {
319 if (new Integer(virtualDevice.getAndroidAPI()).intValue() < 10) {
320 virtualDevice.setSkin("HVGA");
321 } else {
322 virtualDevice.setSkin("WXGA");
323 }
324 }
325 } else if (platform.equals("iphone")) {
326 if (virtualDevice.getFamily() == null) {
327 virtualDevice.setFamily("iphone");
328 }
329 } else if (platform.equals("ipad")) {
330 if (virtualDevice.getFamily() == null) {
331 virtualDevice.setFamily("ipad");
332 }
333 } else if (platform.equals("universal")) {
334 if (virtualDevice.getFamily() == null) {
335 virtualDevice.setFamily("iphone");
336 }
337 }
338 }
339
340 public static boolean isIphoneVersionValid(String version) {
341 List<String> platforms = listAvailableIosPlatformVersions();
342 for (String platform : platforms) {
343 if (platform.equals(version)) {
344 return true;
345 }
346 }
347 return false;
348 }
349
350 public static List<String> listAvailableIosPlatformVersions() {
351 List<String> results = new ArrayList<String>();
352 try {
353 ProcessBuilder pb = new ProcessBuilder("xcodebuild", "-showsdks");
354 pb.redirectErrorStream(true);
355 Process p = pb.start();
356 BufferedReader reader = new BufferedReader(new InputStreamReader(p.getInputStream()));
357 String line = null;
358 Pattern pattern = Pattern.compile("-sdk iphoneos(([0-9]+.?)+)");
359 while ((line = reader.readLine()) != null) {
360 Matcher m = pattern.matcher(line);
361 while (m.find()) {
362 results.add(m.group(1));
363 }
364 }
365 } catch (Throwable t) {
366 }
367 return results;
368 }
369
370 public static String getLatestIosPlatformVersion() {
371 List<String> platforms = listAvailableIosPlatformVersions();
372 if (!platforms.isEmpty()) {
373 return platforms.get(0);
374 }
375 return "4.3";
376 }
377 }