blob: 674961c2dafb1f787f9faf8571d85791e94e9b36 [file] [log] [blame]
#!/usr/bin/env bash
#
# Install JDK for Linux and Mac OS
#
# This script determines the most recent early-access build number,
# downloads the JDK archive to the user home directory and extracts
# it there.
#
# Exported environment variables (when sourcing this script)
#
# JAVA_HOME is set to the extracted JDK directory
# PATH is prepended with ${JAVA_HOME}/bin
#
# (C) 2018 Christian Stein
#
# https://github.com/sormuras/bach/blob/master/install-jdk.sh
#
set -o errexit
#set -o nounset # https://github.com/travis-ci/travis-ci/issues/5434
#set -o xtrace
function initialize() {
readonly script_name="$(basename "${BASH_SOURCE[0]}")"
readonly script_version='2018-10-17'
dry=false
silent=false
verbose=false
emit_java_home=false
feature='ea'
license='GPL'
os='?'
url='?'
workspace="${HOME}"
target='?'
cacerts=false
}
function usage() {
cat << EOF
Usage: ${script_name} [OPTION]...
Download and extract the latest-and-greatest JDK from java.net or Oracle.
Version: ${script_version}
Options:
-h|--help Displays this help
-d|--dry-run Activates dry-run mode
-s|--silent Displays no output
-e|--emit-java-home Print value of "JAVA_HOME" to stdout (ignores silent mode)
-v|--verbose Displays verbose output
-f|--feature 9|10|...|ea JDK feature release number, defaults to "ea"
-l|--license GPL|BCL License defaults to "GPL", BCL also indicates OTN-LA for Oracle Java SE
-o|--os linux-x64|osx-x64 Operating system identifier (works best with GPL license)
-u|--url "https://..." Use custom JDK archive (provided as .tar.gz file)
-w|--workspace PATH Working directory defaults to \${HOME} [${HOME}]
-t|--target PATH Target directory, defaults to first component of the tarball
-c|--cacerts Link system CA certificates (currently only Debian/Ubuntu is supported)
EOF
}
function script_exit() {
if [[ $# -eq 1 ]]; then
printf '%s\n' "$1"
exit 0
fi
if [[ $# -eq 2 && $2 =~ ^[0-9]+$ ]]; then
printf '%b\n' "$1"
exit "$2"
fi
script_exit 'Invalid arguments passed to script_exit()!' 2
}
function say() {
if [[ ${silent} != true ]]; then
echo "$@"
fi
}
function verbose() {
if [[ ${verbose} == true ]]; then
echo "$@"
fi
}
function parse_options() {
local option
while [[ $# -gt 0 ]]; do
option="$1"
shift
case ${option} in
-h|-H|--help)
usage
exit 0
;;
-v|-V|--verbose)
verbose=true
;;
-s|-S|--silent)
silent=true
verbose "Silent mode activated"
;;
-d|-D|--dry-run)
dry=true
verbose "Dry-run mode activated"
;;
-e|-E|--emit-java-home)
emit_java_home=true
verbose "Emitting JAVA_HOME"
;;
-f|-F|--feature)
feature="$1"
verbose "feature=${feature}"
shift
;;
-l|-L|--license)
license="$1"
verbose "license=${license}"
shift
;;
-o|-O|--os)
os="$1"
verbose "os=${os}"
shift
;;
-u|-U|--url)
url="$1"
verbose "url=${url}"
shift
;;
-w|-W|--workspace)
workspace="$1"
verbose "workspace=${workspace}"
shift
;;
-t|-T|--target)
target="$1"
verbose "target=${target}"
shift
;;
-c|-C|--cacerts)
cacerts=true
verbose "Linking system CA certificates"
;;
*)
script_exit "Invalid argument was provided: ${option}" 2
;;
esac
done
}
function determine_latest_jdk() {
local number
local curl_result
local url
verbose "Determine latest JDK feature release number"
number=9
while [[ ${number} != 99 ]]
do
url=http://jdk.java.net/${number}
curl_result=$(curl -o /dev/null --silent --head --write-out %{http_code} ${url})
if [[ ${curl_result} -ge 400 ]]; then
break
fi
verbose " Found ${url} [${curl_result}]"
latest_jdk=${number}
number=$[$number +1]
done
verbose "Latest JDK feature release number is: ${latest_jdk}"
}
function perform_sanity_checks() {
if [[ ${feature} == '?' ]] || [[ ${feature} == 'ea' ]]; then
feature=${latest_jdk}
fi
if [[ ${feature} -lt 9 ]] || [[ ${feature} -gt ${latest_jdk} ]]; then
script_exit "Expected feature release number in range of 9 to ${latest_jdk}, but got: ${feature}" 3
fi
if [[ -d "$target" ]]; then
script_exit "Target directory must not exist, but it does: $(du -hs '${target}')" 3
fi
}
function determine_url() {
local DOWNLOAD='https://download.java.net/java'
local ORACLE='http://download.oracle.com/otn-pub/java/jdk'
# Archived feature or official GA build?
case "${feature}-${license}" in
9-GPL) url="${DOWNLOAD}/GA/jdk9/9.0.4/binaries/openjdk-9.0.4_${os}_bin.tar.gz"; return;;
9-BCL) url="${ORACLE}/9.0.4+11/c2514751926b4512b076cc82f959763f/jdk-9.0.4_${os}_bin.tar.gz"; return;;
10-GPL) url="${DOWNLOAD}/GA/jdk10/10.0.2/19aef61b38124481863b1413dce1855f/13/openjdk-10.0.2_${os}_bin.tar.gz"; return;;
10-BCL) url="${ORACLE}/10.0.2+13/19aef61b38124481863b1413dce1855f/jdk-10.0.2_${os}_bin.tar.gz"; return;;
11-GPL) url="${DOWNLOAD}/GA/jdk11/13/GPL/openjdk-11.0.1_${os}_bin.tar.gz"; return;;
11-BCL) url="${ORACLE}/11.0.1+13/90cf5d8f270a4347a95050320eef3fb7/jdk-11.0.1_${os}_bin.tar.gz"; return;;
esac
# EA or RC build?
local JAVA_NET="http://jdk.java.net/${feature}"
local candidates=$(wget --quiet --output-document - ${JAVA_NET} | grep -Eo 'href[[:space:]]*=[[:space:]]*"[^\"]+"' | grep -Eo '(http|https)://[^"]+')
url=$(echo "${candidates}" | grep -Eo "${DOWNLOAD}/.+/jdk${feature}/.+/${license}/.*jdk-${feature}.+${os}_bin.tar.gz$" || true)
if [[ -z ${url} ]]; then
script_exit "Couldn't determine a download url for ${feature}-${license} on ${os}" 1
fi
}
function prepare_variables() {
if [[ ${os} == '?' ]]; then
if [[ "$OSTYPE" == "darwin"* ]]; then
os='osx-x64'
else
os='linux-x64'
fi
fi
if [[ ${url} == '?' ]]; then
determine_latest_jdk
perform_sanity_checks
determine_url
else
feature='<overridden by custom url>'
license='<overridden by custom url>'
os='<overridden by custom url>'
fi
archive="${workspace}/$(basename ${url})"
status=$(curl -o /dev/null --silent --head --write-out %{http_code} ${url})
}
function print_variables() {
cat << EOF
Variables:
feature = ${feature}
license = ${license}
os = ${os}
url = ${url}
status = ${status}
archive = ${archive}
EOF
}
function download_and_extract_and_set_target() {
local quiet='--quiet'; if [[ ${verbose} == true ]]; then quiet=''; fi
local local="--directory-prefix ${workspace}"
local remote='--timestamping --continue'
local wget_options="${quiet} ${local} ${remote}"
local tar_options="--file ${archive}"
say "Downloading JDK from ${url}..."
verbose "Using wget options: ${wget_options}"
if [[ ${license} == 'GPL' ]]; then
wget ${wget_options} ${url}
else
wget ${wget_options} --header "Cookie: oraclelicense=accept-securebackup-cookie" ${url}
fi
verbose "Using tar options: ${tar_options}"
if [[ ${target} == '?' ]]; then
tar --extract ${tar_options} -C "${workspace}"
if [[ "$OSTYPE" != "darwin"* ]]; then
target="${workspace}"/$(tar --list ${tar_options} | grep 'bin/javac' | tr '/' '\n' | tail -3 | head -1)
else
target="${workspace}"/$(tar --list ${tar_options} | head -2 | tail -1 | cut -f 2 -d '/' -)/Contents/Home
fi
else
if [[ "$OSTYPE" != "darwin"* ]]; then
mkdir --parents "${target}"
tar --extract ${tar_options} -C "${target}" --strip-components=1
else
mkdir -p "${target}"
tar --extract ${tar_options} -C "${target}" --strip-components=4 # . / <jdk> / Contents / Home
fi
fi
if [[ ${verbose} == true ]]; then
echo "Set target to: ${target}"
echo "Content of target directory:"
ls "${target}"
echo "Content of release file:"
[[ ! -f "${target}/release" ]] || cat "${target}/release"
fi
# Link to system certificates
# http://openjdk.java.net/jeps/319
# https://bugs.openjdk.java.net/browse/JDK-8196141
# TODO: Provide support for other distributions than Debian/Ubuntu
if [[ ${cacerts} == true ]]; then
mv "${target}/lib/security/cacerts" "${target}/lib/security/cacerts.jdk"
ln -s /etc/ssl/certs/java/cacerts "${target}/lib/security/cacerts"
fi
}
function main() {
initialize
say "$script_name $script_version"
parse_options "$@"
prepare_variables
if [[ ${silent} == false ]]; then print_variables; fi
if [[ ${dry} == true ]]; then exit 0; fi
download_and_extract_and_set_target
export JAVA_HOME=$(cd "${target}"; pwd)
export PATH=${JAVA_HOME}/bin:$PATH
if [[ ${silent} == false ]]; then java -version; fi
if [[ ${emit_java_home} == true ]]; then echo "${JAVA_HOME}"; fi
}
main "$@"