Skip to content

Commit b4c5660

Browse files
committed
50171283-externalise-jre-configuration to master
[Completes #50171283]
2 parents fbe9af6 + 7594b84 commit b4c5660

25 files changed

+682
-287
lines changed

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@ GEM
22
remote: https://rubygems.org/
33
specs:
44
diff-lcs (1.2.4)
5-
multi_json (1.7.3)
5+
multi_json (1.7.4)
66
rake (10.0.4)
7-
redcarpet (2.2.2)
7+
redcarpet (2.3.0)
88
rspec (2.13.0)
99
rspec-core (~> 2.13.0)
1010
rspec-expectations (~> 2.13.0)

README.md

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,34 +7,76 @@
77

88
[cf]: http://www.cloudfoundry.com
99

10-
11-
# Configuration
12-
The buildpack allows you to configure the both the vendor and version of the Java runtime your application should use. To configure these, you can either put a `system.properties` file into your pushed artifact, or specify environment variables for your application. By default the **OpenJDK 7** Java runtime is chosen.
10+
# Buildpack Users
11+
The buildpack allows you to configure the both the vendor and version of the Java runtime your application should use. To configure these, you can put a `system.properties` file into your pushed artifact.
1312

1413
## `system.properties`
1514
If a `system.properties` file exists anywhere within your artifact's filesystem and the following properties have been set, they will be read and used to select the Java runtime for your application:
1615

17-
| Name | Description
16+
| Name | Description
1817
| ---- | -----------
19-
| `java.runtime.vendor` | The vendor of the Java runtime to use. Legal values are `oracle` or `openjdk`.
20-
| `java.runtime.version` | The version of the Java runtime to use. The legal values are dependent on the vendor, but are typically `6`, `7`, `8`, `1.6`, `1.7`, and `1.8` are acceptable.
18+
| `java.runtime.vendor` | The vendor of the Java runtime to use. The legal values are defined by the keys in [`config/jres.yml`][jres_yml].
19+
| `java.runtime.version` | The version of the Java runtime to use. The legal values are defined by the keys in [`index.yml`][index_yml]
2120

2221
An example `system.properties` file would to contain the following:
2322
```java
2423
java.runtime.vendor=openjdk
25-
java.runtime.version=8
24+
java.runtime.version=1.7.0_21
2625
```
26+
## JRE Version Syntax and Ordering
27+
JREs versions are composed of major, minor, micro, and optional qualifier parts (`<major>.<minor>.<micro>[_<qualifier>]`). The major, minor, and micro parts must be numeric. The qualifier part is composed of letters, digits, and hyphens. The lexical ordering of the qualifier is:
2728

28-
## Environment Variables
29-
If the following environment variables have been set, they will be read and used to select the Java runtime for your application:
29+
1. hyphen
30+
2. lowercase letters
31+
3. uppercase letters
32+
4. digits
3033

31-
| Name | Description
32-
| ---- | -----------
33-
| `JAVA_RUNTIME_VENDOR` | The vendor of the Java runtime to use. Legal values are `oracle` or `openjdk`.
34-
| `JAVA_RUNTIME_VERSION` | The version of the Java runtime to use. The legal values are dependent on the vendor, but are typically `6`, `7`, `8`, `1.6`, `1.7`, and `1.8` are acceptable.
34+
## JRE Version Wildcards
35+
In addition to declaring a specific version of JRE to use, you can also specify a bounded range of JRES to use. Appending the `+` symbol to a version prefix chooses the latest JRE that begins with the prefix.
36+
37+
| Example | Description
38+
| ------- | -----------
39+
| `1.+` | Selects the greatest available version less than `2.0.0`.
40+
| `1.7.+` | Selects the greatest available version less than `1.8.0`.
41+
| `1.7.0_+` | Selects the greatest available version less than `1.7.1`. Use this syntax to stay up to date with the latest security releases in a particular version.
42+
43+
## Default JRE
44+
If the user does not specify a JRE vendor and version, a JRE is selected automatically. The selection algorithm is as follows:
45+
46+
1. If a single vendor is available, it is selected. If zero or more than one vendor is available, the buildpack will fail.
47+
2. The latest version of JRE for the selected vendor is chosen.
48+
49+
[jres_yml]: config/jres.yml
50+
[index_yml]: http://jres.gopivotal.com.s3.amazonaws.com/lucid/x86_64/openjdk/index.yml
51+
52+
53+
# Buildpack Developers
54+
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.
55+
56+
## 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:
3558

36-
To set these properties for your application, do the following:
3759
```plain
38-
cf set-env my-app JAVA_RUNTIME_VENDOR openjdk
39-
cf set-env my-app JAVA_RUNTIME_VERSION 8
60+
<vendor name>: <JRE repository root URI>
4061
```
62+
63+
The JRE repository root must contain a `/index.yml` file ([example][index_yml]). This file is also [YAML][yaml] formatted with the following syntax:
64+
65+
```plain
66+
<JRE version>: <path relative to JRE repository root>
67+
```
68+
69+
The JRES uploaded to the repository must be gzipped TAR files and have no top-level directory ([example][example_jre]).
70+
71+
An example filesystem might look like:
72+
73+
```plain
74+
/index.yml
75+
/openjdk-1.6.0_27.tar.gz
76+
/openjdk-1.7.0_21.tar.gz
77+
/openjdk-1.8.0_M7.tar.gz
78+
```
79+
80+
[openjdk]: http://openjdk.java.net
81+
[yaml]: http://www.yaml.org
82+
[example_jre]: http://jres.gopivotal.com.s3.amazonaws.com/lucid/x86_64/openjdk/openjdk-1.8.0_M7.tar.gz

config/jres.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Cloud Foundry Java Buildpack
2+
# Copyright (c) 2013 the original author or authors.
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+
# Configuration for JRE repositories keyed by vendor
17+
---
18+
openjdk: "http://jres.gopivotal.com.s3.amazonaws.com/lucid/x86_64/openjdk"

lib/java_buildpack/compile.rb

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,9 @@
1414
# limitations under the License.
1515

1616
require 'java_buildpack/jre_properties'
17-
require 'java_buildpack/jre_selector'
1817
require 'java_buildpack/utils/format_duration'
19-
require 'java_buildpack/utils/os'
2018
require 'open-uri'
19+
require 'tempfile'
2120

2221
module JavaBuildpack
2322

@@ -31,9 +30,8 @@ class Compile
3130
# @param [String] app_cache_dir The application cache directory used during compilation
3231
def initialize(app_dir, app_cache_dir)
3332
@app_dir = app_dir
33+
@app_cache_dir = app_cache_dir
3434
@jre_properties = JreProperties.new(app_dir)
35-
jre_selector = JreSelector.new
36-
@uri = jre_selector.uri(@jre_properties.vendor, @jre_properties.version)
3735
end
3836

3937
# The execution entry point for detection. This method is responsible for identifying all of the components that are
@@ -42,11 +40,21 @@ def initialize(app_dir, app_cache_dir)
4240
# @return [void]
4341
def run
4442
download_start_time = Time.now
45-
print "-----> Downloading #{@jre_properties.vendor} #{@jre_properties.version} JRE from #{@uri} "
43+
print "-----> Downloading #{@jre_properties.vendor} #{@jre_properties.version} JRE from #{@jre_properties.uri} "
44+
45+
file = Tempfile.new('jre', @app_cache_dir)
46+
begin
47+
open(@jre_properties.uri) do |stream|
48+
IO.copy_stream(stream, file)
49+
puts "(#{(Time.now - download_start_time).duration})"
50+
end
51+
52+
file.close
4653

47-
open(@uri) do |file| # Use a global cache when available
48-
puts "(#{(Time.now - download_start_time).duration})"
4954
expand file
55+
ensure
56+
file.close
57+
file.unlink
5058
end
5159
end
5260

@@ -59,26 +67,15 @@ def expand(file)
5967
print "-----> Expanding JRE to #{JAVA_HOME} "
6068

6169
java_home = File.join @app_dir, JAVA_HOME
62-
`rm -rf #{java_home}`
63-
`mkdir -p #{java_home}`
64-
65-
expand_tar file, java_home
70+
system "rm -rf #{java_home}"
71+
system "mkdir -p #{java_home}"
72+
system "tar xzf #{file.path} -C #{java_home} --strip 1 2>&1"
6673

6774
puts "(#{(Time.now - expand_start_time).duration})"
6875
end
6976

7077
def expand_tar(file, java_home)
71-
`tar xzf #{file.path} -C #{java_home} --strip 1 2>&1`
72-
end
73-
74-
def expand_deb(file, java_home)
75-
if OS.linux?
76-
filter = '--wildcards "./usr/lib/jvm/java-*/*"'
77-
else
78-
filter = '"./usr/lib/jvm/java-*/*"'
79-
end
8078

81-
`tar xzOf #{file.path} data.tar.gz | tar xz -C #{java_home} --strip 5 #{filter} 2>&1`
8279
end
8380

8481
end

lib/java_buildpack/detect.rb

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
# limitations under the License.
1515

1616
require 'java_buildpack/jre_properties'
17-
require 'java_buildpack/jre_selector'
1817

1918
module JavaBuildpack
2019

@@ -26,8 +25,6 @@ class Detect
2625
# @param [String] app_dir The application directory used during detection
2726
def initialize(app_dir)
2827
@jre_properties = JreProperties.new(app_dir)
29-
# Diagnose invalid vendor or version.
30-
JreSelector.new.uri(@jre_properties.vendor, @jre_properties.version)
3128
end
3229

3330
# The execution entry point for detection. This method is responsible for identifying all of the components that are

lib/java_buildpack/jre_properties.rb

Lines changed: 25 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -13,75 +13,57 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16-
require 'java_buildpack/utils/properties'
16+
17+
require 'java_buildpack/utils/value_resolver'
18+
require 'java_buildpack/vendor_resolver'
19+
require 'java_buildpack/version_resolver'
20+
require 'open-uri'
21+
require 'yaml'
22+
1723

1824
module JavaBuildpack
1925

2026
# A class encapsulating the JRE properties specified by the user.
2127
class JreProperties
2228

23-
DEFAULT_VENDOR = 'openjdk'
24-
2529
# @!attribute [r] vendor
26-
# @return [String] the JRE vendor requested by the user
30+
# @return [String] the resolved JRE vendor based on user input
2731
# @!attribute [r] version
28-
# @return [String] the JRE version requested by the user
29-
attr_reader :vendor, :version
32+
# @return [String] the resolved JRE version based on user input
33+
# @!attribute [r] uri
34+
# @return [String] the resolved JRE URI based on user input
35+
attr_reader :vendor, :version, :uri
3036

3137
# Creates a new instance, passing in the application directory used during release
3238
#
3339
# @param [String] app_dir The application to inspect for values specified by the user
3440
def initialize(app_dir)
35-
properties = system_properties(app_dir)
41+
value_resolver = ValueResolver.new(app_dir)
3642

37-
@vendor = configured_vendor properties
38-
@vendor = DEFAULT_VENDOR if @vendor.nil?
43+
candidate_vendor = value_resolver.resolve(ENV_VAR_VENDOR, SYS_PROP_VENDOR)
44+
candidate_version = value_resolver.resolve(ENV_VAR_VERSION, SYS_PROP_VERSION)
3945

40-
@version = configured_version properties
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]}"
4152
end
4253

4354
private
4455

45-
SYSTEM_PROPERTIES = 'system.properties'
46-
4756
ENV_VAR_VENDOR = 'JAVA_RUNTIME_VENDOR'
4857

49-
PROP_KEY_VENDOR = 'java.runtime.vendor'
50-
5158
ENV_VAR_VERSION = 'JAVA_RUNTIME_VERSION'
5259

53-
PROP_KEY_VERSION = 'java.runtime.version'
60+
INDEX_PATH = '/index.yml'
5461

55-
def system_properties(app_dir)
56-
candidates = Dir["#{app_dir}/**/#{SYSTEM_PROPERTIES}"]
62+
JRES_YAML_FILE = 'config/jres.yml'
5763

58-
if candidates.length > 1
59-
raise "More than one system.properties file found: #{candidates}"
60-
end
64+
SYS_PROP_VENDOR = 'java.runtime.vendor'
6165

62-
if candidates[0]
63-
Properties.new(candidates[0])
64-
else
65-
nil
66-
end
67-
end
66+
SYS_PROP_VERSION = 'java.runtime.version'
6867

69-
def configured_vendor(properties)
70-
resolve ENV_VAR_VENDOR, PROP_KEY_VENDOR, properties
71-
end
72-
73-
def configured_version(properties)
74-
resolve ENV_VAR_VERSION, PROP_KEY_VERSION, properties
75-
end
76-
77-
def resolve(env_var, prop_key, properties, default = nil)
78-
value = ENV[env_var]
79-
80-
if value.nil? && !properties.nil?
81-
value = properties[prop_key]
82-
end
83-
84-
value
85-
end
8668
end
8769
end

lib/java_buildpack/jre_selector.rb

Lines changed: 0 additions & 56 deletions
This file was deleted.

lib/java_buildpack/release.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414
# limitations under the License.
1515

1616
require 'java_buildpack/jre_properties'
17-
require 'java_buildpack/jre_selector'
18-
require 'java_buildpack/utils/properties'
1917
require 'yaml'
2018

2119
module JavaBuildpack
@@ -29,9 +27,7 @@ class Release
2927
def initialize(app_dir)
3028
@app_dir = app_dir
3129

32-
# Diagnose invalid vendor or version.
33-
jre_properties = JreProperties.new(app_dir)
34-
JreSelector.new.uri(jre_properties.vendor, jre_properties.version)
30+
JreProperties.new(app_dir)
3531
end
3632

3733
# The execution entry point for release. This method is responsible for generating a payload describing the execution

0 commit comments

Comments
 (0)