#!/bin/sh

# Uncomment the following line to override the JVM search sequence
# INSTALL4J_JAVA_HOME_OVERRIDE=
# Uncomment the following line to add additional VM parameters
# INSTALL4J_ADD_VM_PARAMS=


INSTALL4J_JAVA_PREFIX=""
unset _JAVA_OPTIONS
unset JAVA_TOOL_OPTIONS
unset JDK_JAVA_OPTIONS

fill_version_numbers() {
  ver_major="${ver_major:-0}"
  ver_minor="${ver_minor:-0}"
  ver_micro="${ver_micro:-0}"
  ver_patch="${ver_patch:-0}"
}

read_db_entry() {
  if [ -n "$INSTALL4J_NO_DB" ]; then
    return 1
  fi
  if [ ! -f "$db_file" ]; then
    return 1
  fi
  if [ ! -x "$java_exc" ]; then
    return 1
  fi
  found=1
  exec 7< $db_file
  while read r_type r_dir r_ver_major r_ver_minor r_ver_micro r_ver_patch r_ver_vendor<&7; do
    if [ "$r_type" = "JRE_VERSION" ]; then
      if [ "$r_dir" = "$test_dir" ]; then
        ver_major="$r_ver_major"
        ver_minor="$r_ver_minor"
        ver_micro="$r_ver_micro"
        ver_patch="$r_ver_patch"
        fill_version_numbers
      fi
    elif [ "$r_type" = "JRE_INFO" ]; then
      if [ "$r_dir" = "$test_dir" ]; then
        is_64bit=$r_ver_micro
        if [ "$r_ver_minor" = "$modification_date" ] && [ "$is_64bit" != "" ]; then
          found=0
          break
        fi
      fi
    fi
    r_ver_micro=""
  done
  exec 7<&-

  return $found
}

create_db_entry() {
  tested_jvm=true
  version_output=$("$bin_dir/java" $1 -version 2>&1)
  is_gcj=0; [ "${version_output#*gcj}" != "$version_output" ] && is_gcj=1
  is_64bit=0; [ "${version_output#*64-Bit}" != "$version_output" ] || [ "${version_output#*amd64}" != "$version_output" ] && is_64bit=1

  if [ "$is_gcj" = 0 ]; then
    java_version="${version_output#*\"}"
    if [ "$java_version" != "$version_output" ]; then
      java_version="${java_version%%\"*}"
    else
      java_version=""
    fi
    ver_major="${java_version%%.*}"
    ver_major="${ver_major%%[![:digit:]]*}"

    ver_rest="${java_version#*.}"
    if [ "$ver_rest" != "$java_version" ]; then
      ver_minor="${ver_rest%%.*}"
      ver_minor="${ver_minor%%[![:digit:]]*}"
    else
      ver_minor=""
    fi

    ver_rest2="${ver_rest#*.}"
    if [ "$ver_rest2" != "$ver_rest" ]; then
      ver_micro="${ver_rest2%%[._]*}"
      ver_micro="${ver_micro%%[![:digit:]]*}"
      tail="${ver_rest2#"$ver_micro"}"
      if [ "$tail" != "$ver_rest2" ]; then
        ver_patch="${tail#[_.]}"
        ver_patch="${ver_patch%%[![:digit:]]*}"
      else
        ver_patch=""
      fi
    else
      ver_micro=""
      ver_patch=""
    fi
  fi
  fill_version_numbers
  if [ -n "$INSTALL4J_NO_DB" ]; then
    return
  fi

  db_new_file=${db_file}_new
  if [ -f "$db_file" ]; then
    : > "$db_new_file"
    while IFS= read -r line; do
      set -- $line
      if [ "$2" != "$test_dir" ]; then
        printf '%s\n' "$line" >> "$db_new_file"
      fi
    done < "$db_file"

    cp "$db_new_file" "$db_file"
    rm "$db_new_file" 2>/dev/null
  fi

  dir_unescaped="$test_dir"
  dir_escaped=""
  while [ "$dir_unescaped" ]; do
    case $dir_unescaped in
      *" "*)
        dir_escaped="$dir_escaped${dir_unescaped%%" "*}\ "
        dir_unescaped="${dir_unescaped#*" "}"
        ;;
      *)
        dir_escaped="$dir_escaped$dir_unescaped"
        break
        ;;
    esac
  done
  echo "JRE_VERSION	$dir_escaped	$ver_major	$ver_minor	$ver_micro	$ver_patch" >> $db_file
  echo "JRE_INFO	$dir_escaped	1	$modification_date	$is_64bit" >> $db_file
  chmod g+w $db_file
}

check_date_output() {
  if [ -n "$date_output" -a $date_output -eq $date_output 2> /dev/null ]; then
    modification_date=$date_output
  fi
}

test_jvm() {
  tested_jvm=na
  test_dir=$1
  bin_dir="$test_dir/bin"
  java_exc="$bin_dir/java"
  if [ -z "$test_dir" ] || [ ! -d "$bin_dir" ] || [ ! -f "$java_exc" ] || [ ! -x "$java_exc" ]; then
    return
  fi

  modification_date=0
  date_output=$(date -r "$java_exc" "+%s" 2>/dev/null)
  if [ $? -eq 0 ]; then
    check_date_output
  fi
  if [ $modification_date -eq 0 ]; then
    stat_path=$(command -v stat 2> /dev/null)
    if [ -f "$stat_path" ]; then
      date_output=$(stat -f "%m" "$java_exc" 2>/dev/null)
      if [ $? -eq 0 ]; then
        check_date_output
      fi
      if [ $modification_date -eq 0 ]; then
        date_output=$(stat -c "%Y" "$java_exc" 2>/dev/null)
        if [ $? -eq 0 ]; then
          check_date_output
        fi
      fi
    fi
  fi

  tested_jvm=false
  read_db_entry || create_db_entry $2

  if [ "$ver_major" = "" ]; then
    return;
  fi
  if [ "$ver_major" -lt "1" ]; then
    return;
  elif [ "$ver_major" -eq "1" ]; then
    if [ "$ver_minor" -lt "8" ]; then
      return;
    fi
  fi

  if [ "$ver_major" = "" ]; then
    return;
  fi
  app_java_home=$test_dir
}

add_class_path() {
  if [ -n "$1" ] && [ "${1%\**}" = "$1" ]; then
    local_classpath="$local_classpath${local_classpath:+:}${1}${2}"
  fi
}

expand_all_vars() {
  case $1 in
    *[!A-Za-z0-9_\/\.\:\ \$\{\}\~\-]*)
      printf '%s' "$1"
      return 0
      ;;
  esac
  set -f
  eval "printf '%s' $1"
  set +f
}

read_vmoptions() {
  vmoptions_file=$(expand_all_vars "$1")
  if [ ! -r "$vmoptions_file" ]; then
    vmoptions_file="$prg_dir/$vmoptions_file"
  fi
  if [ -r "$vmoptions_file" ] && [ -f "$vmoptions_file" ]; then
    exec 8< "$vmoptions_file"
    while read cur_option<&8; do
      cur_option="${cur_option#"${cur_option%%[![:space:]]*}"}"
      if [ "${cur_option#\#}" = "${cur_option}" ]; then 
        vmo_include=${cur_option#-include-options }
        if [ "$vmo_include" != "$cur_option" ]; then
            if [ "$vmo_include_1" = "" ]; then
              vmo_include_1="$vmo_include"
            elif [ "$vmo_include_2" = "" ]; then
              vmo_include_2="$vmo_include"
            elif [ "$vmo_include_3" = "" ]; then
              vmo_include_3="$vmo_include"
            fi
        fi
        vmo_classpath="${cur_option#-classpath }"
        vmo_classpath_a="${cur_option#-classpath/a }"
        vmo_classpath_p="${cur_option#-classpath/p }"
        if [ "$vmo_classpath" != "$cur_option" ]; then
          local_classpath="$i4j_classpath:$vmo_classpath"
        elif [ "$vmo_classpath_a" != "$cur_option" ]; then
          local_classpath="${local_classpath}:${vmo_classpath_a}"
        elif [ "$vmo_classpath_p" != "$cur_option" ]; then
          local_classpath="${vmo_classpath_p}:${local_classpath}"
        elif [ "$vmo_include" = "$cur_option" ] && [ "${cur_option#-jvm=}" = "$cur_option" ]; then
          if [ "${cur_option#*[[:space:]]}" = "$cur_option" ]; then
            vmoptions_val="$vmoptions_val $cur_option"
          else
            if [ "$vmov_1" = "" ]; then
              vmov_1="$cur_option"
            elif [ "$vmov_2" = "" ]; then
              vmov_2="$cur_option"
            elif [ "$vmov_3" = "" ]; then
              vmov_3="$cur_option"
            elif [ "$vmov_4" = "" ]; then
              vmov_4="$cur_option"
            elif [ "$vmov_5" = "" ]; then
              vmov_5="$cur_option"
            fi
          fi
        fi
      fi
    done
    exec 8<&-
    if [ ! "$vmo_include_1" = "" ]; then
      vmo_include="$vmo_include_1"
      unset vmo_include_1
      read_vmoptions "$vmo_include"
    fi
    if [ ! "$vmo_include_2" = "" ]; then
      vmo_include="$vmo_include_2"
      unset vmo_include_2
      read_vmoptions "$vmo_include"
    fi
    if [ ! "$vmo_include_3" = "" ]; then
      vmo_include="$vmo_include_3"
      unset vmo_include_3
      read_vmoptions "$vmo_include"
    fi
  fi
}

read_jvm_from_vmoptions() {
  vmoptions_file=$(expand_all_vars "$1")
  if [ ! -r "$vmoptions_file" ]; then
    vmoptions_file="$prg_dir/$vmoptions_file"
  fi
  if [ -r "$vmoptions_file" ] && [ -f "$vmoptions_file" ]; then
    exec 8< "$vmoptions_file"
    while read cur_option<&8; do
      cur_option="${cur_option#"${cur_option%%[![:space:]]*}"}"
      if [ "${cur_option#\#}" = "${cur_option}" ]; then 
        vmo_include=${cur_option#-include-options }
        if [ "$vmo_include" != "$cur_option" ]; then
            if [ "$vmo_include_1" = "" ]; then
              vmo_include_1="$vmo_include"
            elif [ "$vmo_include_2" = "" ]; then
              vmo_include_2="$vmo_include"
            elif [ "$vmo_include_3" = "" ]; then
              vmo_include_3="$vmo_include"
            fi
        fi
        vmo_jvm="${cur_option#-jvm=}"
        if [ "$vmo_jvm" != "$cur_option" ]; then
            INSTALL4J_JAVA_HOME_OVERRIDE="$vmo_jvm"
        fi
      fi
    done
    exec 8<&-
    if [ ! "$vmo_include_1" = "" ]; then
      vmo_include="$vmo_include_1"
      unset vmo_include_1
      read_jvm_from_vmoptions "$vmo_include"
    fi
    if [ ! "$vmo_include_2" = "" ]; then
      vmo_include="$vmo_include_2"
      unset vmo_include_2
      read_jvm_from_vmoptions "$vmo_include"
    fi
    if [ ! "$vmo_include_3" = "" ]; then
      vmo_include="$vmo_include_3"
      unset vmo_include_3
      read_jvm_from_vmoptions "$vmo_include"
    fi
  fi
}


unpack_file() {
  if [ -f "$1" ]; then
    jar_file="${1%?????}"
    bin/unpack200 -r "$1" "$jar_file" > /dev/null 2>&1

    if [ $? -ne 0 ]; then
      echo "Error unpacking jar files. The architecture or bitness (32/64)"
      echo "of the bundled JVM might not match your machine."
      echo "You might also need administrative privileges for this operation."
      exit 1
    else
      chmod a+r "$jar_file"
    fi
  fi
}

run_unpack200() {
  if [ -d "$1/lib" ]; then
    old_pwd200="$PWD"
    cd "$1"
    for pack_file in lib/*.jar.pack
    do
      unpack_file $pack_file
    done
    for pack_file in lib/ext/*.jar.pack
    do
      unpack_file $pack_file
    done
    cd "$old_pwd200"
  fi
}

search_jre() {
if [ -z "$app_java_home" ]; then
  test_jvm "$INSTALL4J_JAVA_HOME_OVERRIDE"
fi

if [ -z "$app_java_home" ]; then
if [ -f "$app_home/.install4j/pref_jre.cfg" ]; then
    read file_jvm_home < "$app_home/.install4j/pref_jre.cfg"
    test_jvm "$file_jvm_home"
    if [ -z "$app_java_home" ] && [ $tested_jvm = "false" ]; then
if [ -w "$db_file" ]; then
  /bin/sh -c ': > "$db_file"' 2> /dev/null
fi
        test_jvm "$file_jvm_home"
    fi
fi
fi

if [ -z "$app_java_home" ]; then
  test_jvm "$app_home/jre" 
  if [ -z "$app_java_home" ] && [ $tested_jvm = "false" ]; then
if [ -w "$db_file" ]; then
  /bin/sh -c ': > "$db_file"' 2> /dev/null
fi
    test_jvm "$app_home/jre"
  fi
fi

if [ -z "$app_java_home" ]; then
  test_jvm "$app_home/.install4j/jre.bundle/Contents/Home" 
  if [ -z "$app_java_home" ] && [ $tested_jvm = "false" ]; then
if [ -w "$db_file" ]; then
  /bin/sh -c ': > "$db_file"' 2> /dev/null
fi
    test_jvm "$app_home/.install4j/jre.bundle/Contents/Home"
  fi
fi

if [ -z "$app_java_home" ]; then
  test_jvm "$app_home/../jre.bundle/Contents/Home" 
  if [ -z "$app_java_home" ] && [ $tested_jvm = "false" ]; then
if [ -w "$db_file" ]; then
  /bin/sh -c ': > "$db_file"' 2> /dev/null
fi
    test_jvm "$app_home/../jre.bundle/Contents/Home"
  fi
fi

if [ -z "$app_java_home" ]; then
  test_jvm "$JPROFILER_JAVA_HOME"
fi

if [ -z "$app_java_home" ]; then
  if [ "$INSTALL4J_NO_PATH" != "true" ]; then
    prg_jvm=$(command -v java 2> /dev/null)
    if [ -n "$prg_jvm" ] && [ -f "$prg_jvm" ]; then
      old_pwd_jvm="$PWD"
      path_java_bin="${prg_jvm%/*}"; [ "$path_java_bin" = "$prg_jvm" ] && path_java_bin=.
      cd -P "$path_java_bin" || exit 1
      prg_jvm=java

      while [ -h "$prg_jvm" ]; do
        lsout=$(ls -ld -- "$prg_jvm" 2>/dev/null || ls -ld "$prg_jvm") || break
        case $lsout in
          *"-> "*) link="${lsout#*'-> '}" ;;
          *) break ;;
        esac

        case $link in
          */*) prg_jvm="$link" ;;
          *)
            resolved_dir="${prg_jvm%/*}"; [ "$resolved_dir" = "$prg_jvm" ] && resolved_dir=.
            prg_jvm=$resolved_dir/$link
            ;;
        esac
      done

      path_java_bin="${prg_jvm%/*}"; [ "$path_java_bin" = "$prg_jvm" ] && path_java_bin=.
      cd -P "$path_java_bin" || { cd "$old_pwd_jvm"; exit 1; }
      cd -P .. || { cd "$old_pwd_jvm"; exit 1; }

      path_java_home="$PWD"
      cd "$old_pwd_jvm"
      test_jvm "$path_java_home"
    fi
  fi
fi


if [ -z "$app_java_home" ]; then
  common_jvm_locations=" /usr/bin/java* /usr/bin/jdk* /usr/bin/jre* /usr/bin/j2*re* /usr/bin/j2sdk* /usr/java* /usr/java*/jre /usr/jdk* /usr/jre* /usr/j2*re* /usr/j2sdk* /usr/java/j2*re* /usr/java/j2sdk* /opt/java* /usr/java/jdk* /usr/java/jre* /usr/lib/java/jre /usr/local/java* /usr/local/jdk* /usr/local/jre* /usr/local/j2*re* /usr/local/j2sdk* /usr/jdk/java* /usr/jdk/jdk* /usr/jdk/jre* /usr/jdk/j2*re* /usr/jdk/j2sdk* /usr/lib/jvm/* /usr/lib/java* /usr/lib/jdk* /usr/lib/jre* /usr/lib/j2*re* /usr/lib/j2sdk* /System/Library/Frameworks/JavaVM.framework/Versions/1.?/Home /Library/Internet\ Plug-Ins/JavaAppletPlugin.plugin/Contents/Home /Library/Java/JavaVirtualMachines/*.jdk/Contents/Home/jre /Library/Java/JavaVirtualMachines/*.jre/Contents/Home /Library/Java/JavaVirtualMachines/*.jdk/Contents/Home"
  for current_location in $common_jvm_locations
  do
if [ -z "$app_java_home" ]; then
  test_jvm "$current_location"
fi

  done
fi

if [ -z "$app_java_home" ]; then
  test_jvm "$JAVA_HOME"
fi

if [ -z "$app_java_home" ]; then
  test_jvm "$JDK_HOME"
fi

if [ -z "$app_java_home" ]; then
  test_jvm "$INSTALL4J_JAVA_HOME"
fi

if [ -z "$app_java_home" ]; then
if [ -f "$app_home/.install4j/inst_jre.cfg" ]; then
    read file_jvm_home < "$app_home/.install4j/inst_jre.cfg"
    test_jvm "$file_jvm_home"
    if [ -z "$app_java_home" ] && [ $tested_jvm = "false" ]; then
if [ -w "$db_file" ]; then
  /bin/sh -c ': > "$db_file"' 2> /dev/null
fi
        test_jvm "$file_jvm_home"
    fi
fi
fi

}

old_pwd="$PWD"
progname="${0##*/}"
linkdir="${0%/*}"; [ "$linkdir" = "$0" ] && linkdir=.

cd "$linkdir" || exit 1
prg="$progname"
while [ -h "$prg" ]; do
  lsout=$(ls -ld -- "$prg" 2>/dev/null || ls -ld "$prg") || break
  case $lsout in
    *"-> "*) link="${lsout#*'-> '}" ;;
    *) break ;;
  esac
  case $link in
    *'/'*) prg="$link" ;;
    *)
      dir="${prg%/*}"; [ "$dir" = "$prg" ] && dir=.
      prg="$dir/$link"
      ;;
  esac
done


prg_dir="${prg%/*}"; [ "$prg_dir" = "$prg" ] && prg_dir=.
progname="${prg##*/}"
cd "$prg_dir"
prg_dir="$PWD"
app_home=

cd "$prg_dir"
prg_dir="$PWD"
app_home=../
cd "$app_home"
app_home="$PWD"
bundled_jre_home="$app_home/jre"

cd "$old_pwd"

cache_home="$XDG_CACHE_HOME"
if [ "$cache_home" = "" ]; then
  cache_home="$HOME/.cache"
fi
db_home="$cache_home/install4j"
mkdir -p "$db_home" > /dev/null 2>&1
db_file="$db_home/jre_version"
if [ ! -w "$db_home" ]; then
  db_home=/tmp
  db_file="$db_home/install4j_jre_version_$USER"
fi
if [ -d "$db_file" ] || ([ -f "$db_file" ] && [ ! -r "$db_file" ]) || ([ -f "$db_file" ] && [ ! -w "$db_file" ]); then
  db_file="${db_file}.2"
fi
for param in $@; do
  param_without_prefix="${param#-J-jvm=}"
  if [ "$param_without_prefix" != "$param" ]; then
    INSTALL4J_JAVA_HOME_OVERRIDE="$param_without_prefix"
  fi
done

if [ "$INSTALL4J_JAVA_HOME_OVERRIDE" = "" ]; then
  read_jvm_from_vmoptions "$prg_dir/$progname.vmoptions"
fi
if [ ! "__i4j_lang_restart" = "$1" ] && [ ! "__i4j_auth_restart" = "$1" ]; then
run_unpack200 "$bundled_jre_home"
run_unpack200 "$bundled_jre_home/jre"
fi
search_jre
if [ -z "$app_java_home" ]; then
if [ -w "$db_file" ]; then
  /bin/sh -c ': > "$db_file"' 2> /dev/null
fi
  search_jre
fi
if [ -z "$app_java_home" ]; then
  echo "No suitable Java Virtual Machine could be found on your system."
  echo The version of the JVM must be at least 1.8.
  echo Please define INSTALL4J_JAVA_HOME to point to a suitable JVM.
  exit 83
fi

local_classpath=""
i4j_classpath="$app_home/.install4j/i4jruntime.jar:$app_home/.install4j/launcher52a3f866.jar"
add_class_path "$i4j_classpath"

if [ ! -r "$app_home/bin/attach.jar" ]; then
  echo The archive $app_home/bin/attach.jar does not exist.
  exit 1
fi
add_class_path "$app_home/bin/attach.jar"

if [ ! -r "$app_home/lib/nanoxml-2.2.3.jar" ]; then
  echo The archive $app_home/lib/nanoxml-2.2.3.jar does not exist.
  exit 1
fi
add_class_path "$app_home/lib/nanoxml-2.2.3.jar"

vmoptions_val=""
read_vmoptions "$prg_dir/$progname.vmoptions"
INSTALL4J_ADD_VM_PARAMS="$INSTALL4J_ADD_VM_PARAMS $vmoptions_val"

if [ ! "$ver_major" = "" ]; then
  used_major_version=$ver_major
  if [ "$ver_major" = "1" ]; then
    used_major_version=$ver_minor
  fi
  if [ $used_major_version -ge 9 ]; then
    INSTALL4J_ADD_VM_PARAMS="$INSTALL4J_ADD_VM_PARAMS "@$prg_dir/options/base.options""
  fi
fi

for param in $@; do
  param_without_prefix="${param#-J}"
  if [ "$param_without_prefix" != "$param" ] && [ "$param_without_prefix" = "${param_without_prefix#-jvm=}" ]; then
    INSTALL4J_ADD_VM_PARAMS="$INSTALL4J_ADD_VM_PARAMS $param_without_prefix"
  fi
done


has_space_options=false
if [ "$vmov_1" = "" ]; then
  vmov_1="-Di4jv=0"
else
  has_space_options=true
fi
if [ "$vmov_2" = "" ]; then
  vmov_2="-Di4jv=0"
else
  has_space_options=true
fi
if [ "$vmov_3" = "" ]; then
  vmov_3="-Di4jv=0"
else
  has_space_options=true
fi
if [ "$vmov_4" = "" ]; then
  vmov_4="-Di4jv=0"
else
  has_space_options=true
fi
if [ "$vmov_5" = "" ]; then
  vmov_5="-Di4jv=0"
else
  has_space_options=true
fi

return_code=0
if [ "$has_space_options" = "true" ]; then
$INSTALL4J_JAVA_PREFIX exec "$app_java_home/bin/java" "-Djava.awt.headless=true" "-Dswing.volatileImageBufferEnabled=false" "$vmov_1" "$vmov_2" "$vmov_3" "$vmov_4" "$vmov_5" $INSTALL4J_ADD_VM_PARAMS -classpath "$local_classpath" install4j.com.jprofiler.cli.ControllerApplication  "$@"
return_code=$?
else
$INSTALL4J_JAVA_PREFIX exec "$app_java_home/bin/java" "-Djava.awt.headless=true" "-Dswing.volatileImageBufferEnabled=false" $INSTALL4J_ADD_VM_PARAMS -classpath "$local_classpath" install4j.com.jprofiler.cli.ControllerApplication  "$@"
return_code=$?
fi


exit $return_code
