capistrano-jdk-installer 0.0.6 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +0 -5
- data/capistrano-jdk-installer.gemspec +4 -1
- data/lib/capistrano-jdk-installer.rb +145 -347
- data/lib/capistrano-jdk-installer/jdk-installer.rb +471 -0
- data/lib/capistrano-jdk-installer/version.rb +1 -1
- data/test/centos6-64/.gitignore +5 -0
- data/test/centos6-64/Capfile +2 -0
- data/test/centos6-64/Gemfile +2 -0
- data/test/centos6-64/Vagrantfile +99 -0
- data/test/centos6-64/run.sh +7 -0
- data/test/config/deploy.rb +309 -0
- data/test/precise64/.gitignore +5 -0
- data/test/precise64/Capfile +2 -0
- data/test/precise64/Gemfile +2 -0
- data/test/precise64/Vagrantfile +99 -0
- data/test/precise64/run.sh +7 -0
- metadata +76 -5
@@ -0,0 +1,471 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "capistrano-jdk-installer/version"
|
4
|
+
require "fileutils"
|
5
|
+
require "json"
|
6
|
+
require "logger"
|
7
|
+
require "mechanize"
|
8
|
+
require "uri"
|
9
|
+
|
10
|
+
module Capistrano
|
11
|
+
module JDKInstaller
|
12
|
+
class JDKInstallerError < StandardError
|
13
|
+
end
|
14
|
+
|
15
|
+
class JDKInstallerParseError < JDKInstallerError
|
16
|
+
end
|
17
|
+
|
18
|
+
class JDKInstallerFile
|
19
|
+
MECHANIZE_USER_AGENT = "Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)"
|
20
|
+
def initialize(release, data, options={})
|
21
|
+
@release = release
|
22
|
+
@data = data
|
23
|
+
@options = options.dup
|
24
|
+
@logger = @options[:logger]
|
25
|
+
end
|
26
|
+
attr_reader :release, :options
|
27
|
+
|
28
|
+
def logger
|
29
|
+
@logger ||= Logger.new(STDOUT)
|
30
|
+
end
|
31
|
+
|
32
|
+
def filepath
|
33
|
+
@filepath ||= @data["filepath"]
|
34
|
+
end
|
35
|
+
alias file filepath
|
36
|
+
|
37
|
+
def name
|
38
|
+
@name ||= @data["name"]
|
39
|
+
end
|
40
|
+
alias to_s name
|
41
|
+
|
42
|
+
def title
|
43
|
+
@title ||= @data["title"]
|
44
|
+
end
|
45
|
+
|
46
|
+
def platform
|
47
|
+
@platform ||= case name
|
48
|
+
when /jdk-\d+(?:u\d+)?-(\w+-\w+)\.\w+/ then $1.downcase
|
49
|
+
when /j2?dk-\d+_\d+_\d+(?:_\d+)?-(\w+-\w+)\.\w+/ then $1.downcase
|
50
|
+
else
|
51
|
+
raise(JDKInstallerParseError.new("Could not parse JDK file name: #{name}"))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def version
|
56
|
+
release.version
|
57
|
+
end
|
58
|
+
|
59
|
+
def major_version
|
60
|
+
release.major_version
|
61
|
+
end
|
62
|
+
|
63
|
+
def minor_version
|
64
|
+
release.minor_version
|
65
|
+
end
|
66
|
+
|
67
|
+
def update_number
|
68
|
+
release.update_number
|
69
|
+
end
|
70
|
+
|
71
|
+
def inner_version
|
72
|
+
release.inner_version
|
73
|
+
end
|
74
|
+
|
75
|
+
def licpath
|
76
|
+
release.licpath
|
77
|
+
end
|
78
|
+
alias license_path licpath
|
79
|
+
|
80
|
+
def lictitle
|
81
|
+
release.lictitle
|
82
|
+
end
|
83
|
+
alias license_title lictitle
|
84
|
+
|
85
|
+
def mechanize
|
86
|
+
@mechanize ||= ::Mechanize.new { |agent|
|
87
|
+
agent.user_agent = MECHANIZE_USER_AGENT
|
88
|
+
agent.cookie_jar.add!(::Mechanize::Cookie.new("gpw_e24", ".", :domain => "oracle.com", :path => "/", :secure => false, :for_domain => true))
|
89
|
+
agent.ssl_version = :TLSv1 # we have to declare TLS version explicitly to avoid problems on LP:965371
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def download(filename, options={})
|
94
|
+
options = @options.merge(options)
|
95
|
+
username = options.fetch(:username, "")
|
96
|
+
password = options.fetch(:password, "")
|
97
|
+
|
98
|
+
logger.debug("Download JDK archive from #{filepath}....")
|
99
|
+
page = mechanize.get(filepath)
|
100
|
+
1.upto(16) do # to avoid infinity loop...
|
101
|
+
if page.uri.host == "login.oracle.com" # login.oracle.com doesn't return proper Content-Type
|
102
|
+
if page.is_a?(::Mechanize::File)
|
103
|
+
page = ::Mechanize::Page.new(page.uri, page.response, page.body, page.code, mechanize)
|
104
|
+
end
|
105
|
+
form = page.form_with
|
106
|
+
form["ssousername"] = username
|
107
|
+
form["password"] = password
|
108
|
+
page = mechanize.submit(form)
|
109
|
+
else
|
110
|
+
page.save(filename)
|
111
|
+
logger.debug("Wrote #{page.body.size} bytes to #{filename}.")
|
112
|
+
break
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def uri
|
118
|
+
@uri ||= URI.parse(filepath)
|
119
|
+
end
|
120
|
+
|
121
|
+
def basename
|
122
|
+
File.basename(uri.path)
|
123
|
+
end
|
124
|
+
|
125
|
+
def install_path(options={})
|
126
|
+
options = @options.merge(options)
|
127
|
+
case platform
|
128
|
+
when /macosx/i
|
129
|
+
v = if update_number
|
130
|
+
"jdk%s_%02d.jdk" % [inner_version, update_number]
|
131
|
+
else
|
132
|
+
"jdk%s.jdk" % [inner_version]
|
133
|
+
end
|
134
|
+
File.join("/Library", "Java", "JavaVirtualMachines", v, "Contents", "Home")
|
135
|
+
else
|
136
|
+
v = if update_number
|
137
|
+
"jdk%s_%02d" % [inner_version, update_number]
|
138
|
+
else
|
139
|
+
"jdk%s" % [inner_version]
|
140
|
+
end
|
141
|
+
if options.key?(:path)
|
142
|
+
File.join(options[:path], v)
|
143
|
+
else
|
144
|
+
v
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def install_command(filename, destination, options={})
|
150
|
+
execute = []
|
151
|
+
execute << "mkdir -p #{File.dirname(destination).dump}"
|
152
|
+
case filename
|
153
|
+
when /\.(bin|sh)$/
|
154
|
+
execute << "( cd #{File.dirname(destination).dump} && yes | sh #{filename.dump} )"
|
155
|
+
when /\.dmg$/
|
156
|
+
if update_number
|
157
|
+
pkg = File.join("/Volumes", "JDK %d Update %02d" % [major_version, update_number],
|
158
|
+
"JDK %d Update %02d.pkg" % [major_version, update_number])
|
159
|
+
else
|
160
|
+
pkg = File.join("/Volumes", "JDK %d" % [major_version], "JDK %d" % [major_version])
|
161
|
+
end
|
162
|
+
execute << "open #{filenamedump}"
|
163
|
+
execute << "( while test \! -f #{pkg.dump}; do sleep 1; done )"
|
164
|
+
execute << "open #{pkg.dump}"
|
165
|
+
execute << "( while test \! -d #{destination.dump}; do sleep 1; done )"
|
166
|
+
when /\.(tar\.(gz|bz2)|tgz|tbz2)$/
|
167
|
+
execute << "tar xf #{filename.dump} -C #{File.dirname(destination).dump}"
|
168
|
+
when /\.zip$/
|
169
|
+
execute << "( cd #{File.dirname(destination).dump} && unzip #{filename.dump} )"
|
170
|
+
else
|
171
|
+
execute << "true"
|
172
|
+
end
|
173
|
+
execute.join(" && ")
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
class JDKInstallerRelease
|
178
|
+
include Enumerable
|
179
|
+
def initialize(version, data, options={})
|
180
|
+
@version = version
|
181
|
+
@data = data
|
182
|
+
@options = options.dup
|
183
|
+
@logger = @options[:logger]
|
184
|
+
end
|
185
|
+
attr_reader :version, :options
|
186
|
+
|
187
|
+
def logger
|
188
|
+
@logger ||= Logger.new(STDOUT)
|
189
|
+
end
|
190
|
+
|
191
|
+
def files
|
192
|
+
@files ||= @data["files"].map { |file|
|
193
|
+
JDKInstallerFile.new(self, file, @options)
|
194
|
+
}
|
195
|
+
end
|
196
|
+
alias to_a files
|
197
|
+
|
198
|
+
def each(&block)
|
199
|
+
self.to_a.each(&block)
|
200
|
+
end
|
201
|
+
|
202
|
+
def find_by_platform(platform)
|
203
|
+
platform = platform.to_s
|
204
|
+
self.find { |f| f.platform == platform }
|
205
|
+
end
|
206
|
+
|
207
|
+
def licpath
|
208
|
+
@licpath ||= @data["licpath"]
|
209
|
+
end
|
210
|
+
alias license_path licpath
|
211
|
+
|
212
|
+
def lictitle
|
213
|
+
@lictitle ||= @data["lictitle"]
|
214
|
+
end
|
215
|
+
alias license_title lictitle
|
216
|
+
|
217
|
+
def name
|
218
|
+
@name ||= @data["name"]
|
219
|
+
end
|
220
|
+
alias to_s name
|
221
|
+
|
222
|
+
def title
|
223
|
+
@title ||= @data["title"]
|
224
|
+
end
|
225
|
+
|
226
|
+
def version_info
|
227
|
+
@version_info ||= case name
|
228
|
+
when /j2sdk-(1\.4\.(\d+))(?:[_u]([0-9]+))?/ then [ $1, "1.4", $2, $3 ]
|
229
|
+
when /jdk-(1\.5\.(\d+))(?:[_u]([0-9]+))?/ then [ $1, "5", $2, $3 ]
|
230
|
+
when /jdk-(\d+)(?:u(\d+))?/ then [ "1.#{$1}.0", $1, 0, $2 ]
|
231
|
+
else
|
232
|
+
raise(JDKInstallerParseError.new("Could not parse JDK release name: #{name}"))
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def inner_version
|
237
|
+
@inner_version ||= version_info[0] # e.g. "1.7.0"
|
238
|
+
end
|
239
|
+
|
240
|
+
def major_version
|
241
|
+
@major_version ||= version_info[1] # e.g. "7"
|
242
|
+
if @major_version != version.major_version
|
243
|
+
raise(JDKInstallerParseError.new("Major version mismatch (got=#{@major_version}, expected=#{version.major_version})"))
|
244
|
+
end
|
245
|
+
@major_version
|
246
|
+
end
|
247
|
+
|
248
|
+
def minor_version
|
249
|
+
@minor_version ||= version_info[2] # e.g. "0"
|
250
|
+
end
|
251
|
+
|
252
|
+
def update_number
|
253
|
+
@update_number ||= version_info[3] # e.g. "6"
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
class JDKInstallerVersion
|
258
|
+
include Enumerable
|
259
|
+
def initialize(data, options={})
|
260
|
+
@data = data
|
261
|
+
@options = options.dup
|
262
|
+
@logger = @options[:logger]
|
263
|
+
end
|
264
|
+
attr_reader :options
|
265
|
+
|
266
|
+
def logger
|
267
|
+
@logger ||= Logger.new(STDOUT)
|
268
|
+
end
|
269
|
+
|
270
|
+
def name
|
271
|
+
@name ||= @data["name"]
|
272
|
+
end
|
273
|
+
alias to_s name
|
274
|
+
|
275
|
+
def releases
|
276
|
+
@releases ||= @data["releases"].map { |release|
|
277
|
+
JDKInstallerRelease.new(self, release, @options)
|
278
|
+
}
|
279
|
+
end
|
280
|
+
alias to_a releases
|
281
|
+
|
282
|
+
def each(&block)
|
283
|
+
self.to_a.each(&block)
|
284
|
+
end
|
285
|
+
|
286
|
+
def find_by_update_number(update_number, options={})
|
287
|
+
update_number = update_number.to_s
|
288
|
+
self.find { |r| r.update_number == update_number }
|
289
|
+
end
|
290
|
+
|
291
|
+
def major_version
|
292
|
+
case name
|
293
|
+
when /JDK ((?:\d+\.)?\d+)/i then $1
|
294
|
+
else
|
295
|
+
raise(JDKInstallerParseError.new("Could not parse JDK version name: #{name}"))
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
class JDKInstallerVersions
|
301
|
+
include Enumerable
|
302
|
+
JSON_VERSION = 2
|
303
|
+
class << self
|
304
|
+
def parse(s, options={})
|
305
|
+
s = s.sub(/\A[^{]*/, "").sub(/[^}]*\z/, "").strip # remove leading & trailing JS code from response
|
306
|
+
i = new(JSON.load(s), options)
|
307
|
+
i.versions
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def initialize(data, options={})
|
312
|
+
@data = data
|
313
|
+
@options = options.dup
|
314
|
+
@logger = @options[:logger]
|
315
|
+
|
316
|
+
if @data["version"] != JSON_VERSION
|
317
|
+
raise(JDKInstallerParseError.new("JSON version mismatch (got=#{@data["version"]}, expected=#{JSON_VERSION})"))
|
318
|
+
end
|
319
|
+
end
|
320
|
+
attr_reader :options
|
321
|
+
|
322
|
+
def logger
|
323
|
+
@logger ||= Logger.new(STDOUT)
|
324
|
+
end
|
325
|
+
|
326
|
+
def versions
|
327
|
+
@versions ||= @data["data"].map { |version|
|
328
|
+
JDKInstallerVersion.new(version, @options)
|
329
|
+
}
|
330
|
+
end
|
331
|
+
alias to_a versions
|
332
|
+
|
333
|
+
def each(&block)
|
334
|
+
self.to_a.each(&block)
|
335
|
+
end
|
336
|
+
|
337
|
+
def find_by_major_version(version, options={})
|
338
|
+
version = version.to_s
|
339
|
+
self.find { |v| v.major_version == version }
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
class JDKInstaller
|
344
|
+
JDK_INSTALLER_URI = "http://updates.jenkins-ci.org/updates/hudson.tools.JDKInstaller.json"
|
345
|
+
JDK_INSTALLER_TTL = 259200
|
346
|
+
class << self
|
347
|
+
def major_version(version_name)
|
348
|
+
case version_name
|
349
|
+
when /^1_4_\d+(?:_[0-9]+)?$/ then "1.4"
|
350
|
+
when /^1_5_\d+(?:_[0-9]+)?$/ then "5"
|
351
|
+
when /^(\d+)(?:u\d+)?$/ then $1
|
352
|
+
else
|
353
|
+
raise(JDKInstallerParseError.new("Could not parse JDK version name: #{version_name}"))
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
def platform_string(version_name, ostype, arch, options={})
|
358
|
+
major_version = major_version(version_name)
|
359
|
+
ostype = ostype.to_s.strip.downcase
|
360
|
+
arch = arch.to_s.strip.downcase
|
361
|
+
case major_version
|
362
|
+
when /^(?:1\.4|5)$/
|
363
|
+
arch = case arch
|
364
|
+
when /^(?:i[3-7]86)$/i then "i586"
|
365
|
+
when /^(?:amd64|x86_64)$/i then "amd64"
|
366
|
+
else
|
367
|
+
arch
|
368
|
+
end
|
369
|
+
else
|
370
|
+
ostype = case ostype
|
371
|
+
when /^Darwin$/i then "macosx"
|
372
|
+
else
|
373
|
+
ostype
|
374
|
+
end
|
375
|
+
arch = case arch
|
376
|
+
when /^(?:i[3-7]86)$/i then ostype == "macosx" ? "x64" : "i586"
|
377
|
+
when /^(?:amd64|x86_64)$/i then "x64"
|
378
|
+
else
|
379
|
+
arch
|
380
|
+
end
|
381
|
+
end
|
382
|
+
"#{ostype}-#{arch}"
|
383
|
+
end
|
384
|
+
end
|
385
|
+
|
386
|
+
def initialize(options={})
|
387
|
+
@uri = ( options.delete(:uri) || JDK_INSTALLER_URI )
|
388
|
+
@ttl = ( options.delete(:ttl) || JDK_INSTALLER_TTL )
|
389
|
+
@file = if options.key?(:file)
|
390
|
+
options.delete(:file)
|
391
|
+
else
|
392
|
+
Tempfile.new("jdk-installer")
|
393
|
+
end
|
394
|
+
@keep_stale = options.fetch(:keep_stale, false)
|
395
|
+
@options = options.dup
|
396
|
+
@logger = @options[:logger]
|
397
|
+
update
|
398
|
+
end
|
399
|
+
|
400
|
+
def logger
|
401
|
+
@logger ||= Logger.new(STDOUT)
|
402
|
+
end
|
403
|
+
|
404
|
+
def mechanize
|
405
|
+
@mechanize ||= ::Mechanize.new { |agent|
|
406
|
+
agent.ssl_version = :TLSv1 # we have to declare TLS version explicitly to avoid problems on LP:965371
|
407
|
+
}
|
408
|
+
end
|
409
|
+
|
410
|
+
def expired?(t=Time.now)
|
411
|
+
not(File.file?(@file)) or ( File.mtime(@file) + @ttl < t )
|
412
|
+
end
|
413
|
+
|
414
|
+
def update
|
415
|
+
if expired?
|
416
|
+
logger.info("The cache of JDKInstaller.json has been expired. (ttl=#{@ttl})")
|
417
|
+
update!
|
418
|
+
end
|
419
|
+
end
|
420
|
+
|
421
|
+
def update!
|
422
|
+
begin
|
423
|
+
page = mechanize.get(@uri)
|
424
|
+
write(page.body)
|
425
|
+
rescue ::Mechanize::Error => error
|
426
|
+
logger.info("Could not update JDKInstaller.json from #{@uri}. (#{error})")
|
427
|
+
if @keep_stale
|
428
|
+
logger.info("Try to use stale JDKInstaller.json at #{@file}.")
|
429
|
+
else
|
430
|
+
raise
|
431
|
+
end
|
432
|
+
end
|
433
|
+
end
|
434
|
+
|
435
|
+
def write(s)
|
436
|
+
if @file.respond_to?(:write)
|
437
|
+
@file.write(s)
|
438
|
+
else
|
439
|
+
FileUtils.mkdir_p(File.dirname(@file))
|
440
|
+
File.write(@file, s)
|
441
|
+
end
|
442
|
+
end
|
443
|
+
|
444
|
+
def read()
|
445
|
+
if @file.respond_to?(:read)
|
446
|
+
@file.read
|
447
|
+
else
|
448
|
+
File.read(@file)
|
449
|
+
end
|
450
|
+
end
|
451
|
+
|
452
|
+
def versions
|
453
|
+
@versions ||= JDKInstallerVersions.parse(read, @options)
|
454
|
+
end
|
455
|
+
|
456
|
+
def releases
|
457
|
+
@releases ||= versions.map { |version| version.releases }.flatten
|
458
|
+
end
|
459
|
+
|
460
|
+
def files
|
461
|
+
@files ||= releases.map { |release| release.files }.flatten
|
462
|
+
end
|
463
|
+
|
464
|
+
def [](regex)
|
465
|
+
files.find { |file| regex === file.to_s }
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
# vim:set ft=ruby sw=2 ts=2 :
|