#!/usr/bin/env bash # Copyright 2014 The Bazel Authors. All rights reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # This script was generated from java_stub_template.txt. Please # don't edit it directly. # # If present, these flags should either be at the beginning of the command # line, or they should be wrapped in a --wrapper_script_flag=FLAG argument. # # --debug Launch the JVM in remote debugging mode listening # --debug= to the specified port or the port set in the # DEFAULT_JVM_DEBUG_PORT environment variable (e.g. # 'export DEFAULT_JVM_DEBUG_PORT=8000') or else the # default port of 5005. The JVM starts suspended # unless the DEFAULT_JVM_DEBUG_SUSPEND environment # variable is set to 'n'. # --main_advice= Run an alternate main class with the usual main # program and arguments appended as arguments. # --main_advice_classpath= # Prepend additional class path entries. # --jvm_flag= Pass to the "java" command itself. # may contain spaces. Can be used multiple times. # --jvm_flags= Pass space-separated flags to the "java" command # itself. Can be used multiple times. # --singlejar Start the program from the packed-up deployment # jar rather than from the classpath. # --print_javabin Print the location of java executable binary and exit. # --classpath_limit= # Specify the maximum classpath length. If the classpath # is shorter, this script passes it to Java as a command # line flag, otherwise it creates a classpath jar. # # The remainder of the command line is passed to the program. set -o posix # Make it easy to insert 'set -x' or similar commands when debugging problems with this script. eval "$JAVA_STUB_DEBUG" # Prevent problems where the caller has exported CLASSPATH, causing our # computed value to be copied into the environment and double-counted # against the argv limit. unset CLASSPATH JVM_FLAGS_CMDLINE=() # Processes an argument for the wrapper. Returns 0 if the given argument # was recognized as an argument for this wrapper, and 1 if it was not. function process_wrapper_argument() { case "$1" in --debug) JVM_DEBUG_PORT="${DEFAULT_JVM_DEBUG_PORT:-5005}" ;; --debug=*) JVM_DEBUG_PORT="${1#--debug=}" ;; --main_advice=*) MAIN_ADVICE="${1#--main_advice=}" ;; --main_advice_classpath=*) MAIN_ADVICE_CLASSPATH="${1#--main_advice_classpath=}" ;; --jvm_flag=*) JVM_FLAGS_CMDLINE+=( "${1#--jvm_flag=}" ) ;; --jvm_flags=*) JVM_FLAGS_CMDLINE+=( ${1#--jvm_flags=} ) ;; --singlejar) SINGLEJAR=1 ;; --print_javabin) PRINT_JAVABIN=1 ;; --classpath_limit=*) CLASSPATH_LIMIT="${1#--classpath_limit=}" echo "$CLASSPATH_LIMIT" | grep -q '^[0-9]\+$' || \ die "ERROR: $self failed, --classpath_limit is not a number" ;; *) return 1 ;; esac return 0 } die() { printf "%s: $1\n" "$0" "${@:2}" >&2 exit 1 } # Windows function is_windows() { [[ "${OSTYPE}" =~ msys* ]] || [[ "${OSTYPE}" =~ cygwin* ]] } # macOS function is_macos() { [[ "${OSTYPE}" =~ darwin* ]] } # Parse arguments sequentially until the first unrecognized arg is encountered. # Scan the remaining args for --wrapper_script_flag=X options and process them. ARGS=() for ARG in "$@"; do if [[ "$ARG" == --wrapper_script_flag=* ]]; then process_wrapper_argument "${ARG#--wrapper_script_flag=}" \ || die "invalid wrapper argument '%s'" "$ARG" elif [[ "${#ARGS}" -gt 0 ]] || ! process_wrapper_argument "$ARG"; then ARGS+=( "$ARG" ) fi done # Find our runfiles tree. We need this to construct the classpath # (unless --singlejar was passed). # # Call this program X. X was generated by a java_binary or java_test rule. # X may be invoked in many ways: # 1a) directly by a user, with $0 in the output tree # 1b) via 'bazel run' (similar to case 1a) # 2) directly by a user, with $0 in X's runfiles tree # 3) by another program Y which has a data dependency on X, with $0 in Y's runfiles tree # 4) via 'bazel test' # 5) by a genrule cmd, with $0 in the output tree # 6) case 3 in the context of a genrule # # For case 1, $0 will be a regular file, and the runfiles tree will be # at $0.runfiles. # For case 2, $0 will be a symlink to the file seen in case 1. # For case 3, we use Y's runfiles tree, which will be a superset of X's. # For case 4, $JAVA_RUNFILES and $TEST_SRCDIR should already be set. # Case 5 is handled like case 1. # Case 6 is handled like case 3. # If we are running on Windows, convert the windows style path # to unix style for detecting runfiles path. if is_windows; then self=$(cygpath --unix "$0") else self="$0" fi if [[ "$self" != /* ]]; then self="$PWD/$self" fi if [[ "$SINGLEJAR" != 1 || "%needs_runfiles%" == 1 ]]; then if [[ -z "$JAVA_RUNFILES" ]]; then while true; do if [[ -e "$self.runfiles" ]]; then JAVA_RUNFILES="$self.runfiles" break fi if [[ $self == *.runfiles/* ]]; then JAVA_RUNFILES="${self%.runfiles/*}.runfiles" break fi if [[ ! -L "$self" ]]; then break fi readlink="$(readlink "$self")" if [[ "$readlink" = /* ]]; then self="$readlink" else # resolve relative symlink self="${self%/*}/$readlink" fi done if [[ -n "$JAVA_RUNFILES" ]]; then export TEST_SRCDIR=${TEST_SRCDIR:-$JAVA_RUNFILES} elif [[ -f "${self}_deploy.jar" && "%needs_runfiles%" == 0 ]]; then SINGLEJAR=1; else die 'Cannot locate runfiles directory. (Set $JAVA_RUNFILES to inhibit searching.)' fi fi fi # If we are running on Windows, we need a windows style runfiles path for constructing CLASSPATH if is_windows; then JAVA_RUNFILES=$(cygpath --windows "$JAVA_RUNFILES") fi export JAVA_RUNFILES export RUNFILES_MANIFEST_FILE="${JAVA_RUNFILES}/MANIFEST" export RUNFILES_MANIFEST_ONLY=%runfiles_manifest_only% if [ -z "$RUNFILES_MANIFEST_ONLY" ]; then function rlocation() { if [[ "$1" = /* ]]; then echo $1 else echo "$(dirname $RUNFILES_MANIFEST_FILE)/$1" fi } else if ! is_macos; then # Read file into my_array oifs=$IFS IFS=$'\n' my_array=( $(sed -e 's/\r//g' "$RUNFILES_MANIFEST_FILE") ) IFS=$oifs # Process each runfile line into a [key,value] entry in runfiles_array # declare -A is not supported on macOS because an old version of bash is used. declare -A runfiles_array for line in "${my_array[@]}" do line_split=($line) runfiles_array[${line_split[0]}]=${line_split[@]:1} done fi function rlocation() { if [[ "$1" = /* ]]; then echo $1 else if is_macos; then # Print the rest of line after the first space # First, set the first column to empty and print rest of the line # Second, use a trick of awk to remove leading and trailing spaces. echo $(grep "^$1 " $RUNFILES_MANIFEST_FILE | awk '{ $1=""; print }' | awk '{ $1=$1; print }') else echo ${runfiles_array[$1]} fi fi } fi if is_macos || [[ ${OSTYPE} == "freebsd" ]]; then function md5func() { md5 -q $@ ; } else function md5func() { md5sum $@ | awk '{print $1}' ; } fi # Set JAVABIN to the path to the JVM launcher. %javabin% if [[ "$PRINT_JAVABIN" == 1 || "%java_start_class%" == "--print_javabin" ]]; then echo -n "$JAVABIN" exit 0 fi if [[ "$SINGLEJAR" == 1 ]]; then CLASSPATH="${self}_deploy.jar" # Check for the deploy jar now. If it doesn't exist, we can print a # more helpful error message than the JVM. [[ -r "$CLASSPATH" ]] \ || die "Option --singlejar was passed, but %s does not exist.\n (You may need to build it explicitly.)" "$CLASSPATH" else # Create the shortest classpath we can, by making it relative if possible. RUNPATH="${JAVA_RUNFILES}/%workspace_prefix%" RUNPATH="${RUNPATH#$PWD/}" CLASSPATH=%classpath% fi # Export the locations which will be used to find the location of the classes from the classpath file. export SELF_LOCATION="$self" export CLASSLOADER_PREFIX_PATH="${RUNPATH}" # If using Jacoco in offline instrumentation mode, the CLASSPATH contains instrumented files. # We need to make the metadata jar with uninstrumented classes available for generating # the lcov-compatible coverage report, and we don't want it on the classpath. %set_jacoco_metadata% %set_jacoco_main_class% %set_jacoco_java_runfiles_root% if [[ -n "$JVM_DEBUG_PORT" ]]; then JVM_DEBUG_SUSPEND=${DEFAULT_JVM_DEBUG_SUSPEND:-"y"} JVM_DEBUG_FLAGS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=${JVM_DEBUG_SUSPEND},address=${JVM_DEBUG_PORT}" if [[ "$PERSISTENT_TEST_RUNNER" == "true" ]]; then JVM_DEBUG_FLAGS+=",quiet=y" fi fi if [[ -n "$MAIN_ADVICE_CLASSPATH" ]]; then CLASSPATH="${MAIN_ADVICE_CLASSPATH}:${CLASSPATH}" fi # Check if TEST_TMPDIR is available to use for scratch. if [[ -n "$TEST_TMPDIR" && -d "$TEST_TMPDIR" ]]; then JVM_FLAGS+=" -Djava.io.tmpdir=$TEST_TMPDIR" fi ARGS=( ${JVM_DEBUG_FLAGS} ${JVM_FLAGS} %jvm_flags% "${JVM_FLAGS_CMDLINE[@]}" ${MAIN_ADVICE} %java_start_class% "${ARGS[@]}") function create_and_run_classpath_jar() { # Build class path as one single string separated by spaces MANIFEST_CLASSPATH="" if is_windows; then IFS=';' URI_PREFIX="file:/" # e.g. "file:/C:/temp/foo.jar" else IFS=':' URI_PREFIX="file:$(pwd)/" # e.g. "file:/usr/local/foo.jar" fi for x in $CLASSPATH; do # Add file:/ prefix and escaped space characters, it should be a URI. x="${URI_PREFIX}${x// /%20}" MANIFEST_CLASSPATH="$MANIFEST_CLASSPATH $x" done unset IFS # Create manifest file MANIFEST_FILE="$(mktemp -t XXXXXXXX.jar_manifest)" ( echo "Manifest-Version: 1.0" CLASSPATH_LINE="Class-Path:$MANIFEST_CLASSPATH" # No line in the MANIFEST.MF file may be longer than 72 bytes. # A space prefix indicates the line is still the content of the last attribute. for ((i = 0; i < "${#CLASSPATH_LINE}"; i += 71)); do PREFIX=" " if ((i == 0)); then PREFIX="" fi echo "$PREFIX${CLASSPATH_LINE:$i:71}" done echo "Created-By: Bazel" ) >$MANIFEST_FILE # Create classpath JAR file MANIFEST_JAR_FILE="$(mktemp -t XXXXXXXX-classpath.jar)" if is_windows; then MANIFEST_JAR_FILE="$(cygpath --windows "$MANIFEST_JAR_FILE")" MANIFEST_FILE="$(cygpath --windows "$MANIFEST_FILE")" fi JARBIN="${JARBIN:-$(rlocation "$1")}" $JARBIN cvfm "$MANIFEST_JAR_FILE" "$MANIFEST_FILE" >/dev/null || \ die "ERROR: $self failed because $JARBIN failed" # Execute JAVA command $JAVABIN -classpath "$MANIFEST_JAR_FILE" "${ARGS[@]}" exit_code=$? rm -f "$MANIFEST_FILE" rm -f "$MANIFEST_JAR_FILE" exit $exit_code } # If the user didn't specify a --classpath_limit, use the default value. if [ -z "$CLASSPATH_LIMIT" ]; then # Windows per-arg limit MAX_ARG_STRLEN == 8k # Linux per-arg limit MAX_ARG_STRLEN == 128k is_windows && CLASSPATH_LIMIT=7000 || CLASSPATH_LIMIT=120000 fi if is_windows && (("${#CLASSPATH}" > ${CLASSPATH_LIMIT} )); then create_and_run_classpath_jar "local_jdk/bin/jar.exe" elif (("${#CLASSPATH}" > ${CLASSPATH_LIMIT})); then create_and_run_classpath_jar "local_jdk/bin/jar" else exec $JAVABIN -classpath $CLASSPATH "${ARGS[@]}" fi