Skip to content

Commit c0267a4

Browse files
committed
Merge 49322113-default-jre to master
[Completes #49322113]
2 parents 708d5f6 + 458622e commit c0267a4

File tree

6 files changed

+132
-50
lines changed

6 files changed

+132
-50
lines changed

README.md

+11-3
Original file line numberDiff line numberDiff line change
@@ -54,15 +54,23 @@ If the user does not specify a JRE vendor and version, a JRE is selected automat
5454
This buildpacks is designed to be extensible by other developers. To this end, various bits of configuration are exposed that make it simple to add functionality.
5555

5656
## Adding JRES
57-
By default, this buildpack only allows users to choose from [OpenJDK][openjdk] JREs. To allow users to choose a JRE from other vendors, these vendors must be specified in [`config/jres.yml`][jres_yml]. The file is [YAML][yaml] formatted with the following syntax:
57+
By default, this buildpack only allows users to choose from [OpenJDK][openjdk] JREs. To allow users to choose a JRE from other vendors, these vendors must be specified in [`config/jres.yml`][jres_yml]. The file is [YAML][yaml] formatted and in the simplest case is a mapping from a vendor name to a `String` repository root.
5858

59-
```plain
59+
```yaml
6060
<vendor name>: <JRE repository root URI>
6161
```
6262
63+
When configured like this, if the user does not specify a version of the JRE to use, the latest possible version will be selected. If a particular JRE should use a default that is not the latest (e.g. using `1.7.0_21` instead of `1.8.0_M7`), the default version can be specified by using a `Hash` instead of a `String` as the value.
64+
65+
```yaml
66+
<vendor name>:
67+
default_version: <default version pattern>
68+
repository_root: <JRE repository root URI>
69+
```
70+
6371
The JRE repository root must contain a `/index.yml` file ([example][index_yml]). This file is also [YAML][yaml] formatted with the following syntax:
6472

65-
```plain
73+
```yaml
6674
<JRE version>: <path relative to JRE repository root>
6775
```
6876

config/jres.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,6 @@
1515

1616
# Configuration for JRE repositories keyed by vendor
1717
---
18-
openjdk: "http://jres.gopivotal.com.s3.amazonaws.com/lucid/x86_64/openjdk"
18+
openjdk:
19+
default_version: 1.7.0_+
20+
repository_root: "http://jres.gopivotal.com.s3.amazonaws.com/lucid/x86_64/openjdk"

lib/java_buildpack/jre_properties.rb

+43-7
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,20 @@ class JreProperties
3939
# @param [String] app_dir The application to inspect for values specified by the user
4040
def initialize(app_dir)
4141
value_resolver = ValueResolver.new(app_dir)
42-
4342
candidate_vendor = value_resolver.resolve(ENV_VAR_VENDOR, SYS_PROP_VENDOR)
4443
candidate_version = value_resolver.resolve(ENV_VAR_VERSION, SYS_PROP_VERSION)
4544

46-
jre_vendor_repositories = YAML.load_file JRES_YAML_FILE
47-
@vendor = VendorResolver.resolve(candidate_vendor, jre_vendor_repositories.keys)
48-
repository = jre_vendor_repositories[@vendor]
49-
index = YAML.parse(open "#{repository}#{INDEX_PATH}").to_ruby
50-
@version = VersionResolver.resolve(candidate_version, index.keys)
51-
@uri = "#{repository}/#{index[@version]}"
45+
vendors = load_vendors
46+
@vendor = VendorResolver.resolve(candidate_vendor, vendors.keys)
47+
vendor_details = vendors[@vendor]
48+
49+
repository_root = find_repository_root vendor_details
50+
default_version = find_default_version vendor_details
51+
versions = load_versions(repository_root)
52+
53+
@version = VersionResolver.resolve(candidate_version, default_version, versions.keys)
54+
55+
@uri = "#{repository_root}/#{versions[@version]}"
5256
end
5357

5458
private
@@ -61,9 +65,41 @@ def initialize(app_dir)
6165

6266
JRES_YAML_FILE = 'config/jres.yml'
6367

68+
KEY_DEFAULT_VERSION = 'default_version'
69+
70+
KEY_REPOSITORY_ROOT = 'repository_root'
71+
6472
SYS_PROP_VENDOR = 'java.runtime.vendor'
6573

6674
SYS_PROP_VERSION = 'java.runtime.version'
6775

76+
def find_default_version(vendor_details)
77+
if vendor_details.is_a?(Hash) && vendor_details.has_key?(KEY_DEFAULT_VERSION)
78+
default_version = vendor_details[KEY_DEFAULT_VERSION]
79+
else
80+
default_version = nil
81+
end
82+
end
83+
84+
def find_repository_root(vendor_details)
85+
if vendor_details.is_a? String
86+
repository_root = vendor_details
87+
elsif vendor_details.is_a?(Hash) && vendor_details.has_key?(KEY_REPOSITORY_ROOT)
88+
repository_root = vendor_details[KEY_REPOSITORY_ROOT]
89+
else
90+
raise "Vendor details must be either a String or a Hash with a key of '#{KEY_REPOSITORY_ROOT}' and a value that is a String that points to the root of a JRE repository."
91+
end
92+
93+
repository_root
94+
end
95+
96+
def load_versions(repository_root)
97+
YAML.parse(open "#{repository_root}#{INDEX_PATH}").to_ruby
98+
end
99+
100+
def load_vendors
101+
YAML.load_file JRES_YAML_FILE
102+
end
103+
68104
end
69105
end

lib/java_buildpack/version_resolver.rb

+5-2
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@ class VersionResolver
2424
# The resolution returns the maximum of the versions that match the candidate version
2525
#
2626
# @param [String, nil] candidate_version the version, possibly containing a wildcard, to resolve
27+
# @param [String, nil] default_version the version, possibly containing a wildcard, to resolve if
28+
# +candidate_version+ is +nil+
2729
# @param [Array<String>] versions the collection of versions to resolve against
2830
# @return [String] the resolved version
2931
# @raise if no version can be resolved
30-
def self.resolve(candidate_version, versions)
31-
tokenized_candidate_version = TokenizedVersion.new(candidate_version)
32+
def self.resolve(candidate_version, default_version, versions)
33+
tokenized_candidate_version = TokenizedVersion.new(
34+
candidate_version.nil? || candidate_version.empty? ? default_version : candidate_version)
3235
tokenized_versions = versions.map { |version| TokenizedVersion.new(version, false) }
3336

3437
version = tokenized_versions

spec/java_buildpack/jre_properties_spec.rb

+28-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
CANDIDATE_VERSION = 'candidate-version'
2323

24+
DEFAULT_VERSION = 'default-version'
25+
2426
RESOLVED_PATH = 'resolved-path'
2527

2628
RESOLVED_ROOT = 'resolved-root'
@@ -31,13 +33,28 @@
3133

3234
RESOLVED_URI = "#{RESOLVED_ROOT}/#{RESOLVED_PATH}"
3335

34-
it 'returns the resolved vendor, version, and uri' do
36+
it 'returns the resolved vendor, version, and uri from uri-only vendor details' do
37+
JavaBuildpack::ValueResolver.any_instance.stub(:resolve).with('JAVA_RUNTIME_VENDOR', 'java.runtime.vendor').and_return(CANDIDATE_VENDOR)
38+
JavaBuildpack::ValueResolver.any_instance.stub(:resolve).with('JAVA_RUNTIME_VERSION', 'java.runtime.version').and_return(CANDIDATE_VERSION)
3539
YAML.stub(:load_file).with('config/jres.yml').and_return(RESOLVED_VENDOR => RESOLVED_ROOT)
40+
JavaBuildpack::VendorResolver.stub(:resolve).with(CANDIDATE_VENDOR, [RESOLVED_VENDOR]).and_return(RESOLVED_VENDOR)
3641
JavaBuildpack::JreProperties.any_instance.stub(:open).with("#{RESOLVED_ROOT}/index.yml").and_return(File.open('spec/fixtures/test-index.yml'))
42+
JavaBuildpack::VersionResolver.stub(:resolve).with(CANDIDATE_VERSION, nil, [RESOLVED_VERSION]).and_return(RESOLVED_VERSION)
43+
44+
jre_properties = JavaBuildpack::JreProperties.new('spec/fixtures/no_system_properties')
45+
46+
expect(jre_properties.vendor).to eq(RESOLVED_VENDOR)
47+
expect(jre_properties.version).to eq(RESOLVED_VERSION)
48+
expect(jre_properties.uri).to eq(RESOLVED_URI)
49+
end
50+
51+
it 'returns the resolved vendor, version, and uri from extended vendor details' do
3752
JavaBuildpack::ValueResolver.any_instance.stub(:resolve).with('JAVA_RUNTIME_VENDOR', 'java.runtime.vendor').and_return(CANDIDATE_VENDOR)
3853
JavaBuildpack::ValueResolver.any_instance.stub(:resolve).with('JAVA_RUNTIME_VERSION', 'java.runtime.version').and_return(CANDIDATE_VERSION)
54+
YAML.stub(:load_file).with('config/jres.yml').and_return(RESOLVED_VENDOR => { 'default_version' => DEFAULT_VERSION, 'repository_root' => RESOLVED_ROOT})
3955
JavaBuildpack::VendorResolver.stub(:resolve).with(CANDIDATE_VENDOR, [RESOLVED_VENDOR]).and_return(RESOLVED_VENDOR)
40-
JavaBuildpack::VersionResolver.stub(:resolve).with(CANDIDATE_VERSION, [RESOLVED_VERSION]).and_return(RESOLVED_VERSION)
56+
JavaBuildpack::JreProperties.any_instance.stub(:open).with("#{RESOLVED_ROOT}/index.yml").and_return(File.open('spec/fixtures/test-index.yml'))
57+
JavaBuildpack::VersionResolver.stub(:resolve).with(CANDIDATE_VERSION, DEFAULT_VERSION, [RESOLVED_VERSION]).and_return(RESOLVED_VERSION)
4158

4259
jre_properties = JavaBuildpack::JreProperties.new('spec/fixtures/no_system_properties')
4360

@@ -46,4 +63,13 @@
4663
expect(jre_properties.uri).to eq(RESOLVED_URI)
4764
end
4865

66+
it 'raises an error if the vendor details are not of a valid structure' do
67+
JavaBuildpack::ValueResolver.any_instance.stub(:resolve).with('JAVA_RUNTIME_VENDOR', 'java.runtime.vendor').and_return(CANDIDATE_VENDOR)
68+
JavaBuildpack::ValueResolver.any_instance.stub(:resolve).with('JAVA_RUNTIME_VERSION', 'java.runtime.version').and_return(CANDIDATE_VERSION)
69+
YAML.stub(:load_file).with('config/jres.yml').and_return(RESOLVED_VENDOR => { 'uri' => RESOLVED_ROOT})
70+
JavaBuildpack::VendorResolver.stub(:resolve).with(CANDIDATE_VENDOR, [RESOLVED_VENDOR]).and_return(RESOLVED_VENDOR)
71+
72+
expect { JavaBuildpack::JreProperties.new('spec/fixtures/no_system_properties') }.to raise_error
73+
end
74+
4975
end

spec/java_buildpack/version_resolver_spec.rb

+42-35
Original file line numberDiff line numberDiff line change
@@ -29,110 +29,117 @@
2929
]
3030

3131
it 'resolves the latest version if no candidate is supplied' do
32-
expect(JavaBuildpack::VersionResolver.resolve(nil, VERSIONS)).to eq('2.0.0')
33-
expect(JavaBuildpack::VersionResolver.resolve('', VERSIONS)).to eq('2.0.0')
32+
expect(JavaBuildpack::VersionResolver.resolve(nil, nil, VERSIONS)).to eq('2.0.0')
33+
expect(JavaBuildpack::VersionResolver.resolve('', nil, VERSIONS)).to eq('2.0.0')
34+
expect(JavaBuildpack::VersionResolver.resolve(nil, '', VERSIONS)).to eq('2.0.0')
35+
expect(JavaBuildpack::VersionResolver.resolve('', '', VERSIONS)).to eq('2.0.0')
36+
end
37+
38+
it 'resolves the default version if no candidate is supplied' do
39+
expect(JavaBuildpack::VersionResolver.resolve(nil, '1.6.0_+', VERSIONS)).to eq('1.6.0_27')
40+
expect(JavaBuildpack::VersionResolver.resolve('', '1.6.0_+', VERSIONS)).to eq('1.6.0_27')
3441
end
3542

3643
it 'resolves a wildcard major version' do
37-
expect(JavaBuildpack::VersionResolver.resolve('+', VERSIONS)).to eq('2.0.0')
44+
expect(JavaBuildpack::VersionResolver.resolve('+', nil, VERSIONS)).to eq('2.0.0')
3845
end
3946

4047
it 'resolves a wildcard minor version' do
41-
expect(JavaBuildpack::VersionResolver.resolve('1.+', VERSIONS)).to eq('1.8.0_05')
48+
expect(JavaBuildpack::VersionResolver.resolve('1.+', nil, VERSIONS)).to eq('1.8.0_05')
4249
end
4350

4451
it 'resolves a wildcard micro version' do
45-
expect(JavaBuildpack::VersionResolver.resolve('1.6.+', VERSIONS)).to eq('1.6.1_14')
52+
expect(JavaBuildpack::VersionResolver.resolve('1.6.+', nil, VERSIONS)).to eq('1.6.1_14')
4653
end
4754

4855
it 'resolves a wildcard qualifier' do
49-
expect(JavaBuildpack::VersionResolver.resolve('1.6.0_+', VERSIONS)).to eq('1.6.0_27')
50-
expect(JavaBuildpack::VersionResolver.resolve('1.8.0_+', VERSIONS)).to eq('1.8.0_05')
56+
expect(JavaBuildpack::VersionResolver.resolve('1.6.0_+', nil, VERSIONS)).to eq('1.6.0_27')
57+
expect(JavaBuildpack::VersionResolver.resolve('1.8.0_+', nil, VERSIONS)).to eq('1.8.0_05')
5158
end
5259

5360
it 'resolves a non-wildcard version' do
54-
expect(JavaBuildpack::VersionResolver.resolve('1.6.0_26', VERSIONS)).to eq('1.6.0_26')
55-
expect(JavaBuildpack::VersionResolver.resolve('2.0.0', VERSIONS)).to eq('2.0.0')
61+
expect(JavaBuildpack::VersionResolver.resolve('1.6.0_26', nil, VERSIONS)).to eq('1.6.0_26')
62+
expect(JavaBuildpack::VersionResolver.resolve('2.0.0', nil, VERSIONS)).to eq('2.0.0')
5663
end
5764

5865
it 'resolves a non-digit qualifier' do
59-
expect(JavaBuildpack::VersionResolver.resolve('1.8.0_M-7', VERSIONS)).to eq('1.8.0_M-7')
66+
expect(JavaBuildpack::VersionResolver.resolve('1.8.0_M-7', nil, VERSIONS)).to eq('1.8.0_M-7')
6067
end
6168

6269
it 'should order qualifiers correctly' do
63-
expect(JavaBuildpack::VersionResolver.resolve('1.7.0_+', ['1.7.0_28', '1.7.0_28a'])).to eq('1.7.0_28a')
70+
expect(JavaBuildpack::VersionResolver.resolve('1.7.0_+', nil, ['1.7.0_28', '1.7.0_28a'])).to eq('1.7.0_28a')
6471
end
6572

6673
it 'should raise an exception when the major version is not numeric' do
67-
expect { JavaBuildpack::VersionResolver.resolve('A', VERSIONS) }.to raise_error
74+
expect { JavaBuildpack::VersionResolver.resolve('A', nil, VERSIONS) }.to raise_error
6875
end
6976

7077
it 'should raise an exception when the minor version is not numeric' do
71-
expect { JavaBuildpack::VersionResolver.resolve('1.A', VERSIONS) }.to raise_error
72-
expect { JavaBuildpack::VersionResolver.resolve('1..0', VERSIONS) }.to raise_error
78+
expect { JavaBuildpack::VersionResolver.resolve('1.A', nil, VERSIONS) }.to raise_error
79+
expect { JavaBuildpack::VersionResolver.resolve('1..0', nil, VERSIONS) }.to raise_error
7380
end
7481

7582
it 'should raise an exception when the micro version is not numeric' do
76-
expect { JavaBuildpack::VersionResolver.resolve('1.6.A', VERSIONS) }.to raise_error
77-
expect { JavaBuildpack::VersionResolver.resolve('1.6..', VERSIONS) }.to raise_error
78-
expect { JavaBuildpack::VersionResolver.resolve('1.6_26', VERSIONS) }.to raise_error
83+
expect { JavaBuildpack::VersionResolver.resolve('1.6.A', nil, VERSIONS) }.to raise_error
84+
expect { JavaBuildpack::VersionResolver.resolve('1.6..', nil, VERSIONS) }.to raise_error
85+
expect { JavaBuildpack::VersionResolver.resolve('1.6_26', nil, VERSIONS) }.to raise_error
7986
end
8087

8188
it 'should raise an exception if no version can be resolved' do
82-
expect { JavaBuildpack::VersionResolver.resolve('2.1.0', VERSIONS) }.to raise_error
89+
expect { JavaBuildpack::VersionResolver.resolve('2.1.0', nil, VERSIONS) }.to raise_error
8390
end
8491

8592
it 'should raise an exception when major version is not legal' do
86-
expect { JavaBuildpack::VersionResolver.resolve('1+', VERSIONS) }.to raise_error
93+
expect { JavaBuildpack::VersionResolver.resolve('1+', nil, VERSIONS) }.to raise_error
8794
end
8895

8996
it 'should raise an exception when minor version is not legal' do
90-
expect { JavaBuildpack::VersionResolver.resolve('1.6+', VERSIONS) }.to raise_error
97+
expect { JavaBuildpack::VersionResolver.resolve('1.6+', nil, VERSIONS) }.to raise_error
9198
end
9299

93100
it 'should raise an exception when micro version is not legal' do
94-
expect { JavaBuildpack::VersionResolver.resolve('1.6.0+', VERSIONS) }.to raise_error
101+
expect { JavaBuildpack::VersionResolver.resolve('1.6.0+', nil, VERSIONS) }.to raise_error
95102
end
96103

97104
it 'should raise an exception when qualifier version is not legal' do
98-
expect { JavaBuildpack::VersionResolver.resolve('1.6.0_05+', VERSIONS) }.to raise_error
105+
expect { JavaBuildpack::VersionResolver.resolve('1.6.0_05+', nil, VERSIONS) }.to raise_error
99106
end
100107

101108
it 'should raise an exception when the qualifier is not letter, number, or hyphen' do
102-
expect { JavaBuildpack::VersionResolver.resolve('1.6.0_?', VERSIONS) }.to raise_error
103-
expect { JavaBuildpack::VersionResolver.resolve('1.6.0__5', VERSIONS) }.to raise_error
104-
expect { JavaBuildpack::VersionResolver.resolve('1.6.0_A.', VERSIONS) }.to raise_error
109+
expect { JavaBuildpack::VersionResolver.resolve('1.6.0_?', nil, VERSIONS) }.to raise_error
110+
expect { JavaBuildpack::VersionResolver.resolve('1.6.0__5', nil, VERSIONS) }.to raise_error
111+
expect { JavaBuildpack::VersionResolver.resolve('1.6.0_A.', nil, VERSIONS) }.to raise_error
105112
end
106113

107114
it 'should raise an exception when a major version wildcard is folowed by anything' do
108-
expect { JavaBuildpack::VersionResolver.resolve('+.6.0_26', VERSIONS) }.to raise_error
115+
expect { JavaBuildpack::VersionResolver.resolve('+.6.0_26', nil, VERSIONS) }.to raise_error
109116
end
110117

111118
it 'should raise an exception when a minor version wildcard is folowed by anything' do
112-
expect { JavaBuildpack::VersionResolver.resolve('1.+.0_26', VERSIONS) }.to raise_error
119+
expect { JavaBuildpack::VersionResolver.resolve('1.+.0_26', nil, VERSIONS) }.to raise_error
113120
end
114121

115122
it 'should raise an exception when a micro version wildcard is folowed by anything' do
116-
expect { JavaBuildpack::VersionResolver.resolve('1.6.+_26', VERSIONS) }.to raise_error
123+
expect { JavaBuildpack::VersionResolver.resolve('1.6.+_26', nil, VERSIONS) }.to raise_error
117124
end
118125

119126
it 'should raise an exception when too many components are specified' do
120-
expect { JavaBuildpack::VersionResolver.resolve('1.6.0.25', VERSIONS) }.to raise_error
121-
expect { JavaBuildpack::VersionResolver.resolve('1.6.0.25_27', VERSIONS) }.to raise_error
127+
expect { JavaBuildpack::VersionResolver.resolve('1.6.0.25', nil, VERSIONS) }.to raise_error
128+
expect { JavaBuildpack::VersionResolver.resolve('1.6.0.25_27', nil, VERSIONS) }.to raise_error
122129
end
123130

124131
it 'should raise an exception when not enough components are specified' do
125-
expect { JavaBuildpack::VersionResolver.resolve('_25', VERSIONS) }.to raise_error
132+
expect { JavaBuildpack::VersionResolver.resolve('_25', nil, VERSIONS) }.to raise_error
126133
end
127134

128135
it 'should raise an exception when a wildcard is specified in the versions collection' do
129-
expect { JavaBuildpack::VersionResolver.resolve('1.6.0_25', ['+']) }.to raise_error
136+
expect { JavaBuildpack::VersionResolver.resolve('1.6.0_25', nil, ['+']) }.to raise_error
130137
end
131138

132139
it 'should raise an exception when a version ends with a component separator' do
133-
expect { JavaBuildpack::VersionResolver.resolve('1.', ['1.']) }.to raise_error
134-
expect { JavaBuildpack::VersionResolver.resolve('1.7.', ['1.7.']) }.to raise_error
135-
expect { JavaBuildpack::VersionResolver.resolve('1.7.0_', ['1.7.0_']) }.to raise_error
140+
expect { JavaBuildpack::VersionResolver.resolve('1.', nil, ['1.']) }.to raise_error
141+
expect { JavaBuildpack::VersionResolver.resolve('1.7.', nil, ['1.7.']) }.to raise_error
142+
expect { JavaBuildpack::VersionResolver.resolve('1.7.0_', nil, ['1.7.0_']) }.to raise_error
136143
end
137144

138145
end

0 commit comments

Comments
 (0)