#!/bin/sh
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.


PRG=$0


resolve_symlink () {
    file="$1"
    while [ -h "$file" ]; do
        ls=`ls -ld "$file"`
        link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
        if expr "$link" : '^/' 2> /dev/null >/dev/null; then
            file="$link"
        else
            file=`dirname "$1"`"/$link"
        fi
    done
    echo "$file"
}

absolutize_path () {
    oldpwd=`pwd`
    cd "$1"
    abspath=`pwd`
    cd "${oldpwd}"
    echo "$abspath"
}

PRG=`resolve_symlink "$PRG"`
progdir=`dirname "$PRG"`
plathome=`absolutize_path "$progdir/.."`

jargs=${jreflags}
jargs="$jargs -Dnetbeans.home=\"$plathome\""

args=""

prefixcp=""
postfixcp=""

updater_class=org.netbeans.updater.UpdaterFrame

#
# parse arguments
#

parse_args() {
while [ $# -gt 0 ] ; do
    case "$1" in
        -h|-\?|-help|--help) cat >&2 <<EOF
Usage: $0 {options} arguments

General options:
  --help                show this help 
  --jdkhome <path>      path to Java(TM) 2 SDK, Standard Edition
  -J<jvm_option>        pass <jvm_option> to JVM

  --cp:p <classpath>    prepend <classpath> to classpath
  --cp:a <classpath>    append <classpath> to classpath
EOF
            # go on and print IDE options as well
        args="$args --help"
            ;;
        --nosplash)
            nosplash="nosplash";
            args="$args --nosplash"
            ;;
        --nogui)
            nogui="nogui";
            args="$args --nogui"
            ;;
        --jdkhome) shift; if [ $# -gt 0 ] ; then jdkhome=$1; fi
            ;;
        # this has to be here for purposes of updater.jar, but it should be
        # better to handle this argument inside the java launcher part 
        --userdir) shift; if [ $# -gt 0 ] ; then userdir="$1"; fi
            ;;
        --cachedir) shift; if [ $# -gt 0 ] ; then cachedir="$1"; cachedirspecified="specified" ; fi
            ;;
        -cp|-cp:a|--cp|--cp:a)
            shift;
            if [ $# -gt 0 ] ; then
                if [ ! -z "$postfixcp" ] ; then postfixcp="$postfixcp:" ; fi
                postfixcp=$postfixcp$1;
            fi
            ;;
        
        -cp:p|--cp:p)
            shift;
            if [ $# -gt 0 ] ; then
                if [ ! -z "$prefixcp" ] ; then prefixcp="$prefixcp:" ; fi
                prefixcp=$prefixcp$1;
            fi
            ;;
        --clusters)
            shift;
            if [ $# -gt 0 ] ; then
                clusters="$1"
            fi
            ;;
        -psn*)
            shift;
            ;;
        -J*) jopt=`expr "X-$1" : 'X--J\(.*\)'`; jargs="$jargs '$jopt'";;
        *) args="$args \"$1\"" ;;
    esac
    shift
done
} # parse_args()

# Process arguments given on the command line.
parse_args "$@"

#
# check JDK
#

if [ -z "$jdkhome" ] ; then
    # Check Java installed with sdkman
    if [ -x "$HOME/.sdkman/candidates/java/current/bin/java" ]; then
        jdkhome=`resolve_symlink "$HOME/.sdkman/candidates/java/current"`
    fi
    if [ -z "$jdkhome" ] ; then
        # try to find JDK
        case "`uname`" in
            Darwin*)
            # check if JAVA_HOME is empty string since java_home will return the value of JAVA_HOME
            if [ -z "$JAVA_HOME" ]; then
                unset JAVA_HOME
            fi
            # read Java Preferences
            if [ -x "/usr/libexec/java_home" ]; then
                jdkhome=`/usr/libexec/java_home --version 1.8+`
            # JDK1.8 as a fallback
            elif [ -f "/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/bin/java" ] ; then
                jdkhome="/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home"
            fi

            # JRE fallback
            if [ ! -x "${jdkhome}/bin/java" -a -f "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" ] ; then
                jdkhome="/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home"
            fi
            ;;
            *) javac=`which javac`
            if [ -z "$javac" ] ; then
                java=`which java`
                if [ ! -z "$java" ] ; then
                    java=`resolve_symlink "$java"`
                    jdkhome=`dirname $java`"/.."
                fi
            else
                javac=`resolve_symlink "$javac"`
                jdkhome=`dirname $javac`"/.."
            fi
            ;;
        esac
    fi
fi

if [ ! -x "${jdkhome}/bin/java" ] ; then
    echo "Cannot find java. Please use the --jdkhome switch." >&2
    exit 2
fi

# fixes 225762: Can't open project from a folder with UTF-8 letters on Mac OS X
if [ `uname` = "Darwin" ] ; then
    if [ x${LC_CTYPE} = x ] ; then
        export LC_CTYPE=UTF-8;
    fi
fi

jargs="$jargs -XX:+HeapDumpOnOutOfMemoryError"
if [ -z "`echo $jargs | grep -- "-XX:HeapDumpPath="`" ] ; then
  jargs="$jargs -XX:HeapDumpPath=\"${userdir}/var/log/heapdump.hprof\""
fi
# rename old heap dump to .old
mv "${userdir}/var/log/heapdump.hprof" "${userdir}/var/log/heapdump.hprof.old" > /dev/null 2>&1

jargs_without_clusters="$jargs -Djava.security.manager=allow"
jargs="-Dnetbeans.dirs=\"${clusters}\" $jargs_without_clusters"

if [ -z "$cachedirspecified" ]; then
   cachedir="${userdir}/var/cache"
fi

if [ `uname` != Darwin -a -z "$nosplash" -a -f "${cachedir}/splash.png" -a ! -f "${userdir}/lock" ]; then
   jargs="$jargs -splash:\"${cachedir}/splash.png\""
fi

jdkhome=`absolutize_path "$jdkhome"`

args="--userdir \"${userdir}\" $args"

args="--cachedir \"${cachedir}\" $args"

append_jars_to_cp() {
    dir="$1"
    subpath="$2"
    for ex in jar zip ; do
        if [ "`echo "${dir}"/*.$ex`" != "${dir}/*.$ex" ] ; then
            for x in "${dir}"/*.$ex ; do
                subx=`basename "$x"`
                if [ -z "`echo "$paths" | grep -E "$subpath$subx"`" ] ; then
                    if [ ! -z "$cp" ] ; then cp="$cp:" ; fi
                    cp="$cp$x"
                    if [ ! -z "$paths" ] ; then paths="$paths:" ; fi
                    paths="$paths$subpath$subx"
                fi
            done
        fi
    done
}

construct_cp() {
    cp=""
    updatercp=""
    paths=""
    
    build_cp "${userdir}"
    build_cp "${plathome}"
    
    if [ -f "${userdir}/modules/ext/updater.jar" ] ; then
        updatercp="${userdir}/modules/ext/updater.jar"
    else 
        if [ -f "${plathome}/modules/ext/updater.jar" ] ; then
            updatercp="${plathome}/modules/ext/updater.jar"
        fi
    fi

    # JDK tools
    for x in "${jdkhome}/lib/dt.jar" "${jdkhome}/lib/tools.jar"; do
        if [ -f "$x" ]; then
            if [ ! -z "$cp" ] ; then cp="$cp:" ; fi
            cp="${cp}$x"
        fi
    done

    # user-specified prefix and postfix CLASSPATH
    
    if [ ! -z "${prefixcp}" ] ; then
        cp="${prefixcp}:$cp"
    fi
    
    if [ ! -z "${postfixcp}" ] ; then
        cp="$cp:${postfixcp}"
    fi


    # prepend IDE's classpath to updater's classpath
    # (just xml-apis.jar and one XML parser would suffice)
    if [ ! -z "$updatercp" ] ; then
        updatercp=${cp}:${updatercp}
    else
        updatercp=${cp}
    fi
}

build_cp() {
    base="$1"
    append_jars_to_cp "${base}/lib/patches" "patches"
    append_jars_to_cp "${base}/lib" "lib"
    append_jars_to_cp "${base}/lib/locale" "locale"
}

do_run_updater() {
    eval "\"$jdkhome/bin/java\"" -classpath "\"${updatercp}\"" "$jargs" "-Dnetbeans.user=\"$userdir\"" $updater_class "$args"
    construct_cp
}

look_for_pre_runs() {
    base="$1"
    install_new_updater "$1"
    dir="${base}/update/download"
    if [ "`echo "${dir}"/*.nbm`" != "${dir}/*.nbm" -o "`echo "${dir}"/*.jar`" != "${dir}/*.jar" ] ; then
        run_updater=yes
    else
        dir="${base}/update/deactivate"
        if [ -f "${dir}/to_disable.txt" -o -f "${dir}/to_uninstall.txt" -o -f "${dir}/to_enable.txt" ] ; then
            run_updater=yes
        fi
    fi
}

look_for_post_runs() {
    base="$1"
    install_new_updater "$1"
    dir="${base}/update/download"
    if [ \! -f "${dir}/install_later.xml" ] && [ "`echo "${dir}"/*.nbm`" != "${dir}/*.nbm" -o "`echo "${dir}"/*.jar`" != "${dir}/*.jar" ] ; then
        run_updater=yes
    else
        dir="${base}/update/deactivate"
        if [ \! -f "${dir}/deactivate_later.txt" ] ; then
            if [ -f "${dir}/to_disable.txt" -o -f "${dir}/to_uninstall.txt" -o -f "${dir}/to_enable.txt" ] ; then
                run_updater=yes
            fi
        fi
    fi
}

look_for_new_clusters() {
    base="$userdir"
    dir="${base}/update/download"
    newclusters="${dir}/netbeans.dirs"
    if [ -f "${newclusters}" ] ; then
        clusters=`cat "${newclusters}"`
        jargs="-Dnetbeans.dirs=\"${clusters}\" $jargs_without_clusters"
        rm -f "${newclusters}"
    fi
}

delete_new_clusters_file() {
    base="$userdir"
    dir="${base}/update/download"
    newclusters="${dir}/netbeans.dirs"
    if [ \! -f "${newclusters}" ] ; then
        rm -f "${newclusters}"
    fi
}

install_new_updater() {
    base="$1"
    newUpdaterDir="${base}/update/new_updater"
    if [ -d "${newUpdaterDir}" ]; then
        mkdir -p "${base}/modules/ext/"
        if [ -f "${newUpdaterDir}/updater.jar" ]; then
            mv -f "${newUpdaterDir}/updater.jar" "${base}/modules/ext/"
        fi
        for i in "${newUpdaterDir}/locale/"updater_*.jar; do
            if [ -f "$i" ]; then
                mkdir -p "${base}/modules/ext/locale/"
                mv -f "$i" "${base}/modules/ext/locale/"
            fi
        done
        rmdir "${newUpdaterDir}"
    fi
}

if [ "$KDE_FULL_SESSION" = "true" ] ; then
    jargs="-Dnetbeans.running.environment=kde $jargs"        
else
    if [ ! -z "$GNOME_DESKTOP_SESSION_ID" ] ; then
        jargs="-Dnetbeans.running.environment=gnome $jargs" 
    fi
fi

if [ ! -z "${DEFAULT_USERDIR_ROOT}" ] ; then
	jargs="-Dnetbeans.default_userdir_root=\"${DEFAULT_USERDIR_ROOT}\" $jargs"
        unset DEFAULT_USERDIR_ROOT
fi

# http://java.sun.com/j2se/1.5.0/docs/guide/2d/flags.html#pixmaps
J2D_PIXMAPS=shared
export J2D_PIXMAPS

# Check DISPLAY variable on non-Mac
if [ "no$DISPLAY" = "no" -a `uname` != Darwin -a -z "$nogui" ]; then
    echo "$0: WARNING: environment variable DISPLAY is not set"
fi


# The Startup Notification Protocol Specification [1]
# recommends to unset the DESKTOP_STARTUP_ID environment variable 
# to avoid possible reuse by some process started later by this
# process, e.g. when a browser will be launched by the NetBeans [2].
#
# See:
# [1] http://standards.freedesktop.org/startup-notification-spec
# [2] http://netbeans.org/bugzilla/show_bug.cgi?id=76970
if [ ! -z "$DESKTOP_STARTUP_ID" ] ; then
    # Save a value for later using
    NB_DESKTOP_STARTUP_ID="$DESKTOP_STARTUP_ID"; export NB_DESKTOP_STARTUP_ID

    unset DESKTOP_STARTUP_ID
fi


#
# main loop
#

# clear to prevent loop from ending
restart="yes"
first_time_starting="yes"
restart_file="${userdir}/var/restart"

while [ "$restart" ] ; do

    #
    # build CLASSPATH
    #
    construct_cp
    
    # First check for pre-run updates.
    if [ "$first_time_starting" ] ; then
        run_updater=""
        look_for_pre_runs "$plathome"
        save="$IFS"
        IFS=':' ; for oneCls in $clusters ; do
            IFS="$save"
            look_for_pre_runs "$oneCls"
        done
        IFS="$save"
        look_for_pre_runs "$userdir"
        if [ "$run_updater" ] ; then do_run_updater ; fi
        # Do not check this after a restart, it makes no sense.
        first_time_starting=""
    fi
    
    #
    # let's go
    #
    delete_new_clusters_file
    rm -f "${restart_file}"
    eval ${_NB_PROFILE_CMD} "\"${jdkhome}/bin/java\"" -Djdk.home="\"${jdkhome}\"" -classpath "\"$cp\"" \
        "$jargs" org.netbeans.Main "$args" '<&0' '&'
    PID=$!
    trap "kill $PID" EXIT
    wait $PID
    exitcode=$?
    trap '' EXIT
    look_for_new_clusters
    # If we should update anything, do it and restart IDE.
    if [ $exitcode -eq 4 ] ; then
        # Just connected to CLI, not in charge of running Updater or whatever.
        exitcode=0
        break
    fi
    run_updater=""
    look_for_post_runs "$plathome"

    save="$IFS"
    IFS=':' ; for oneCls in $clusters ; do
        IFS="$save"
        look_for_post_runs "$oneCls"
    done
    IFS="$save"
    look_for_post_runs "$userdir"
    if [ "$run_updater" ] ; then
        do_run_updater
        restart="yes"
    else
        if [ ! -f "${restart_file}" ] ; then
            # will fall thru loop and exit
            restart=""
        fi
    fi

done
# and we exit.
exit $exitcode
