#!/bin/bash
#
# Copyright (C) 2015 The Android Open Source Project
#
# 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.
#
# Version: 1.3-eng
#
set -o nounset
umask 077

#
# Settings
#
JACK_VERSION=${JACK_VERSION:=4.31.CANDIDATE}
JACK_HOME="${JACK_HOME:=$HOME/.jack-server}"
JACK_CLIENT_SETTING="${JACK_CLIENT_SETTING:=$HOME/.jack-settings}"
TMPDIR=${TMPDIR:=/tmp}
# This is half the timeout since the script will make a second attempt collecting debugs when
# the first attempt fails on connection timeout
JACK_CONNECTION_TIMEOUT=150
JACK_EXTRA_CURL_OPTIONS=${JACK_EXTRA_CURL_OPTIONS:=}
JACK_ASSERTION_ENABLED="${JACK_ASSERTION_ENABLED:=false}"


abort () { exit 255; }


#
# Load client settings
#
if [ -f "$JACK_CLIENT_SETTING" ]; then
  source "$JACK_CLIENT_SETTING"
else
  echo "Cannot find settings at '$JACK_CLIENT_SETTING'" >&2
  abort
fi


JACK_SERVER=${JACK_SERVER:=true}
JACK_MAIN_COMMAND=${JACK_MAIN_COMMAND:="java -Djava.io.tmpdir=$TMPDIR -Dfile.encoding=UTF-8 -XX:+TieredCompilation"}
JACK_REPOSITORY=${JACK_REPOSITORY:=}


#
# If not in server mode, exec jack
#
if [ "$JACK_SERVER" != "true" ]; then
  if [ -z "$JACK_REPOSITORY" ]; then
    echo "Running Jack without Jack server requires definition of JACK_REPOSITORY" >&2
    abort
  fi
  JACK_JAR=$JACK_REPOSITORY/jack-$JACK_VERSION.jar
  if [ ! -r "$JACK_JAR" ]; then
    echo "Jack jar \"$JACK_JAR\" is not readable" >&2
    abort
  fi


  exec $JACK_MAIN_COMMAND -jar $JACK_JAR "$@"
  echo "Cannot succeed to launch Jack without Jack server" >&2
  abort
fi


#
# Prepare compilation
#
JACK_PWD="$PWD"
JACK_EXIT="$TMPDIR/jack-task-$USER-$$-exit"

# Cleanup
trap 'rm -f "$JACK_EXIT" 2>/dev/null;' EXIT

set -o errexit

# Check that we can create temp file for exit status
rm -rf "$JACK_EXIT"
echo "" > "$JACK_EXIT"

#
# Launch the compilation
#

set +o errexit
trap ERR

# put arguments in a non array variable
ARGS=""
for i in "$@"; do
  ARGS="$ARGS $i"
done


CURRENT_CHARSET=$(locale charmap)
if [ -z "$CURRENT_CHARSET" ]; then
  CHARSET_ARGUMENT=
else
  CHARSET_ARGUMENT=";charset=$CURRENT_CHARSET"
fi

# Check base64 availability
BASE64_CHECK=$((echo amFjaw==;echo LXNlcnZlcg==) | base64 --decode 2>&1)

sendRequest() {
RETRY_OPTION=$1
shift

# Launch compilation
exec 3>&1
exec 4>&2
if [ "$BASE64_CHECK" = jack-server ]; then
  HTTP_CODE=$(curl -f $JACK_EXTRA_CURL_OPTIONS $RETRY_OPTION \
       --cert "${JACK_HOME}/client.pem" \
       --cacert "${JACK_HOME}/server.pem" \
       --output >(tee >(sed -n -e 's/^E|\(.*\)$/\1/p' | base64 --decode >&4 ) | tee >(sed -n -e 's/^X|\(.*\)$/\1/p' >>$JACK_EXIT) | sed -n -e 's/^O|\(.*\)$/\1/p' | base64 --decode >&3) \
       --no-buffer --write-out '%{http_code}' --silent --connect-timeout $JACK_CONNECTION_TIMEOUT \
       -X POST \
       -H "Accept: application/vnd.jack.command-out-base64;version=1$CHARSET_ARGUMENT" \
       -F "cli=$ARGS;type=text/plain$CHARSET_ARGUMENT" \
       -F "version=$JACK_VERSION;type=application/vnd.jack.select-exact;version=1" \
       -F "pwd=$JACK_PWD;type=text/plain$CHARSET_ARGUMENT" \
       -F "assert=$JACK_ASSERTION_ENABLED;type=text/plain$CHARSET_ARGUMENT" \
       --noproxy ${SERVER_HOST} \
       https://${SERVER_HOST}:$SERVER_PORT_SERVICE/jack \
       )
else
  HTTP_CODE=$(curl -f $JACK_EXTRA_CURL_OPTIONS $RETRY_OPTION \
       --cert "${JACK_HOME}/client.pem" \
       --cacert "${JACK_HOME}/server.pem" \
       --output >(tee >(sed -n -e 's/^E|\(.*\)$/\1/p' >&4 ) | tee >(sed -n -e 's/^X|\(.*\)$/\1/p' >>$JACK_EXIT) | sed -n -e 's/^O|\(.*\)$/\1/p' >&3) \
       --no-buffer --write-out '%{http_code}' --silent --connect-timeout $JACK_CONNECTION_TIMEOUT \
       -X POST \
       -H "Accept: application/vnd.jack.command-out;version=1$CHARSET_ARGUMENT" \
       -F "cli=$ARGS;type=text/plain$CHARSET_ARGUMENT" \
       -F "version=$JACK_VERSION;type=application/vnd.jack.select-exact;version=1" \
       -F "pwd=$JACK_PWD;type=text/plain$CHARSET_ARGUMENT" \
       -F "assert=$JACK_ASSERTION_ENABLED;type=text/plain$CHARSET_ARGUMENT" \
       --noproxy ${SERVER_HOST} \
       https://${SERVER_HOST}:$SERVER_PORT_SERVICE/jack \
       )
fi
CURL_CODE=$?
exec 3>&-
exec 4>&-

set -o errexit

if [ $CURL_CODE -eq 0 ]; then
  # No problem, let's go
  JACK_CODE=$(cat "$JACK_EXIT")
  exit $JACK_CODE
elif [ $CURL_CODE -eq 7 ]; then
  # Failed to connect
  echo "No Jack server running. Try 'jack-admin start-server'" >&2
  abort
elif [ $CURL_CODE -eq 28 ]; then
  if [ "$RETRY_OPTION" == "" ]; then
    echo "Connection to the Jack server timeout, retrying with debug"
    sendRequest -v $@
  else
    echo "Connection to the Jack server timeout" >&2
    abort
  fi
elif [ $CURL_CODE -eq 35 ]; then
  if [ "$RETRY_OPTION" == "" ]; then
    echo "SSL error when connecting to the Jack server, retrying with debug"
    sendRequest -v $@
  else
    echo "SSL error when connecting to the Jack server. Try 'jack-diagnose'" >&2
    abort
  fi
elif [ $CURL_CODE -eq 58 ]; then
  echo "Failed to contact Jack server: Problem reading ${JACK_HOME}/client.pem. Try 'jack-diagnose'" >&2
  abort
elif [ $CURL_CODE -eq 60 ]; then
  echo "Failed to authenticate Jack server certificate. Try 'jack-diagnose'" >&2
  abort
 elif [ $CURL_CODE -eq 77 ]; then
  echo "Failed to contact Jack server: Problem reading ${JACK_HOME}/server.pem. Try 'jack-diagnose'" >&2
  abort
elif  [ $CURL_CODE -eq 22 ]; then
  # Http code not OK, let's decode and abort
  if [ $HTTP_CODE -eq 400 ]; then
    # 400: Bad request
    echo "Bad request, see server log" >&2
    abort
  else
    # Other
    echo "Internal unknown error ($HTTP_CODE), try 'jack-diagnose' or see Jack server log" >&2
    abort
  fi
else
  echo "Communication error with Jack server ($CURL_CODE). Try 'jack-diagnose'" >&2
  abort
fi
}

sendRequest "" $@