metafacture-runner/src/main/scripts/flux.sh
#!/bin/bash
#
# Copyright 2017, 2018 Christoph Böhme
#
# 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.
#

# `cd` is used with a relative path in this script. We may
# end in an unexpected location if CDPATH is not empty.
unset CDPATH

# This script uses extended regular expressions in sed. As
# there are two ways to enable them, we need to find out what
# the installed version of sed supports:
if echo "" | sed -r "" > /dev/null 2>&1 ; then
    extended_regexp="-r"
elif echo "" | sed -E "" > /dev/null 2>&1 ; then
    extended_regexp="-E"
else
    echo "Error: sed does not seem to support extended regular expressions (neither -r nor -E works)" >&2
    exit 2
fi

if [ -z "$BASH_SOURCE" ] ; then
    echo "Error: cannot determine script location (\$BASH_SOURCE is not set)" >&2
    exit 2
fi
# If a symbolic link is used to invoke this script this link
# needs to be resolved in order to find the directory where
# the actual script file lives. Several tools exist for
# resolving symbolic links. However, none of these tools is
# available on all platforms. Hence, we try different ones
# until we succeed.
if [ -L "$BASH_SOURCE" ] ; then
    script_file=$( realpath "$BASH_SOURCE" 2> /dev/null ) ||
    script_file=$( readlink -f "$BASH_SOURCE" 2> /dev/null ) ||
    script_file=$(
        file=$BASH_SOURCE
        while [ -L "$file" ] ; do
            cd "$( dirname "$file" )"
            link_name=$( basename "$file" )
            file=$( readlink "$link_name" 2> /dev/null ) ||
            file=$( ls -ld "$link_name" | sed "s/^.\+ -> \(.\+\)$/\1/g" )
        done
        cd "$( dirname "$file" )"
        echo "$( pwd )/$( basename "$file" )"
    )
else
    script_file=$BASH_SOURCE
fi
# Remove script file name from the path and make sure
# that the path is absolute:
METAFACTURE_HOME=$( cd "$( dirname "$script_file" )" ; pwd )

# Fix path if running under cygwin:
if uname | grep -iq cygwin ; then
    METAFACTURE_HOME=$( cygpath -am "$METAFACTURE_HOME" )
fi

# Use the java command available on the path by default.
# Define FLUX_JAVA_BIN in your environment to use a
# different executable.
if [ -z "$FLUX_JAVA_BIN" ] ; then
    FLUX_JAVA_BIN=java
fi

java_opts_file="$METAFACTURE_HOME/config/java-options.conf"
jar_file="$METAFACTURE_HOME/@jarfile@"

# Load java options from configuration file. Lines starting
# with # are treated as comments. Empty lines are ignored.
java_opts=$( cat "$java_opts_file" | grep -v "^#" | tr "\n\r" "  " )

# Substitute environment variables. Undefined variables
# remain in the configuration. Since FLUX_JAVA_OPTIONS is
# included in the configuration by default we make sure that
# it can always be substituted.
if [ -z "$FLUX_JAVA_OPTIONS" ] ; then
    FLUX_JAVA_OPTIONS=
fi
# This sed script turns the output of set into a sed script
# which replaces the dollar prefixed name of each environment
# variable with its value. As the output of the set command
# is a list of variables followed by a list of functions, the
# script terminates at the first line which appears not to be
# a variable definition:
vars_to_script=$( cat <<'EOF'
    s/^[^=]*$//g ;                          # is this not a variable definition?
                                            # then jump to quit
    t quit
    s/\\/\\\\/g ;                           # otherwise escape backslashes,
    s/!/\\!/g ;                             # escape exclamation marks,
    s/='(.*)'$/=\1/ ;                       # remove quotes,
    s/^([^=]+)=(.*)$/s!\\$\1!\2!g ; /g ;    # convert to sed regexp command
                                            # and continue with next line
    b
    : quit
    q
EOF
)
substitute_vars_script=$( set | sed $extended_regexp "$vars_to_script" )
# Substitute environment variables in the java options:
java_opts=$( echo "$java_opts" | sed "$substitute_vars_script")

# Turn java options string into an array to allow passing
# the options as command parameters. Options may be partially
# quoted with single or double quotes and may contain
# escape sequences. Quotes are removed after splitting because
# the shell quotes the parameters again:
option_pattern="[^\"' ]*(\"[^\"\\]*(\\\\.[^\"\\]*)*\"|'[^'\\]*(\\\\.[^'\\]*)*'|\\.[^\"' ]*)*"
remove_quotes="s/(^[\"'])|(([^\\])[\"'])/\3/g"
java_opts_array=()
while read line ; do
    line=$( echo "$line" | sed $extended_regexp "$remove_quotes" )
    java_opts_array+=("$line")
done < <( echo "$java_opts" | grep -Eo "$option_pattern" )

# Start flux:
command=$(echo "$FLUX_JAVA_BIN" "${java_opts_array[@]}" -jar "$jar_file" "$@")
$command
