#!/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) 2020 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='2020-06-02' dry=false silent=false verbose=false emit_java_home=false emit_url=false feature='ea' license='GPL' # Force GPLv2+CE os='?' url='?' workspace="${HOME}" target='?' cacerts=false } function usage() { cat << EOF Usage: ${script_name} [OPTION]... Download and extract latest-and-greatest JDK from https://jdk.java.net 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) --emit-url Print value of "url" to stdout (ignores silent mode) -v|--verbose Displays verbose output -f|--feature ea|16|...|9 JDK feature release number, defaults to "ea" -o|--os linux-x64|osx-x64 Operating system identifier -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 "Emit JAVA_HOME" ;; --emit-url) emit_url=true verbose "Emit download URL" ;; -f|-F|--feature) feature="$1" verbose "feature=${feature}" shift ;; -l|-L|--license) # license="$1" say "Ignoring license option: $1 -- using GPLv2+CE by default" 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 number=15 verbose "Determine latest JDK feature release number, starting with ${number}" while [[ ${number} != 99 ]] do url="https://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 properties='https://github.com/sormuras/bach/raw/releases/11/install-jdk.properties' url=$(wget --quiet --output-document - ${properties} | grep -i "${feature}-${os}=" | awk -F "=" '{print $2}') 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='' license='' os='' fi status=$(curl -o /dev/null --silent --head --write-out %{http_code} ${url}) } function print_variables() { cat << EOF Variables: feature = ${feature} os = ${os} url = ${url} status = ${status} EOF } function download_and_extract_and_set_target() { local quiet='--quiet'; if [[ ${verbose} == true ]]; then quiet=''; fi local local="--directory-prefix ${workspace} --output-document=jdk.tar.gz" local remote='--timestamping --continue' local wget_options="${quiet} ${local} ${remote}" local tar_options="--file jdk.tar.gz" say "Downloading JDK from ${url}..." verbose "Using wget options: ${wget_options}" wget ${wget_options} ${url} if [[ ${os} == 'windows-x64' ]]; then script_exit "Extracting archives on Windows isn't supported, yet" 4 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 verbose "Set target to: ${target}" else echo "Using custom target: ${target}" 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 fi fi if [[ ${verbose} == true ]]; then echo "Content of target directory:" ls "${target}" echo "Content of release file:" [[ ! -f "${target}/release" ]] || cat "${target}/release" fi # Link to system certificates # https://openjdk.java.net/jeps/319 # https://bugs.openjdk.java.net/browse/JDK-8196141 if [[ ${cacerts} == true ]]; then local directory="${target}/lib/security/cacerts" if [[ -f "${directory}" ]]; then mv "${directory}" "${directory}.jdk" ln -s /etc/ssl/certs/java/cacerts "${directory}" else verbose "Directory ${directory} doesn't exist, didn't link system CA certificates." fi fi } function main() { initialize parse_options "$@" say "$script_name $script_version" prepare_variables if [[ ${silent} == false ]]; then print_variables; fi if [[ ${emit_url} == true ]]; then echo "${url}"; 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 -Xmx100m -version; fi if [[ ${emit_java_home} == true ]]; then echo "${JAVA_HOME}"; fi } main "$@"