calabash 1.2.1 → 1.9.9.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +39 -0
  3. data/LICENSE +204 -21
  4. data/README.md +36 -6
  5. data/VERSIONING.md +16 -0
  6. data/bin/calabash +95 -0
  7. data/lib/calabash.rb +185 -1
  8. data/lib/calabash/android.rb +64 -0
  9. data/lib/calabash/android/adb.rb +277 -0
  10. data/lib/calabash/android/application.rb +110 -0
  11. data/lib/calabash/android/build.rb +12 -0
  12. data/lib/calabash/android/build/application.rb +13 -0
  13. data/lib/calabash/android/build/build_error.rb +11 -0
  14. data/lib/calabash/android/build/builder.rb +119 -0
  15. data/lib/calabash/android/build/java_keystore.rb +177 -0
  16. data/lib/calabash/android/build/resigner.rb +56 -0
  17. data/lib/calabash/android/build/test_server.rb +27 -0
  18. data/lib/calabash/android/console_helpers.rb +44 -0
  19. data/lib/calabash/android/cucumber.rb +3 -0
  20. data/lib/calabash/android/device.rb +965 -0
  21. data/lib/calabash/android/environment.rb +470 -0
  22. data/lib/calabash/android/gestures.rb +369 -0
  23. data/lib/calabash/android/interactions.rb +45 -0
  24. data/lib/calabash/android/lib/.irbrc +55 -0
  25. data/lib/calabash/android/lib/AndroidManifest.xml +51 -0
  26. data/lib/calabash/android/lib/TestServer.apk +0 -0
  27. data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5 +0 -0
  28. data/lib/calabash/android/lib/calmd5/arm64-v8a/calmd5-pie +0 -0
  29. data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5 +0 -0
  30. data/lib/calabash/android/lib/calmd5/armeabi-v7a/calmd5-pie +0 -0
  31. data/lib/calabash/android/lib/calmd5/armeabi/calmd5 +0 -0
  32. data/lib/calabash/android/lib/calmd5/armeabi/calmd5-pie +0 -0
  33. data/lib/calabash/android/lib/calmd5/mips/calmd5 +0 -0
  34. data/lib/calabash/android/lib/calmd5/mips/calmd5-pie +0 -0
  35. data/lib/calabash/android/lib/calmd5/mips64/calmd5 +0 -0
  36. data/lib/calabash/android/lib/calmd5/mips64/calmd5-pie +0 -0
  37. data/lib/calabash/android/lib/calmd5/x86/calmd5 +0 -0
  38. data/lib/calabash/android/lib/calmd5/x86/calmd5-pie +0 -0
  39. data/lib/calabash/android/lib/calmd5/x86_64/calmd5 +0 -0
  40. data/lib/calabash/android/lib/calmd5/x86_64/calmd5-pie +0 -0
  41. data/lib/calabash/android/lib/screenshot_taker.jar +0 -0
  42. data/lib/calabash/android/life_cycle.rb +37 -0
  43. data/lib/calabash/android/orientation.rb +30 -0
  44. data/lib/calabash/android/physical_buttons.rb +39 -0
  45. data/lib/calabash/android/screenshot.rb +9 -0
  46. data/lib/calabash/android/scroll.rb +5 -0
  47. data/lib/calabash/android/server.rb +10 -0
  48. data/lib/calabash/android/text.rb +54 -0
  49. data/lib/calabash/application.rb +74 -0
  50. data/lib/calabash/cli.rb +12 -0
  51. data/lib/calabash/cli/build.rb +33 -0
  52. data/lib/calabash/cli/console.rb +90 -0
  53. data/lib/calabash/cli/generate.rb +110 -0
  54. data/lib/calabash/cli/helpers.rb +130 -0
  55. data/lib/calabash/cli/resign.rb +33 -0
  56. data/lib/calabash/cli/run.rb +99 -0
  57. data/lib/calabash/cli/setup_keystore.rb +39 -0
  58. data/lib/calabash/color.rb +32 -0
  59. data/lib/calabash/console_helpers.rb +90 -0
  60. data/lib/calabash/defaults.rb +56 -0
  61. data/lib/calabash/device.rb +401 -0
  62. data/lib/calabash/environment.rb +75 -0
  63. data/lib/calabash/gestures.rb +384 -0
  64. data/lib/calabash/http.rb +8 -0
  65. data/lib/calabash/http/error.rb +15 -0
  66. data/lib/calabash/http/request.rb +42 -0
  67. data/lib/calabash/http/retriable_client.rb +156 -0
  68. data/lib/calabash/interactions.rb +105 -0
  69. data/lib/calabash/ios.rb +37 -0
  70. data/lib/calabash/ios/application.rb +119 -0
  71. data/lib/calabash/ios/conditions.rb +79 -0
  72. data/lib/calabash/ios/console_helpers.rb +72 -0
  73. data/lib/calabash/ios/device.rb +24 -0
  74. data/lib/calabash/ios/device/device_implementation.rb +779 -0
  75. data/lib/calabash/ios/device/gestures_mixin.rb +167 -0
  76. data/lib/calabash/ios/device/keyboard_mixin.rb +133 -0
  77. data/lib/calabash/ios/device/physical_device_mixin.rb +266 -0
  78. data/lib/calabash/ios/device/rotation_mixin.rb +124 -0
  79. data/lib/calabash/ios/device/routes/backdoor_route_mixin.rb +86 -0
  80. data/lib/calabash/ios/device/routes/condition_route_mixin.rb +62 -0
  81. data/lib/calabash/ios/device/routes/error.rb +8 -0
  82. data/lib/calabash/ios/device/routes/handle_route_mixin.rb +102 -0
  83. data/lib/calabash/ios/device/routes/map_route_mixin.rb +38 -0
  84. data/lib/calabash/ios/device/routes/playback_route_mixin.rb +70 -0
  85. data/lib/calabash/ios/device/routes/response_parser.rb +48 -0
  86. data/lib/calabash/ios/device/routes/uia_route_mixin.rb +238 -0
  87. data/lib/calabash/ios/device/runtime_attributes.rb +184 -0
  88. data/lib/calabash/ios/device/status_bar_mixin.rb +17 -0
  89. data/lib/calabash/ios/device/text_mixin.rb +19 -0
  90. data/lib/calabash/ios/device/uia_keyboard_mixin.rb +188 -0
  91. data/lib/calabash/ios/device/uia_mixin.rb +12 -0
  92. data/lib/calabash/ios/environment.rb +41 -0
  93. data/lib/calabash/ios/interactions.rb +10 -0
  94. data/lib/calabash/ios/lib/.irbrc +55 -0
  95. data/lib/calabash/ios/lib/recordings/rotate_left_home_down_ipad.base64 +2 -0
  96. data/lib/calabash/ios/lib/recordings/rotate_left_home_down_iphone.base64 +2 -0
  97. data/lib/calabash/ios/lib/recordings/rotate_left_home_left_ipad.base64 +2 -0
  98. data/lib/calabash/ios/lib/recordings/rotate_left_home_left_iphone.base64 +2 -0
  99. data/lib/calabash/ios/lib/recordings/rotate_left_home_right_ipad.base64 +2 -0
  100. data/lib/calabash/ios/lib/recordings/rotate_left_home_right_iphone.base64 +2 -0
  101. data/lib/calabash/ios/lib/recordings/rotate_left_home_up_ipad.base64 +2 -0
  102. data/lib/calabash/ios/lib/recordings/rotate_left_home_up_iphone.base64 +2 -0
  103. data/lib/calabash/ios/lib/recordings/rotate_right_home_down_ipad.base64 +2 -0
  104. data/lib/calabash/ios/lib/recordings/rotate_right_home_down_iphone.base64 +2 -0
  105. data/lib/calabash/ios/lib/recordings/rotate_right_home_left_ipad.base64 +2 -0
  106. data/lib/calabash/ios/lib/recordings/rotate_right_home_left_iphone.base64 +2 -0
  107. data/lib/calabash/ios/lib/recordings/rotate_right_home_right_ipad.base64 +2 -0
  108. data/lib/calabash/ios/lib/recordings/rotate_right_home_right_iphone.base64 +2 -0
  109. data/lib/calabash/ios/lib/recordings/rotate_right_home_up_ipad.base64 +2 -0
  110. data/lib/calabash/ios/lib/recordings/rotate_right_home_up_iphone.base64 +2 -0
  111. data/lib/calabash/ios/orientation.rb +117 -0
  112. data/lib/calabash/ios/scroll.rb +504 -0
  113. data/lib/calabash/ios/server.rb +73 -0
  114. data/lib/calabash/ios/text.rb +248 -0
  115. data/lib/calabash/ios/uia.rb +24 -0
  116. data/lib/calabash/lib/skeleton/config/cucumber.yml +6 -0
  117. data/lib/calabash/lib/skeleton/features/sample.feature +5 -0
  118. data/lib/calabash/lib/skeleton/features/step_definitions/calabash_steps.rb +29 -0
  119. data/lib/calabash/lib/skeleton/features/support/env.rb +54 -0
  120. data/lib/calabash/lib/skeleton/features/support/hooks.rb +83 -0
  121. data/lib/calabash/life_cycle.rb +111 -0
  122. data/lib/calabash/location.rb +51 -0
  123. data/lib/calabash/logger.rb +87 -0
  124. data/lib/calabash/orientation.rb +84 -0
  125. data/lib/calabash/page.rb +35 -0
  126. data/lib/calabash/patch.rb +14 -0
  127. data/lib/calabash/patch/array.rb +16 -0
  128. data/lib/calabash/patch/run_loop.rb +90 -0
  129. data/lib/calabash/query.rb +160 -0
  130. data/lib/calabash/query_result.rb +85 -0
  131. data/lib/calabash/screenshot.rb +89 -0
  132. data/lib/calabash/server.rb +16 -0
  133. data/lib/calabash/text.rb +76 -0
  134. data/lib/calabash/utility.rb +58 -0
  135. data/lib/calabash/version.rb +3 -1
  136. data/lib/calabash/wait.rb +474 -0
  137. metadata +462 -24
@@ -0,0 +1,470 @@
1
+ require 'rexml/document'
2
+ require 'timeout'
3
+ require 'luffa'
4
+ require 'timeout'
5
+
6
+ if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
7
+ require 'win32/registry'
8
+ end
9
+
10
+ module Calabash
11
+ module Android
12
+ class Environment < Calabash::Environment
13
+ class InvalidEnvironmentError < RuntimeError; end
14
+ class InvalidJavaSDKHome < RuntimeError; end
15
+
16
+ private
17
+
18
+ def self.set_android_dependencies(android_dependencies)
19
+ @@android_dependencies = android_dependencies
20
+ end
21
+
22
+ def self.set_java_dependencies(java_dependencies)
23
+ @@java_dependencies = java_dependencies
24
+ end
25
+
26
+ def self.android_dependencies(key)
27
+ if @@android_dependencies.has_key?(key)
28
+ file = @@android_dependencies[key]
29
+
30
+ unless File.exists?(file)
31
+ raise "No such file '#{file}'"
32
+ end
33
+
34
+ file
35
+ else
36
+ raise "No such dependency '#{key}'"
37
+ end
38
+ end
39
+
40
+ def self.java_dependencies(key)
41
+ if key == :ant_path
42
+ ant_executable
43
+ elsif @@java_dependencies.has_key?(key)
44
+ file = @@java_dependencies[key]
45
+
46
+ unless File.exists?(file)
47
+ raise "No such file '#{file}'"
48
+ end
49
+
50
+ file
51
+ else
52
+ raise "No such dependency '#{key}'"
53
+ end
54
+ end
55
+
56
+ public
57
+
58
+ def self.adb_path
59
+ android_dependencies(:adb_path)
60
+ end
61
+
62
+ def self.aapt_path
63
+ android_dependencies(:aapt_path)
64
+ end
65
+
66
+ def self.zipalign_path
67
+ android_dependencies(:zipalign_path)
68
+ end
69
+
70
+ def self.android_jar_path
71
+ android_dependencies(:android_jar_path)
72
+ end
73
+
74
+ def self.java_path
75
+ java_dependencies(:java_path)
76
+ end
77
+
78
+ def self.keytool_path
79
+ java_dependencies(:keytool_path)
80
+ end
81
+
82
+ def self.jarsigner_path
83
+ java_dependencies(:jarsigner_path)
84
+ end
85
+
86
+ def self.ant_path
87
+ java_dependencies(:ant_path)
88
+ end
89
+
90
+ def self.setup
91
+ if Environment.variable('ANDROID_HOME')
92
+ android_sdk_location = Environment.variable('ANDROID_HOME')
93
+ Logger.debug("Setting Android SDK location to $ANDROID_HOME")
94
+ else
95
+ android_sdk_location = detect_android_sdk_location
96
+ end
97
+
98
+ if android_sdk_location.nil?
99
+ Logger.error 'Could not find an Android SDK please make sure it is installed.'
100
+ Logger.error 'You can read about how Calabash is searching for an Android SDK and how you can help here:'
101
+ Logger.error 'https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites'
102
+
103
+ raise 'Could not find an Android SDK'
104
+ end
105
+
106
+ Logger.debug("Android SDK location set to '#{android_sdk_location}'")
107
+
108
+ begin
109
+ set_android_dependencies(locate_android_dependencies(android_sdk_location))
110
+ rescue InvalidEnvironmentError => e
111
+ Logger.error 'Could not locate Android dependency'
112
+ Logger.error 'You can read about how Calabash is searching for an Android SDK and how you can help here:'
113
+ Logger.error 'https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites'
114
+
115
+ raise e
116
+ end
117
+
118
+ if Environment.variable('JAVA_HOME')
119
+ java_sdk_home = Environment.variable('JAVA_HOME')
120
+ Logger.debug("Setting Java SDK location to $JAVA_HOME")
121
+ else
122
+ java_sdk_home = detect_java_sdk_location
123
+ end
124
+
125
+ Logger.debug("Java SDK location set to '#{java_sdk_home}'")
126
+
127
+ begin
128
+ set_java_dependencies(locate_java_dependencies(java_sdk_home))
129
+ rescue InvalidJavaSDKHome => e
130
+ Logger.error "Could not find Java Development Kit please make sure it is installed."
131
+ Logger.error "You can read about how Calabash is searching for a JDK and how you can help here:"
132
+ Logger.error "https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites"
133
+
134
+ raise e
135
+ rescue InvalidEnvironmentError => e
136
+ Logger.error "Could not find Java dependency"
137
+ Logger.error "You can read about how Calabash is searching for a JDK and how you can help here:"
138
+ Logger.error "https://github.com/calabash/calabash-android/blob/master/documentation/installation.md#prerequisites"
139
+
140
+ raise e
141
+ end
142
+ end
143
+
144
+ private
145
+
146
+ def self.tools_directory
147
+ tools_directories = tools_directories(Environment.variable('ANDROID_HOME'))
148
+
149
+ File.join(Environment.variable('ANDROID_HOME'), tools_directories.first)
150
+ end
151
+
152
+ def self.tools_directories(android_sdk_location)
153
+ build_tools_files = list_files(File.join(android_sdk_location, 'build-tools')).select {|file| File.directory?(file)}
154
+
155
+ build_tools_directories =
156
+ build_tools_files.select do |dir|
157
+ begin
158
+ Luffa::Version.new(File.basename(dir))
159
+ true
160
+ rescue ArgumentError
161
+ false
162
+ end
163
+ end.sort do |a, b|
164
+ Luffa::Version.compare(Luffa::Version.new(File.basename(a)), Luffa::Version.new(File.basename(b)))
165
+ end.reverse.map{|dir| File.join('build-tools', File.basename(dir))}
166
+
167
+ if build_tools_directories.empty?
168
+ build_tools_directories = [File.join('build-tools', File.basename(build_tools_files.reverse.first))]
169
+ end
170
+
171
+ build_tools_directories + ['platform-tools', 'tools']
172
+ end
173
+
174
+ def self.platform_directory(android_sdk_location)
175
+ files = list_files(File.join(android_sdk_location, 'platforms'))
176
+ .select {|file| File.directory?(file)}
177
+
178
+ sorted_files = files.sort_by {|item| '%08s' % item.split('-').last}.reverse
179
+
180
+ File.join('platforms', File.basename(sorted_files.first))
181
+ end
182
+
183
+ def self.locate_android_dependencies(android_sdk_location)
184
+ adb_path = scan_for_path(android_sdk_location, adb_executable, ['platform-tools'])
185
+ aapt_path = scan_for_path(android_sdk_location, aapt_executable, tools_directories(android_sdk_location))
186
+ zipalign_path = scan_for_path(android_sdk_location, zipalign_executable, tools_directories(android_sdk_location))
187
+
188
+ if adb_path.nil?
189
+ raise InvalidEnvironmentError,
190
+ "Could not find '#{adb_executable}' in '#{android_sdk_location}'"
191
+ end
192
+
193
+ if aapt_path.nil?
194
+ raise InvalidEnvironmentError,
195
+ "Could not find '#{aapt_executable}' in '#{android_sdk_location}'"
196
+ end
197
+
198
+ if zipalign_path.nil?
199
+ raise InvalidEnvironmentError,
200
+ "Could not find '#{zipalign_executable}' in '#{android_sdk_location}'"
201
+ end
202
+
203
+ Logger.debug("Set aapt path to '#{aapt_path}'")
204
+ Logger.debug("Set zipalign path to '#{zipalign_path}'")
205
+ Logger.debug("Set adb path to '#{adb_path}'")
206
+
207
+ android_jar_path = scan_for_path(File.join(android_sdk_location, 'platforms'), 'android.jar', [File.basename(platform_directory(android_sdk_location))])
208
+
209
+ if android_jar_path.nil?
210
+ raise InvalidEnvironmentError,
211
+ "Could not find 'android.jar' in '#{File.join(android_sdk_location, 'platforms')}'"
212
+ end
213
+
214
+ Logger.debug("Set android jar path to '#{android_jar_path}'")
215
+
216
+ {
217
+ aapt_path: aapt_path,
218
+ zipalign_path: zipalign_path,
219
+ adb_path: adb_path,
220
+ android_jar_path: android_jar_path
221
+ }
222
+ end
223
+
224
+ def self.locate_java_dependencies(java_sdk_location)
225
+ # For the Java dependencies, we will use the PATH elements of they exist
226
+ on_path = find_executable_on_path(java_executable)
227
+
228
+ if on_path
229
+ Logger.debug('Found java on PATH')
230
+ java_path = on_path
231
+ else
232
+ if java_sdk_location.nil? || java_sdk_location.empty?
233
+ raise InvalidJavaSDKHome,
234
+ "Could not locate '#{java_executable}' on path, and Java SDK Home is invalid."
235
+ end
236
+
237
+ java_path = scan_for_path(java_sdk_location, java_executable, ['bin'])
238
+ end
239
+
240
+ Logger.debug("Set java path to '#{java_path}'")
241
+
242
+ on_path = find_executable_on_path(keytool_executable)
243
+
244
+ if on_path
245
+ Logger.debug('Found keytool on PATH')
246
+ keytool_path = on_path
247
+ else
248
+ if java_sdk_location.nil? || java_sdk_location.empty?
249
+ raise InvalidJavaSDKHome,
250
+ "Could not locate '#{keytool_executable}' on path, and Java SDK Home is invalid."
251
+ end
252
+
253
+ keytool_path = scan_for_path(java_sdk_location, keytool_executable, ['bin'])
254
+ end
255
+
256
+ Logger.debug("Set keytool path to '#{keytool_path}'")
257
+
258
+ on_path = find_executable_on_path(jarsigner_executable)
259
+
260
+ if on_path
261
+ Logger.debug('Found jarsigner on PATH')
262
+ jarsigner_path = on_path
263
+ else
264
+ if java_sdk_location.nil? || java_sdk_location.empty?
265
+ raise InvalidJavaSDKHome,
266
+ "Could not locate '#{jarsigner_executable}' on path, and Java SDK Home is invalid."
267
+ end
268
+
269
+ jarsigner_path = scan_for_path(java_sdk_location, jarsigner_executable, ['bin'])
270
+ end
271
+
272
+ Logger.debug("Set jarsigner path to '#{jarsigner_path}'")
273
+
274
+ if java_path.nil?
275
+ raise InvalidEnvironmentError,
276
+ "Could not find '#{java_executable}' on PATH or in '#{java_sdk_location}'"
277
+ end
278
+
279
+ if keytool_path.nil?
280
+ raise InvalidEnvironmentError,
281
+ "Could not find '#{keytool_executable}' on PATH or in '#{java_sdk_location}'"
282
+ end
283
+
284
+ if jarsigner_path.nil?
285
+ raise InvalidEnvironmentError,
286
+ "Could not find '#{jarsigner_executable}' on PATH or in '#{java_sdk_location}'"
287
+ end
288
+
289
+ {
290
+ java_path: java_path,
291
+ keytool_path: keytool_path,
292
+ jarsigner_path: jarsigner_path
293
+ }
294
+ end
295
+
296
+ def self.scan_for_path(path, file_name, expected_sub_folders = nil)
297
+ # Optimization for expected folders
298
+ if expected_sub_folders && !expected_sub_folders.empty?
299
+ expected_sub_folders.each do |expected_sub_folder|
300
+ result = scan_for_path(File.join(path, expected_sub_folder), file_name)
301
+
302
+ return result if result
303
+ end
304
+
305
+ Logger.warn("Did not find '#{file_name}' in any standard directory of '#{path}'. Calabash will therefore take longer to load")
306
+ Logger.debug(" - Expected to find '#{file_name}' in any of:")
307
+
308
+ expected_sub_folders.each do |expected_sub_folder|
309
+ Logger.debug(" - #{File.join(path, expected_sub_folder)}")
310
+ end
311
+ end
312
+
313
+ files = list_files(path).sort.reverse
314
+
315
+ if files.reject{|file| File.directory?(file)}.
316
+ map{|file| File.basename(file)}.include?(file_name)
317
+ return File.join(path, file_name)
318
+ else
319
+ files.select{|file| File.directory?(file)}.each do |dir|
320
+ result = scan_for_path(dir, file_name)
321
+
322
+ return result if result
323
+ end
324
+ end
325
+
326
+ nil
327
+ end
328
+
329
+ def self.detect_android_sdk_location
330
+ if File.exist?(monodroid_config_file)
331
+ sdk_location = read_attribute_from_monodroid_config('android-sdk', 'path')
332
+
333
+ if sdk_location
334
+ Logger.debug("Setting Android SDK location from '#{monodroid_config_file}'")
335
+
336
+ return sdk_location
337
+ end
338
+ end
339
+
340
+ if File.exist?('~/Library/Developer/Xamarin/android-sdk-mac_x86/')
341
+ return '~/Library/Developer/Xamarin/android-sdk-mac_x86/'
342
+ end
343
+
344
+ if File.exist?('C:\\Android\\android-sdk')
345
+ return 'C:\\Android\\android-sdk'
346
+ end
347
+
348
+ if is_windows?
349
+ from_registry = read_registry(::Win32::Registry::HKEY_CURRENT_USER, "Software\\Novell\\Mono for Android", 'AndroidSdkDirectory')
350
+
351
+ if from_registry && File.exist?(from_registry)
352
+ Logger.debug("Setting Android SDK location from HKEY_CURRENT_USER Software\\Novell\\Mono for Android")
353
+ return from_registry
354
+ end
355
+
356
+ from_registry = read_registry(::Win32::Registry::HKEY_LOCAL_MACHINE, 'Software\\Android SDK Tools', 'Path')
357
+
358
+ if from_registry && File.exist?(from_registry)
359
+ Logger.debug("Setting Android SDK location from HKEY_LOCAL_MACHINE Software\\Android SDK Tools")
360
+ return from_registry
361
+ end
362
+ end
363
+
364
+ nil
365
+ end
366
+
367
+ def self.detect_java_sdk_location
368
+ if File.exist?(monodroid_config_file)
369
+ sdk_location = read_attribute_from_monodroid_config('java-sdk', 'path')
370
+
371
+ if sdk_location
372
+ Logger.debug("Setting Java SDK location from '#{monodroid_config_file}'")
373
+
374
+ return sdk_location
375
+ end
376
+ end
377
+
378
+ java_versions = ['1.9', '1.8', '1.7', '1.6']
379
+
380
+ if is_windows?
381
+ java_versions.each do |java_version|
382
+ key = "SOFTWARE\\JavaSoft\\Java Development Kit\\#{java_version}"
383
+ from_registry = read_registry(::Win32::Registry::HKEY_LOCAL_MACHINE, key, 'JavaHome')
384
+
385
+ if from_registry && File.exist?(from_registry)
386
+ Logger.debug("Setting Java SDK location from HKEY_LOCAL_MACHINE #{key}")
387
+ return from_registry
388
+ end
389
+ end
390
+ end
391
+
392
+ nil
393
+ end
394
+
395
+ def self.monodroid_config_file
396
+ File.expand_path('~/.config/xbuild/monodroid-config.xml')
397
+ end
398
+
399
+ def self.read_attribute_from_monodroid_config(element, attribute)
400
+ REXML::Document.new(IO.read(monodroid_config_file)).elements["//#{element}"].attributes[attribute]
401
+ end
402
+
403
+ def self.find_executable_on_path(executable)
404
+ path_elements.each do |x|
405
+ f = File.join(x, executable)
406
+ return f if File.exists?(f)
407
+ end
408
+
409
+ nil
410
+ end
411
+
412
+ def self.path_elements
413
+ return [] unless Environment.variable('PATH')
414
+ Environment.variable('PATH').split (/[:;]/)
415
+ end
416
+
417
+ def self.zipalign_executable
418
+ is_windows? ? 'zipalign.exe' : 'zipalign'
419
+ end
420
+
421
+ def self.jarsigner_executable
422
+ is_windows? ? 'jarsigner.exe' : 'jarsigner'
423
+ end
424
+
425
+ def self.java_executable
426
+ is_windows? ? 'java.exe' : 'java'
427
+ end
428
+
429
+ def self.keytool_executable
430
+ is_windows? ? 'keytool.exe' : 'keytool'
431
+ end
432
+
433
+ def self.adb_executable
434
+ is_windows? ? 'adb.exe' : 'adb'
435
+ end
436
+
437
+ def self.aapt_executable
438
+ is_windows? ? 'aapt.exe' : 'aapt'
439
+ end
440
+
441
+ def self.ant_executable
442
+ is_windows? ? 'ant.exe' : 'ant'
443
+ end
444
+
445
+ def self.is_windows?
446
+ (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/)
447
+ end
448
+
449
+ def self.read_registry(root_key, key, value)
450
+ begin
451
+ root_key.open(key)[value]
452
+ rescue
453
+ nil
454
+ end
455
+ end
456
+
457
+ def self.list_files(path)
458
+ # Dir.glob does not accept backslashes, even on windows. We have to
459
+ # substitute all backwards slashes to forward.
460
+ # C:\foo becomes C:/foo
461
+
462
+ if is_windows?
463
+ Dir.glob(File.join(path, '*').gsub('\\', '/'))
464
+ else
465
+ Dir.glob(File.join(path, '*'))
466
+ end
467
+ end
468
+ end
469
+ end
470
+ end