#!/usr/bin/env bash # # To run this script remotely type this in your shell # (where ... are the arguments you want to pass to JBang): # curl -Ls https://sh.jbang.dev | bash -s - ... # # The Java version to install when it's not installed on the system yet javaVersion=${JBANG_DEFAULT_JAVA_VERSION:-17} script_dir() { script=${BASH_SOURCE[0]} while [ -L "$script" ]; do dir=$( cd -P "$( dirname "$script" )" >/dev/null 2>&1 && pwd ) script=$(readlink "$script") [[ $script != /* ]] && script=$dir/$script done dir=$( cd -P "$( dirname "$script" )" >/dev/null 2>&1 && pwd ) echo $dir } download() { if [ -x "$(command -v curl)" ]; then curl -sLf -o "$2" "$1" retval=$? elif [ -x "$(command -v wget)" ]; then wget -q -O "$2" "$1" retval=$? else echo "Error: curl or wget not found, please make sure one of them is installed" 1>&2 exit 1 fi } unpack() { if [[ "$1" == *.tar.gz ]]; then gzip -cd "$1" | tar xf - -C "$2" retval=$? if [[ $os == mac && $retval -eq 0 ]]; then mv "$TDIR/jdks/$javaVersion.tmp/"*/Contents/Home/* "$TDIR/jdks/$javaVersion.tmp/" retval=$? else mv "$TDIR/jdks/$javaVersion.tmp/"*/* "$TDIR/jdks/$javaVersion.tmp/" fi else unzip -qq -o "$1" -d "$2" retval=$? mv "$TDIR/jdks/$javaVersion.tmp/"*/* "$TDIR/jdks/$javaVersion.tmp/" fi } javacInPath() { [[ -x "$(command -v javac)" ]] && ( [[ $os != "mac" ]] || /usr/libexec/java_home &> /dev/null ) } abs_jbang_dir=$(script_dir) # todo might vary by os so can be overwritten below libc_type=glibc file_type=tar.gz case "$(uname -s)" in Linux*) os=linux if [ -f /etc/alpine-release ]; then os=alpine-linux javaVersion=16 fi ;; Darwin*) os=mac libc_type=libc;; CYGWIN*|MINGW*|MSYS*) os=windows libc_type=c_std_lib file_type=zip;; AIX) os=aix;; *) os= esac case "$(uname -m)" in i?86) arch=x32;; x86_64|amd64) arch=x64;; aarch64) arch=aarch64;; armv7l) arch=arm;; ppc64le) arch=ppc64le;; s390x) arch=s390x;; arm64) arch=arm64;; riscv64) arch=riscv64 ;; *) ## AIX gives a machine ID for `uname -m` but it only supports ppc64 if [ "$os" = "aix" ]; then arch=ppc64 else arch= fi ;; esac ## when using cygwin fall out to just running the bat file. if [[ $os == windows && -f "$abs_jbang_dir/jbang.cmd" && "$(uname -s)" == CYGWIN* ]]; then cmd /c "$(cygpath -m "$abs_jbang_dir"/jbang.cmd)" "$@" exit $? fi if [[ -z "$JBANG_JDK_VENDOR" ]]; then if [[ "$javaVersion" -eq 8 || "$javaVersion" -eq 11 || "$javaVersion" -ge 17 ]]; then distro="temurin"; else distro="aoj"; fi else distro=$JBANG_JDK_VENDOR fi if [[ -z "$JBANG_DIR" ]]; then JBDIR="$HOME/.jbang"; else JBDIR="$JBANG_DIR"; fi if [[ -z "$JBANG_CACHE_DIR" ]]; then TDIR="$JBDIR/cache"; else TDIR="$JBANG_CACHE_DIR"; fi ## resolve application jar path from script location if [ -f "$abs_jbang_dir/jbang.jar" ]; then jarPath=$abs_jbang_dir/jbang.jar elif [ -f "$abs_jbang_dir/.jbang/jbang.jar" ]; then jarPath=$abs_jbang_dir/.jbang/jbang.jar else if [[ ! -f "$JBDIR/bin/jbang.jar" || ! -f "$JBDIR/bin/jbang" ]]; then echo "Downloading JBang $JBANG_DOWNLOAD_VERSION..." 1>&2 mkdir -p "$TDIR/urls" if [ -z "$JBANG_DOWNLOAD_VERSION" ]; then jburl="https://github.com/jbangdev/jbang/releases/latest/download/jbang.tar"; else jburl="https://github.com/jbangdev/jbang/releases/download/v$JBANG_DOWNLOAD_VERSION/jbang.tar"; fi download $jburl "$TDIR/urls/jbang.tar" if [ $retval -ne 0 ]; then echo "Error downloading JBang from $jburl" 1>&2; exit $retval; fi echo "Installing JBang..." 1>&2 rm -rf "$TDIR/urls/jbang" tar xf "$TDIR/urls/jbang.tar" -C "$TDIR/urls" if [ $retval -ne 0 ]; then echo "Error installing JBang" 1>&2; exit $retval; fi mkdir -p "$JBDIR/bin" rm -f "$JBDIR/bin/jbang" "$JBDIR/bin"/jbang.* cp -f "$TDIR/urls/jbang/bin"/* "$JBDIR/bin" fi "$JBDIR"/bin/jbang "$@" exit $? fi if [ -f "$jarPath.new" ]; then # a new jbang version was found, we replace the old one with it mv "$jarPath.new" "$jarPath" fi # Find/get a JDK unset JAVA_EXEC if [[ -n "$JAVA_HOME" ]]; then # Determine if a (working) JDK is available in JAVA_HOME if [ -x "$(command -v "$JAVA_HOME"/bin/javac)" ]; then JAVA_EXEC="$JAVA_HOME/bin/java" else echo "JAVA_HOME is set but does not seem to point to a valid Java JDK" 1>&2 fi fi if [[ -z "$JAVA_EXEC" ]]; then # Determine if a (working) JDK is available on the PATH if javacInPath; then unset JAVA_HOME JAVA_EXEC="java" elif [ -x "$JBDIR/currentjdk/bin/javac" ]; then export JAVA_HOME="$JBDIR/currentjdk" JAVA_EXEC="$JBDIR/currentjdk/bin/java" else export JAVA_HOME="$TDIR/jdks/$javaVersion" JAVA_EXEC="$JAVA_HOME/bin/java" # Check if we installed a JDK before if [ ! -d "$TDIR/jdks/$javaVersion" ]; then # If not, download and install it if [[ $os == "" ]]; then echo "Unable to download JDK, unsupported Operating System: $(uname -s)" 1>&2 exit 1 fi if [[ $arch == "" ]]; then echo "Unable to download JDK, unsupported Architecture: $(uname -m)" 1>&2 exit 1 fi mkdir -p "$TDIR/jdks" echo "Downloading JDK $javaVersion. Be patient, this can take several minutes..." 1>&2 jdkurl="https://api.foojay.io/disco/v3.0/directuris?distro=$distro&javafx_bundled=false&libc_type=$libc_type&archive_type=$file_type&operating_system=$os&package_type=jdk&version=$javaVersion&architecture=$arch&latest=available" download "$jdkurl" "$TDIR/bootstrap-jdk.$file_type" if [ $retval -ne 0 ]; then echo "Error downloading JDK" 1>&2; exit $retval; fi echo "Installing JDK $javaVersion..." 1>&2 rm -rf "$TDIR/jdks/$javaVersion.tmp/" mkdir -p "$TDIR/jdks/$javaVersion.tmp" unpack "$TDIR/bootstrap-jdk.$file_type" "$TDIR/jdks/$javaVersion.tmp" if [ $retval -ne 0 ]; then # Check if the JDK was installed properly javac -version > /dev/null 2>&1 retval=$? fi if [ $retval -ne 0 ]; then echo "Error installing JDK" 1>&2; exit $retval; fi # Activate the downloaded JDK giving it its proper name mv "$TDIR/jdks/$javaVersion.tmp" "$TDIR/jdks/$javaVersion" # Set the current JDK "${JAVA_EXEC}" -classpath "${jarPath}" dev.jbang.Main jdk default $javaVersion fi fi fi ## https://stackoverflow.com/questions/1668649/how-to-keep-quotes-in-bash-arguments ## attempt to ensure each argument keeps its original quoting ## run it using command substitution to have just the user process once jbang is done export JBANG_RUNTIME_SHELL=bash export JBANG_STDIN_NOTTY=$([ -t 0 ] && echo "false" || echo "true") output=$(CLICOLOR_FORCE=1 "${JAVA_EXEC}" ${JBANG_JAVA_OPTIONS} -classpath "${jarPath}" dev.jbang.Main "$@") err=$? if [ $err -eq 255 ]; then eval "exec $output" elif [ -n "$output" ]; then echo "$output" exit $err else exit $err fi