#!/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.
# 

ARG_JAVAHOME="--javahome"
ARG_VERBOSE="--verbose"
ARG_OUTPUT="--output"
ARG_EXTRACT="--extract"
ARG_JAVA_ARG_PREFIX="-J"
ARG_TEMPDIR="--tempdir"
ARG_CLASSPATHA="--classpath-append"
ARG_CLASSPATHP="--classpath-prepend"
ARG_HELP="--help"
ARG_SILENT="--silent"
ARG_NOSPACECHECK="--nospacecheck"
ARG_LOCALE="--locale"

USE_DEBUG_OUTPUT=0
PERFORM_FREE_SPACE_CHECK=1
SILENT_MODE=0
EXTRACT_ONLY=0
SHOW_HELP_ONLY=0
LOCAL_OVERRIDDEN=0
APPEND_CP=
PREPEND_CP=
LAUNCHER_APP_ARGUMENTS=
LAUNCHER_JVM_ARGUMENTS=
ERROR_OK=0
ERROR_TEMP_DIRECTORY=2
ERROR_TEST_JVM_FILE=3
ERROR_JVM_NOT_FOUND=4
ERROR_JVM_UNCOMPATIBLE=5
ERROR_EXTRACT_ONLY=6
ERROR_INPUTOUPUT=7
ERROR_FREESPACE=8
ERROR_INTEGRITY=9
ERROR_MISSING_RESOURCES=10
ERROR_JVM_EXTRACTION=11
ERROR_JVM_UNPACKING=12
ERROR_VERIFY_BUNDLED_JVM=13

VERIFY_OK=1
VERIFY_NOJAVA=2
VERIFY_UNCOMPATIBLE=3

MSG_ERROR_JVM_NOT_FOUND="nlu.jvm.notfoundmessage"
MSG_ERROR_USER_ERROR="nlu.jvm.usererror"
MSG_ERROR_JVM_UNCOMPATIBLE="nlu.jvm.uncompatible"
MSG_ERROR_INTEGRITY="nlu.integrity"
MSG_ERROR_FREESPACE="nlu.freespace"
MSG_ERROP_MISSING_RESOURCE="nlu.missing.external.resource"
MSG_ERROR_TMPDIR="nlu.cannot.create.tmpdir"

MSG_ERROR_EXTRACT_JVM="nlu.cannot.extract.bundled.jvm"
MSG_ERROR_UNPACK_JVM_FILE="nlu.cannot.unpack.jvm.file"
MSG_ERROR_VERIFY_BUNDLED_JVM="nlu.error.verify.bundled.jvm"

MSG_RUNNING="nlu.running"
MSG_STARTING="nlu.starting"
MSG_EXTRACTING="nlu.extracting"
MSG_PREPARE_JVM="nlu.prepare.jvm"
MSG_JVM_SEARCH="nlu.jvm.search"
MSG_ARG_JAVAHOME="nlu.arg.javahome"
MSG_ARG_VERBOSE="nlu.arg.verbose"
MSG_ARG_OUTPUT="nlu.arg.output"
MSG_ARG_EXTRACT="nlu.arg.extract"
MSG_ARG_TEMPDIR="nlu.arg.tempdir"
MSG_ARG_CPA="nlu.arg.cpa"
MSG_ARG_CPP="nlu.arg.cpp"
MSG_ARG_DISABLE_FREE_SPACE_CHECK="nlu.arg.disable.space.check"
MSG_ARG_LOCALE="nlu.arg.locale"
MSG_ARG_SILENT="nlu.arg.silent"
MSG_ARG_HELP="nlu.arg.help"
MSG_USAGE="nlu.msg.usage"

isSymlink=

entryPoint() {
        initSymlinkArgument        
	CURRENT_DIRECTORY=`pwd`
	LAUNCHER_NAME=`echo $0`
	parseCommandLineArguments "$@"
	initializeVariables            
	setLauncherLocale	
	debugLauncherArguments "$@"
	if [ 1 -eq $SHOW_HELP_ONLY ] ; then
		showHelp
	fi
	
        message "$MSG_STARTING"
        createTempDirectory
	checkFreeSpace "$TOTAL_BUNDLED_FILES_SIZE" "$LAUNCHER_EXTRACT_DIR"	

        extractJVMData
	if [ 0 -eq $EXTRACT_ONLY ] ; then 
            searchJava
	fi

	extractBundledData
	verifyIntegrity

	if [ 0 -eq $EXTRACT_ONLY ] ; then 
	    executeMainClass
	else 
	    exitProgram $ERROR_OK
	fi
}

initSymlinkArgument() {
        testSymlinkErr=`test -L / 2>&1 > /dev/null`
        if [ -z "$testSymlinkErr" ] ; then
            isSymlink=-L
        else
            isSymlink=-h
        fi
}

debugLauncherArguments() {
	debug "Launcher Command : $0"
	argCounter=1
        while [ $# != 0 ] ; do
		debug "... argument [$argCounter] = $1"
		argCounter=`expr "$argCounter" + 1`
		shift
	done
}
isLauncherCommandArgument() {
	case "$1" in
	    $ARG_VERBOSE | $ARG_NOSPACECHECK | $ARG_OUTPUT | $ARG_HELP | $ARG_JAVAHOME | $ARG_TEMPDIR | $ARG_EXTRACT | $ARG_SILENT | $ARG_LOCALE | $ARG_CLASSPATHP | $ARG_CLASSPATHA)
	    	echo 1
		;;
	    *)
		echo 0
		;;
	esac
}

parseCommandLineArguments() {
	while [ $# != 0 ]
	do
		case "$1" in
		$ARG_VERBOSE)
                        USE_DEBUG_OUTPUT=1;;
		$ARG_NOSPACECHECK)
                        PERFORM_FREE_SPACE_CHECK=0
                        parseJvmAppArgument "$1"
                        ;;
                $ARG_OUTPUT)
			if [ -n "$2" ] ; then
                        	OUTPUT_FILE="$2"
				if [ -f "$OUTPUT_FILE" ] ; then
					# clear output file first
					rm -f "$OUTPUT_FILE" > /dev/null 2>&1
					touch "$OUTPUT_FILE"
				fi
                        	shift
			fi
			;;
		$ARG_HELP)
			SHOW_HELP_ONLY=1
			;;
		$ARG_JAVAHOME)
			if [ -n "$2" ] ; then
				LAUNCHER_JAVA="$2"
				shift
			fi
			;;
		$ARG_TEMPDIR)
			if [ -n "$2" ] ; then
				LAUNCHER_JVM_TEMP_DIR="$2"
				shift
			fi
			;;
		$ARG_EXTRACT)
			EXTRACT_ONLY=1
			if [ -n "$2" ] && [ `isLauncherCommandArgument "$2"` -eq 0 ] ; then
				LAUNCHER_EXTRACT_DIR="$2"
				shift
			else
				LAUNCHER_EXTRACT_DIR="$CURRENT_DIRECTORY"				
			fi
			;;
		$ARG_SILENT)
			SILENT_MODE=1
			parseJvmAppArgument "$1"
			;;
		$ARG_LOCALE)
			SYSTEM_LOCALE="$2"
			LOCAL_OVERRIDDEN=1			
			parseJvmAppArgument "$1"
			;;
		$ARG_CLASSPATHP)
			if [ -n "$2" ] ; then
				if [ -z "$PREPEND_CP" ] ; then
					PREPEND_CP="$2"
				else
					PREPEND_CP="$2":"$PREPEND_CP"
				fi
				shift
			fi
			;;
		$ARG_CLASSPATHA)
			if [ -n "$2" ] ; then
				if [ -z "$APPEND_CP" ] ; then
					APPEND_CP="$2"
				else
					APPEND_CP="$APPEND_CP":"$2"
				fi
				shift
			fi
			;;

		*)
			parseJvmAppArgument "$1"
		esac
                shift
	done
}

setLauncherLocale() {
	if [ 0 -eq $LOCAL_OVERRIDDEN ] ; then		
        	SYSTEM_LOCALE="$LANG"
		debug "Setting initial launcher locale from the system : $SYSTEM_LOCALE"
	else	
		debug "Setting initial launcher locale using command-line argument : $SYSTEM_LOCALE"
	fi

	LAUNCHER_LOCALE="$SYSTEM_LOCALE"
	
	if [ -n "$LAUNCHER_LOCALE" ] ; then
		# check if $LAUNCHER_LOCALE is in UTF-8
		if [ 0 -eq $LOCAL_OVERRIDDEN ] ; then
			removeUTFsuffix=`echo "$LAUNCHER_LOCALE" | sed "s/\.UTF-8//"`
			isUTF=`ifEquals "$removeUTFsuffix" "$LAUNCHER_LOCALE"`
			if [ 1 -eq $isUTF ] ; then
				#set launcher locale to the default if the system locale name doesn`t containt  UTF-8
				LAUNCHER_LOCALE=""
			fi
		fi

        	localeChanged=0	
		localeCounter=0
		while [ $localeCounter -lt $LAUNCHER_LOCALES_NUMBER ] ; do		
		    localeVar="$""LAUNCHER_LOCALE_NAME_$localeCounter"
		    arg=`eval "echo \"$localeVar\""`		
                    if [ -n "$arg" ] ; then 
                        # if not a default locale			
			# $comp length shows the difference between $SYSTEM_LOCALE and $arg
  			# the less the length the less the difference and more coincedence

                        comp=`echo "$SYSTEM_LOCALE" | sed -e "s/^${arg}//"`				
			length1=`getStringLength "$comp"`
                        length2=`getStringLength "$LAUNCHER_LOCALE"`
                        if [ $length1 -lt $length2 ] ; then	
				# more coincidence between $SYSTEM_LOCALE and $arg than between $SYSTEM_LOCALE and $arg
                                compare=`ifLess "$comp" "$LAUNCHER_LOCALE"`
				
                                if [ 1 -eq $compare ] ; then
                                        LAUNCHER_LOCALE="$arg"
                                        localeChanged=1
                                        debug "... setting locale to $arg"
                                fi
                                if [ -z "$comp" ] ; then
					# means that $SYSTEM_LOCALE equals to $arg
                                        break
                                fi
                        fi   
                    else 
                        comp="$SYSTEM_LOCALE"
                    fi
		    localeCounter=`expr "$localeCounter" + 1`
       		done
		if [ $localeChanged -eq 0 ] ; then 
                	#set default
                	LAUNCHER_LOCALE=""
        	fi
        fi

        
        debug "Final Launcher Locale : $LAUNCHER_LOCALE"	
}

escapeBackslash() {
	echo "$1" | sed "s/\\\/\\\\\\\/g"
}

ifLess() {
	arg1=`escapeBackslash "$1"`
	arg2=`escapeBackslash "$2"`
	compare=`awk 'END { if ( a < b ) { print 1 } else { print 0 } }' a="$arg1" b="$arg2" < /dev/null`
	echo $compare
}

formatVersion() {
        formatted=`echo "$1" | sed "s/-ea//g;s/-rc[0-9]*//g;s/-beta[0-9]*//g;s/-preview[0-9]*//g;s/-dp[0-9]*//g;s/-alpha[0-9]*//g;s/-fcs//g;s/_/./g;s/-/\./g"`
        formatted=`echo "$formatted" | sed "s/^\(\([0-9][0-9]*\)\.\([0-9][0-9]*\)\.\([0-9][0-9]*\)\)\.b\([0-9][0-9]*\)/\1\.0\.\5/g"`
        formatted=`echo "$formatted" | sed "s/\.b\([0-9][0-9]*\)/\.\1/g"`
	echo "$formatted"

}

compareVersions() {
        current1=`formatVersion "$1"`
        current2=`formatVersion "$2"`
	compresult=
	#0 - equals
	#-1 - less
	#1 - more

	while [ -z "$compresult" ] ; do
		value1=`echo "$current1" | sed "s/\..*//g"`
		value2=`echo "$current2" | sed "s/\..*//g"`


		removeDots1=`echo "$current1" | sed "s/\.//g"`
		removeDots2=`echo "$current2" | sed "s/\.//g"`

		if [ 1 -eq `ifEquals "$current1" "$removeDots1"` ] ; then
			remainder1=""
		else
			remainder1=`echo "$current1" | sed "s/^$value1\.//g"`
		fi
		if [ 1 -eq `ifEquals "$current2" "$removeDots2"` ] ; then
			remainder2=""
		else
			remainder2=`echo "$current2" | sed "s/^$value2\.//g"`
		fi

		current1="$remainder1"
		current2="$remainder2"
		
		if [ -z "$value1" ] || [ 0 -eq `ifNumber "$value1"` ] ; then 
			value1=0 
		fi
		if [ -z "$value2" ] || [ 0 -eq `ifNumber "$value2"` ] ; then 
			value2=0 
		fi
		if [ "$value1" -gt "$value2" ] ; then 
			compresult=1
			break
		elif [ "$value2" -gt "$value1" ] ; then 
			compresult=-1
			break
		fi

		if [ -z "$current1" ] && [ -z "$current2" ] ; then	
			compresult=0
			break
		fi
	done
	echo $compresult
}

ifVersionLess() {
	compareResult=`compareVersions "$1" "$2"`
        if [ -1 -eq $compareResult ] ; then
            echo 1
        else
            echo 0
        fi
}

ifVersionGreater() {
	compareResult=`compareVersions "$1" "$2"`
        if [ 1 -eq $compareResult ] ; then
            echo 1
        else
            echo 0
        fi
}

ifGreater() {
	arg1=`escapeBackslash "$1"`
	arg2=`escapeBackslash "$2"`

	compare=`awk 'END { if ( a > b ) { print 1 } else { print 0 } }' a="$arg1" b="$arg2" < /dev/null`
	echo $compare
}

ifEquals() {
	arg1=`escapeBackslash "$1"`
	arg2=`escapeBackslash "$2"`

	compare=`awk 'END { if ( a == b ) { print 1 } else { print 0 } }' a="$arg1" b="$arg2" < /dev/null`
	echo $compare
}

ifNumber() 
{
	result=0
	if  [ -n "$1" ] ; then 
		num=`echo "$1" | sed 's/[0-9]*//g' 2>/dev/null`
		if [ -z "$num" ] ; then
			result=1
		fi
	fi 
	echo $result
}
getStringLength() {
    strlength=`awk 'END{ print length(a) }' a="$1" < /dev/null`
    echo $strlength
}

resolveRelativity() {
	if [ 1 -eq `ifPathRelative "$1"` ] ; then
		echo "$CURRENT_DIRECTORY"/"$1" | sed 's/\"//g' 2>/dev/null
	else 
		echo "$1"
	fi
}

ifPathRelative() {
	param="$1"
	removeRoot=`echo "$param" | sed "s/^\\\///" 2>/dev/null`
	echo `ifEquals "$param" "$removeRoot"` 2>/dev/null
}


initializeVariables() {	
	debug "Launcher name is $LAUNCHER_NAME"
	systemName=`uname`
	debug "System name is $systemName"
	isMacOSX=`ifEquals "$systemName" "Darwin"`	
	isSolaris=`ifEquals "$systemName" "SunOS"`
	if [ 1 -eq $isSolaris ] ; then
		POSSIBLE_JAVA_EXE_SUFFIX="$POSSIBLE_JAVA_EXE_SUFFIX_SOLARIS"
	else
		POSSIBLE_JAVA_EXE_SUFFIX="$POSSIBLE_JAVA_EXE_SUFFIX_COMMON"
	fi
        if [ 1 -eq $isMacOSX ] ; then
                # set default userdir and cachedir on MacOS
                DEFAULT_USERDIR_ROOT="${HOME}/Library/Application Support/NetBeans"
                DEFAULT_CACHEDIR_ROOT="${HOME}/Library/Caches/NetBeans"
        else
                # set default userdir and cachedir on unix systems
                DEFAULT_USERDIR_ROOT=${HOME}/.netbeans
                DEFAULT_CACHEDIR_ROOT=${HOME}/.cache/netbeans
        fi
	systemInfo=`uname -a 2>/dev/null`
	debug "System Information:"
	debug "$systemInfo"             
	debug ""
	DEFAULT_DISK_BLOCK_SIZE=512
	LAUNCHER_TRACKING_SIZE=$LAUNCHER_STUB_SIZE
	LAUNCHER_TRACKING_SIZE_BYTES=`expr "$LAUNCHER_STUB_SIZE" \* "$FILE_BLOCK_SIZE"`
	getLauncherLocation
}

parseJvmAppArgument() {
        param="$1"
	arg=`echo "$param" | sed "s/^-J//"`
	argEscaped=`escapeString "$arg"`

	if [ "$param" = "$arg" ] ; then
	    LAUNCHER_APP_ARGUMENTS="$LAUNCHER_APP_ARGUMENTS $argEscaped"
	else
	    LAUNCHER_JVM_ARGUMENTS="$LAUNCHER_JVM_ARGUMENTS $argEscaped"
	fi	
}

getLauncherLocation() {
	# if file path is relative then prepend it with current directory
	LAUNCHER_FULL_PATH=`resolveRelativity "$LAUNCHER_NAME"`
	debug "... normalizing full path"
	LAUNCHER_FULL_PATH=`normalizePath "$LAUNCHER_FULL_PATH"`
	debug "... getting dirname"
	LAUNCHER_DIR=`dirname "$LAUNCHER_FULL_PATH"`
	debug "Full launcher path = $LAUNCHER_FULL_PATH"
	debug "Launcher directory = $LAUNCHER_DIR"
}

getLauncherSize() {
	lsOutput=`ls -l --block-size=1 "$LAUNCHER_FULL_PATH" 2>/dev/null`
	if [ $? -ne 0 ] ; then
	    #default block size
	    lsOutput=`ls -l "$LAUNCHER_FULL_PATH" 2>/dev/null`
	fi
	echo "$lsOutput" | awk ' { print $5 }' 2>/dev/null
}

verifyIntegrity() {
	size=`getLauncherSize`
	extractedSize=$LAUNCHER_TRACKING_SIZE_BYTES
	if [ 1 -eq `ifNumber "$size"` ] ; then
		debug "... check integrity"
		debug "... minimal size : $extractedSize"
		debug "... real size    : $size"

        	if [ $size -lt $extractedSize ] ; then
			debug "... integration check FAILED"
			message "$MSG_ERROR_INTEGRITY" `normalizePath "$LAUNCHER_FULL_PATH"`
			exitProgram $ERROR_INTEGRITY
		fi
		debug "... integration check OK"
	fi
}
showHelp() {
	msg0=`message "$MSG_USAGE"`
	msg1=`message "$MSG_ARG_JAVAHOME $ARG_JAVAHOME"`
	msg2=`message "$MSG_ARG_TEMPDIR $ARG_TEMPDIR"`
	msg3=`message "$MSG_ARG_EXTRACT $ARG_EXTRACT"`
	msg4=`message "$MSG_ARG_OUTPUT $ARG_OUTPUT"`
	msg5=`message "$MSG_ARG_VERBOSE $ARG_VERBOSE"`
	msg6=`message "$MSG_ARG_CPA $ARG_CLASSPATHA"`
	msg7=`message "$MSG_ARG_CPP $ARG_CLASSPATHP"`
	msg8=`message "$MSG_ARG_DISABLE_FREE_SPACE_CHECK $ARG_NOSPACECHECK"`
        msg9=`message "$MSG_ARG_LOCALE $ARG_LOCALE"`
        msg10=`message "$MSG_ARG_SILENT $ARG_SILENT"`
	msg11=`message "$MSG_ARG_HELP $ARG_HELP"`
	out "$msg0"
	out "$msg1"
	out "$msg2"
	out "$msg3"
	out "$msg4"
	out "$msg5"
	out "$msg6"
	out "$msg7"
	out "$msg8"
	out "$msg9"
	out "$msg10"
	out "$msg11"
	exitProgram $ERROR_OK
}

exitProgram() {
	if [ 0 -eq $EXTRACT_ONLY ] ; then
	    if [ -n "$LAUNCHER_EXTRACT_DIR" ] && [ -d "$LAUNCHER_EXTRACT_DIR" ]; then		
		debug "Removing directory $LAUNCHER_EXTRACT_DIR"
		rm -rf "$LAUNCHER_EXTRACT_DIR" > /dev/null 2>&1
	    fi
	fi
	debug "exitCode = $1"
	exit $1
}

debug() {
        if [ $USE_DEBUG_OUTPUT -eq 1 ] ; then
		timestamp=`date '+%Y-%m-%d %H:%M:%S'`
                out "[$timestamp]> $1"
        fi
}

out() {
	
        if [ -n "$OUTPUT_FILE" ] ; then
                printf "%s\n" "$@" >> "$OUTPUT_FILE"
        elif [ 0 -eq $SILENT_MODE ] ; then
                printf "%s\n" "$@"
	fi
}

message() {        
        msg=`getMessage "$@"`
        out "$msg"
}


createTempDirectory() {
	if [ 0 -eq $EXTRACT_ONLY ] ; then
            if [ -z "$LAUNCHER_JVM_TEMP_DIR" ] ; then
		if [ 0 -eq $EXTRACT_ONLY ] ; then
                    if [ -n "$TEMP" ] && [ -d "$TEMP" ] ; then
                        debug "TEMP var is used : $TEMP"
                        LAUNCHER_JVM_TEMP_DIR="$TEMP"
                    elif [ -n "$TMP" ] && [ -d "$TMP" ] ; then
                        debug "TMP var is used : $TMP"
                        LAUNCHER_JVM_TEMP_DIR="$TMP"
                    elif [ -n "$TEMPDIR" ] && [ -d "$TEMPDIR" ] ; then
                        debug "TEMPDIR var is used : $TEMPDIR"
                        LAUNCHER_JVM_TEMP_DIR="$TEMPDIR"
                    elif [ -d "/tmp" ] ; then
                        debug "Using /tmp for temp"
                        LAUNCHER_JVM_TEMP_DIR="/tmp"
                    else
                        debug "Using home dir for temp"
                        LAUNCHER_JVM_TEMP_DIR="$HOME"
                    fi
		else
		    #extract only : to the curdir
		    LAUNCHER_JVM_TEMP_DIR="$CURRENT_DIRECTORY"		    
		fi
            fi
            # if temp dir does not exist then try to create it
            if [ ! -d "$LAUNCHER_JVM_TEMP_DIR" ] ; then
                mkdir -p "$LAUNCHER_JVM_TEMP_DIR" > /dev/null 2>&1
                if [ $? -ne 0 ] ; then                        
                        message "$MSG_ERROR_TMPDIR" "$LAUNCHER_JVM_TEMP_DIR"
                        exitProgram $ERROR_TEMP_DIRECTORY
                fi
            fi		
            debug "Launcher TEMP ROOT = $LAUNCHER_JVM_TEMP_DIR"
            subDir=`date '+%u%m%M%S'`
            subDir=`echo ".nbi-$subDir.tmp"`
            LAUNCHER_EXTRACT_DIR="$LAUNCHER_JVM_TEMP_DIR/$subDir"
	else
	    #extracting to the $LAUNCHER_EXTRACT_DIR
            debug "Launcher Extracting ROOT = $LAUNCHER_EXTRACT_DIR"
	fi

        if [ ! -d "$LAUNCHER_EXTRACT_DIR" ] ; then
                mkdir -p "$LAUNCHER_EXTRACT_DIR" > /dev/null 2>&1
                if [ $? -ne 0 ] ; then                        
                        message "$MSG_ERROR_TMPDIR"  "$LAUNCHER_EXTRACT_DIR"
                        exitProgram $ERROR_TEMP_DIRECTORY
                fi
        else
                debug "$LAUNCHER_EXTRACT_DIR is directory and exist"
        fi
        debug "Using directory $LAUNCHER_EXTRACT_DIR for extracting data"
}
extractJVMData() {
	debug "Extracting testJVM file data..."
        extractTestJVMFile
	debug "Extracting bundled JVMs ..."
	extractJVMFiles        
	debug "Extracting JVM data done"
}
extractBundledData() {
	message "$MSG_EXTRACTING"
	debug "Extracting bundled jars  data..."
	extractJars		
	debug "Extracting other  data..."
	extractOtherData
	debug "Extracting bundled data finished..."
}

setTestJVMClasspath() {
	testjvmname=`basename "$TEST_JVM_PATH"`
	removeClassSuffix=`echo "$testjvmname" | sed 's/\.class$//'`
	notClassFile=`ifEquals "$testjvmname" "$removeClassSuffix"`
		
	if [ -d "$TEST_JVM_PATH" ] ; then
		TEST_JVM_CLASSPATH="$TEST_JVM_PATH"
		debug "... testJVM path is a directory"
	elif [ $isSymlink "$TEST_JVM_PATH" ] && [ $notClassFile -eq 1 ] ; then
		TEST_JVM_CLASSPATH="$TEST_JVM_PATH"
		debug "... testJVM path is a link but not a .class file"
	else
		if [ $notClassFile -eq 1 ] ; then
			debug "... testJVM path is a jar/zip file"
			TEST_JVM_CLASSPATH="$TEST_JVM_PATH"
		else
			debug "... testJVM path is a .class file"
			TEST_JVM_CLASSPATH=`dirname "$TEST_JVM_PATH"`
		fi        
	fi
	debug "... testJVM classpath is : $TEST_JVM_CLASSPATH"
}

extractTestJVMFile() {
        TEST_JVM_PATH=`resolveResourcePath "TEST_JVM_FILE"`
	extractResource "TEST_JVM_FILE"
	setTestJVMClasspath
        
}

installJVM() {
	message "$MSG_PREPARE_JVM"	
	jvmFile=`resolveRelativity "$1"`
	jvmDir=`dirname "$jvmFile"`/_jvm
	debug "JVM Directory : $jvmDir"
	mkdir "$jvmDir" > /dev/null 2>&1
	if [ $? != 0 ] ; then
		message "$MSG_ERROR_EXTRACT_JVM"
		exitProgram $ERROR_JVM_EXTRACTION
	fi
        chmod +x "$jvmFile" > /dev/null  2>&1
	jvmFileEscaped=`escapeString "$jvmFile"`
        jvmDirEscaped=`escapeString "$jvmDir"`
	cd "$jvmDir"
        runCommand "$jvmFileEscaped"
	ERROR_CODE=$?

        cd "$CURRENT_DIRECTORY"

	if [ $ERROR_CODE != 0 ] ; then		
	        message "$MSG_ERROR_EXTRACT_JVM"
		exitProgram $ERROR_JVM_EXTRACTION
	fi
	
	files=`find "$jvmDir" -name "*.jar.pack.gz" -print`
	debug "Packed files : $files"
	f="$files"
	fileCounter=1;
	while [ -n "$f" ] ; do
		f=`echo "$files" | sed -n "${fileCounter}p" 2>/dev/null`
		debug "... next file is $f"				
		if [ -n "$f" ] ; then
			debug "... packed file  = $f"
			unpacked=`echo "$f" | sed s/\.pack\.gz//`
			debug "... unpacked file = $unpacked"
			fEsc=`escapeString "$f"`
			uEsc=`escapeString "$unpacked"`
			cmd="$jvmDirEscaped/bin/unpack200 -r $fEsc $uEsc"
			runCommand "$cmd"
			if [ $? != 0 ] ; then
			    message "$MSG_ERROR_UNPACK_JVM_FILE" "$f"
			    exitProgram $ERROR_JVM_UNPACKING
			fi		
		fi					
		fileCounter=`expr "$fileCounter" + 1`
	done
		
	verifyJVM "$jvmDir"
	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
		message "$MSG_ERROR_VERIFY_BUNDLED_JVM"
		exitProgram $ERROR_VERIFY_BUNDLED_JVM
	fi
}

resolveResourcePath() {
	resourcePrefix="$1"
	resourceVar="$""$resourcePrefix""_PATH"
	resourceName=`eval "echo \"$resourceVar\""`
	resourcePath=`resolveString "$resourceName"`
    	echo "$resourcePath"

}

resolveResourceSize() {
	resourcePrefix="$1"
	resourceVar="$""$resourcePrefix""_SIZE"
	resourceSize=`eval "echo \"$resourceVar\""`
    	echo "$resourceSize"
}

resolveResourceMd5() {
	resourcePrefix="$1"
	resourceVar="$""$resourcePrefix""_MD5"
	resourceMd5=`eval "echo \"$resourceVar\""`
    	echo "$resourceMd5"
}

resolveResourceType() {
	resourcePrefix="$1"
	resourceVar="$""$resourcePrefix""_TYPE"
	resourceType=`eval "echo \"$resourceVar\""`
	echo "$resourceType"
}

extractResource() {	
	debug "... extracting resource" 
        resourcePrefix="$1"
	debug "... resource prefix id=$resourcePrefix"	
	resourceType=`resolveResourceType "$resourcePrefix"`
	debug "... resource type=$resourceType"	
	if [ $resourceType -eq 0 ] ; then
                resourceSize=`resolveResourceSize "$resourcePrefix"`
		debug "... resource size=$resourceSize"
            	resourcePath=`resolveResourcePath "$resourcePrefix"`
	    	debug "... resource path=$resourcePath"
            	extractFile "$resourceSize" "$resourcePath"
                resourceMd5=`resolveResourceMd5 "$resourcePrefix"`
	    	debug "... resource md5=$resourceMd5"
                checkMd5 "$resourcePath" "$resourceMd5"
		debug "... done"
	fi
	debug "... extracting resource finished"	
        
}

extractJars() {
        counter=0
	while [ $counter -lt $JARS_NUMBER ] ; do
		extractResource "JAR_$counter"
		counter=`expr "$counter" + 1`
	done
}

extractOtherData() {
        counter=0
	while [ $counter -lt $OTHER_RESOURCES_NUMBER ] ; do
		extractResource "OTHER_RESOURCE_$counter"
		counter=`expr "$counter" + 1`
	done
}

extractJVMFiles() {
	javaCounter=0
	debug "... total number of JVM files : $JAVA_LOCATION_NUMBER"
	while [ $javaCounter -lt $JAVA_LOCATION_NUMBER ] ; do		
		extractResource "JAVA_LOCATION_$javaCounter"
		javaCounter=`expr "$javaCounter" + 1`
	done
}


processJarsClasspath() {
	JARS_CLASSPATH=""
	jarsCounter=0
	while [ $jarsCounter -lt $JARS_NUMBER ] ; do
		resolvedFile=`resolveResourcePath "JAR_$jarsCounter"`
		debug "... adding jar to classpath : $resolvedFile"
		if [ ! -f "$resolvedFile" ] && [ ! -d "$resolvedFile" ] && [ ! $isSymlink "$resolvedFile" ] ; then
				message "$MSG_ERROP_MISSING_RESOURCE" "$resolvedFile"
				exitProgram $ERROR_MISSING_RESOURCES
		else
			if [ -z "$JARS_CLASSPATH" ] ; then
				JARS_CLASSPATH="$resolvedFile"
			else				
				JARS_CLASSPATH="$JARS_CLASSPATH":"$resolvedFile"
			fi
		fi			
			
		jarsCounter=`expr "$jarsCounter" + 1`
	done
	debug "Jars classpath : $JARS_CLASSPATH"
}

extractFile() {
        start=$LAUNCHER_TRACKING_SIZE
        size=$1 #absolute size
        name="$2" #relative part        
        fullBlocks=`expr $size / $FILE_BLOCK_SIZE`
        fullBlocksSize=`expr "$FILE_BLOCK_SIZE" \* "$fullBlocks"`
        oneBlocks=`expr  $size - $fullBlocksSize`
	oneBlocksStart=`expr "$start" + "$fullBlocks"`

	checkFreeSpace $size "$name"	
	LAUNCHER_TRACKING_SIZE_BYTES=`expr "$LAUNCHER_TRACKING_SIZE" \* "$FILE_BLOCK_SIZE"`

	if [ 0 -eq $diskSpaceCheck ] ; then
		dir=`dirname "$name"`
		message "$MSG_ERROR_FREESPACE" "$size" "$ARG_TEMPDIR"	
		exitProgram $ERROR_FREESPACE
	fi

        if [ 0 -lt "$fullBlocks" ] ; then
                # file is larger than FILE_BLOCK_SIZE
                dd if="$LAUNCHER_FULL_PATH" of="$name" \
                        bs="$FILE_BLOCK_SIZE" count="$fullBlocks" skip="$start"\
			> /dev/null  2>&1
		LAUNCHER_TRACKING_SIZE=`expr "$LAUNCHER_TRACKING_SIZE" + "$fullBlocks"`
		LAUNCHER_TRACKING_SIZE_BYTES=`expr "$LAUNCHER_TRACKING_SIZE" \* "$FILE_BLOCK_SIZE"`
        fi
        if [ 0 -lt "$oneBlocks" ] ; then
		dd if="$LAUNCHER_FULL_PATH" of="$name.tmp.tmp" bs="$FILE_BLOCK_SIZE" count=1\
			skip="$oneBlocksStart"\
			 > /dev/null 2>&1

		dd if="$name.tmp.tmp" of="$name" bs=1 count="$oneBlocks" seek="$fullBlocksSize"\
			 > /dev/null 2>&1

		rm -f "$name.tmp.tmp"
		LAUNCHER_TRACKING_SIZE=`expr "$LAUNCHER_TRACKING_SIZE" + 1`

		LAUNCHER_TRACKING_SIZE_BYTES=`expr "$LAUNCHER_TRACKING_SIZE_BYTES" + "$oneBlocks"`
        fi        
}

md5_program=""
no_md5_program_id="no_md5_program"

initMD5program() {
    if [ -z "$md5_program" ] ; then 
        type digest >> /dev/null 2>&1
        if [ 0 -eq $? ] ; then
            md5_program="digest -a md5"
        else
            type md5sum >> /dev/null 2>&1
            if [ 0 -eq $? ] ; then
                md5_program="md5sum"
            else 
                type gmd5sum >> /dev/null 2>&1
                if [ 0 -eq $? ] ; then
                    md5_program="gmd5sum"
                else
                    type md5 >> /dev/null 2>&1
                    if [ 0 -eq $? ] ; then
                        md5_program="md5 -q"
                    else 
                        md5_program="$no_md5_program_id"
                    fi
                fi
            fi
        fi
        debug "... program to check: $md5_program"
    fi
}

checkMd5() {
     name="$1"
     md5="$2"     
     if [ 32 -eq `getStringLength "$md5"` ] ; then
         #do MD5 check         
         initMD5program            
         if [ 0 -eq `ifEquals "$md5_program" "$no_md5_program_id"` ] ; then
            debug "... check MD5 of file : $name"           
            debug "... expected md5: $md5"
            realmd5=`$md5_program "$name" 2>/dev/null | sed "s/ .*//g"`
            debug "... real md5 : $realmd5"
            if [ 32 -eq `getStringLength "$realmd5"` ] ; then
                if [ 0 -eq `ifEquals "$md5" "$realmd5"` ] ; then
                        debug "... integration check FAILED"
			message "$MSG_ERROR_INTEGRITY" `normalizePath "$LAUNCHER_FULL_PATH"`
			exitProgram $ERROR_INTEGRITY
                fi
            else
                debug "... looks like not the MD5 sum"
            fi
         fi
     fi   
}
searchJavaEnvironment() {
     if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
		    # search java in the environment
		
            	    ptr="$POSSIBLE_JAVA_ENV"
            	    while [ -n "$ptr" ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do
			argJavaHome=`echo "$ptr" | sed "s/:.*//"`
			back=`echo "$argJavaHome" | sed "s/\\\//\\\\\\\\\//g"`
		    	end=`echo "$ptr"       | sed "s/${back}://"`
			argJavaHome=`echo "$back" | sed "s/\\\\\\\\\//\\\//g"`
			ptr="$end"
                        eval evaluated=`echo \\$$argJavaHome` > /dev/null
                        if [ -n "$evaluated" ] ; then
                                debug "EnvVar $argJavaHome=$evaluated"				
                                verifyJVM "$evaluated"
                        fi
            	    done
     fi
}

installBundledJVMs() {
	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
	    # search bundled java in the common list
	    javaCounter=0
    	    while [ $javaCounter -lt $JAVA_LOCATION_NUMBER ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do
	    	fileType=`resolveResourceType "JAVA_LOCATION_$javaCounter"`
		
		if [ $fileType -eq 0 ] ; then # bundled->install
			argJavaHome=`resolveResourcePath "JAVA_LOCATION_$javaCounter"`
			installJVM  "$argJavaHome"				
        	fi
		javaCounter=`expr "$javaCounter" + 1`
    	    done
	fi
}

searchJavaOnMacOs() {
        if [ -x "/usr/libexec/java_home" ]; then
            javaOnMacHome=`/usr/libexec/java_home --version 1.8+ --failfast`
        fi

        if [ ! -x "$javaOnMacHome/bin/java" -a -f "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java" ] ; then
            javaOnMacHome=`echo "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home"`
        fi

        verifyJVM "$javaOnMacHome"
}

searchJavaSystemDefault() {
        if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
            debug "... check default java in the path"
            java_bin=`which java 2>&1`
            if [ $? -eq 0 ] && [ -n "$java_bin" ] ; then
                remove_no_java_in=`echo "$java_bin" | sed "s/no java in//g"`
                if [ 1 -eq `ifEquals "$remove_no_java_in" "$java_bin"` ] && [ -f "$java_bin" ] ; then
                    debug "... java in path found: $java_bin"
                    # java is in path
                    java_bin=`resolveSymlink "$java_bin"`
                    debug "... java real path: $java_bin"
                    parentDir=`dirname "$java_bin"`
                    if [ -n "$parentDir" ] ; then
                        parentDir=`dirname "$parentDir"`
                        if [ -n "$parentDir" ] ; then
                            debug "... java home path: $parentDir"
                            parentDir=`resolveSymlink "$parentDir"`
                            debug "... java home real path: $parentDir"
                            verifyJVM "$parentDir"
                        fi
                    fi
                fi
            fi
	fi
}

searchJavaSystemPaths() {
	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
	    # search java in the common system paths
	    javaCounter=0
    	    while [ $javaCounter -lt $JAVA_LOCATION_NUMBER ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do
	    	fileType=`resolveResourceType "JAVA_LOCATION_$javaCounter"`
	    	argJavaHome=`resolveResourcePath "JAVA_LOCATION_$javaCounter"`

	    	debug "... next location $argJavaHome"
		
		if [ $fileType -ne 0 ] ; then # bundled JVMs have already been proceeded
			argJavaHome=`escapeString "$argJavaHome"`
			locations=`ls -d -1 $argJavaHome 2>/dev/null`
			nextItem="$locations"
			itemCounter=1
			while [ -n "$nextItem" ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do
				nextItem=`echo "$locations" | sed -n "${itemCounter}p" 2>/dev/null`
				debug "... next item is $nextItem"				
				nextItem=`removeEndSlashes "$nextItem"`
				if [ -n "$nextItem" ] ; then
					if [ -d "$nextItem" ] || [ $isSymlink "$nextItem" ] ; then
	               				debug "... checking item : $nextItem"
						verifyJVM "$nextItem"
					fi
				fi					
				itemCounter=`expr "$itemCounter" + 1`
			done
		fi
		javaCounter=`expr "$javaCounter" + 1`
    	    done
	fi
}

searchJavaUserDefined() {
	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
        	if [ -n "$LAUNCHER_JAVA" ] ; then
                	verifyJVM "$LAUNCHER_JAVA"
		
			if [ $VERIFY_UNCOMPATIBLE -eq $verifyResult ] ; then
		    		message "$MSG_ERROR_JVM_UNCOMPATIBLE" "$LAUNCHER_JAVA" "$ARG_JAVAHOME"
		    		exitProgram $ERROR_JVM_UNCOMPATIBLE
			elif [ $VERIFY_NOJAVA -eq $verifyResult ] ; then
				message "$MSG_ERROR_USER_ERROR" "$LAUNCHER_JAVA"
		    		exitProgram $ERROR_JVM_NOT_FOUND
			fi
        	fi
	fi
}

searchJavaInstallFolder() {
        installFolder="`dirname \"$0\"`"
        installFolder="`( cd \"$installFolder\" && pwd )`"
        installFolder="$installFolder/bin/jre"
        tempJreFolder="$TEST_JVM_CLASSPATH/_jvm"

        if [ -d "$installFolder" ] ; then
            #copy nested JRE to temp folder
            cp -r "$installFolder" "$tempJreFolder"

            verifyJVM "$tempJreFolder"
        fi
}

searchJava() {
	message "$MSG_JVM_SEARCH"
        if [ ! -f "$TEST_JVM_CLASSPATH" ] && [ ! $isSymlink "$TEST_JVM_CLASSPATH" ] && [ ! -d "$TEST_JVM_CLASSPATH" ]; then
                debug "Cannot find file for testing JVM at $TEST_JVM_CLASSPATH"
		message "$MSG_ERROR_JVM_NOT_FOUND" "$ARG_JAVAHOME"
                exitProgram $ERROR_TEST_JVM_FILE
        else	
                searchJavaInstallFolder
		searchJavaUserDefined
		installBundledJVMs
		searchJavaEnvironment
		searchJavaSystemDefault
		searchJavaSystemPaths
                if [ 1 -eq $isMacOSX ] ; then
                    searchJavaOnMacOs
                fi
        fi

	if [ -z "$LAUNCHER_JAVA_EXE" ] ; then
		message "$MSG_ERROR_JVM_NOT_FOUND" "$ARG_JAVAHOME"
		exitProgram $ERROR_JVM_NOT_FOUND
	fi
}

normalizePath() {	
	argument="$1"
  
  # replace all /./ to /
	while [ 0 -eq 0 ] ; do	
		testArgument=`echo "$argument" | sed 's/\/\.\//\//g' 2> /dev/null`
		if [ -n "$testArgument" ] && [ 0 -eq `ifEquals "$argument" "$testArgument"` ] ; then
		  # something changed
			argument="$testArgument"
		else
			break
		fi	
	done

	# replace XXX/../YYY to 'dirname XXX'/YYY
	while [ 0 -eq 0 ] ; do	
		beforeDotDot=`echo "$argument" | sed "s/\/\.\.\/.*//g" 2> /dev/null`
      if [ 0 -eq `ifEquals "$beforeDotDot" "$argument"` ] && [ 0 -eq `ifEquals "$beforeDotDot" "."` ] && [ 0 -eq `ifEquals "$beforeDotDot" ".."` ] ; then
        esc=`echo "$beforeDotDot" | sed "s/\\\//\\\\\\\\\//g"`
        afterDotDot=`echo "$argument" | sed "s/^$esc\/\.\.//g" 2> /dev/null` 
        parent=`dirname "$beforeDotDot"`
        argument=`echo "$parent""$afterDotDot"`
		else 
      break
		fi	
	done

	# replace XXX/.. to 'dirname XXX'
	while [ 0 -eq 0 ] ; do	
		beforeDotDot=`echo "$argument" | sed "s/\/\.\.$//g" 2> /dev/null`
    if [ 0 -eq `ifEquals "$beforeDotDot" "$argument"` ] && [ 0 -eq `ifEquals "$beforeDotDot" "."` ] && [ 0 -eq `ifEquals "$beforeDotDot" ".."` ] ; then
		  argument=`dirname "$beforeDotDot"`
		else 
      break
		fi	
	done

  # remove /. a the end (if the resulting string is not zero)
	testArgument=`echo "$argument" | sed 's/\/\.$//' 2> /dev/null`
	if [ -n "$testArgument" ] ; then
		argument="$testArgument"
	fi

	# replace more than 2 separators to 1
	testArgument=`echo "$argument" | sed 's/\/\/*/\//g' 2> /dev/null`
	if [ -n "$testArgument" ] ; then
		argument="$testArgument"
	fi
	
	echo "$argument"	
}

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

verifyJVM() {                
    javaTryPath=`normalizePath "$1"` 
    verifyJavaHome "$javaTryPath"
    if [ $VERIFY_OK -ne $verifyResult ] ; then
	savedResult=$verifyResult

    	if [ 0 -eq $isMacOSX ] ; then
        	#check private jre
		javaTryPath="$javaTryPath""/jre"
		verifyJavaHome "$javaTryPath"	
    	else
		#check MacOSX Home dir
		javaTryPath="$javaTryPath""/Home"
		verifyJavaHome "$javaTryPath"			
	fi	
	
	if [ $VERIFY_NOJAVA -eq $verifyResult ] ; then                                           
		verifyResult=$savedResult
	fi 
    fi
}

removeEndSlashes() {
 arg="$1"
 tryRemove=`echo "$arg" | sed 's/\/\/*$//' 2>/dev/null`
 if [ -n "$tryRemove" ] ; then
      arg="$tryRemove"
 fi
 echo "$arg"
}

checkJavaHierarchy() {
	# return 0 on no java
	# return 1 on jre
	# return 2 on jdk

	tryJava="$1"
	javaHierarchy=0
	if [ -n "$tryJava" ] ; then
		if [ -d "$tryJava" ] || [ $isSymlink "$tryJava" ] ; then # existing directory or a isSymlink        			
			javaBin="$tryJava"/"bin"
	        
			if [ -d "$javaBin" ] || [ $isSymlink "$javaBin" ] ; then
				javaBinJavac="$javaBin"/"javac"
				if [ -f "$javaBinJavac" ] || [ $isSymlink "$javaBinJavac" ] ; then
					#definitely JDK as the JRE doesn`t contain javac
					javaHierarchy=2				
				else
					#check if we inside JRE
					javaBinJava="$javaBin"/"java"
					if [ -f "$javaBinJava" ] || [ $isSymlink "$javaBinJava" ] ; then
						javaHierarchy=1
					fi					
				fi
			fi
		fi
	fi
	if [ 0 -eq $javaHierarchy ] ; then
		debug "... no java there"
	elif [ 1 -eq $javaHierarchy ] ; then
		debug "... JRE there"
	elif [ 2 -eq $javaHierarchy ] ; then
		debug "... JDK there"
	fi
}

verifyJavaHome() { 
    verifyResult=$VERIFY_NOJAVA
    java=`removeEndSlashes "$1"`
    debug "... verify    : $java"    

    java=`resolveSymlink "$java"`    
    debug "... real path : $java"

    checkJavaHierarchy "$java"
	
    if [ 0 -ne $javaHierarchy ] ; then 
	testJVMclasspath=`escapeString "$TEST_JVM_CLASSPATH"`
	testJVMclass=`escapeString "$TEST_JVM_CLASS"`

        pointer="$POSSIBLE_JAVA_EXE_SUFFIX"
        while [ -n "$pointer" ] && [ -z "$LAUNCHER_JAVA_EXE" ]; do
            arg=`echo "$pointer" | sed "s/:.*//"`
	    back=`echo "$arg" | sed "s/\\\//\\\\\\\\\//g"`
	    end=`echo "$pointer"       | sed "s/${back}://"`
	    arg=`echo "$back" | sed "s/\\\\\\\\\//\\\//g"`
	    pointer="$end"
            javaExe="$java/$arg"	    

            if [ -x "$javaExe" ] ; then		
                javaExeEscaped=`escapeString "$javaExe"`
                command="$javaExeEscaped -classpath $testJVMclasspath $testJVMclass"

                debug "Executing java verification command..."
		debug "$command"
                output=`eval "$command" 2>/dev/null`
                javaVersion=`echo "$output"   | sed "2d;3d;4d;5d"`
		javaVmVersion=`echo "$output" | sed "1d;3d;4d;5d"`
		vendor=`echo "$output"        | sed "1d;2d;4d;5d"`
		osname=`echo "$output"        | sed "1d;2d;3d;5d"`
		osarch=`echo "$output"        | sed "1d;2d;3d;4d"`

		debug "Java :"
                debug "       executable = {$javaExe}"	
		debug "      javaVersion = {$javaVersion}"
		debug "    javaVmVersion = {$javaVmVersion}"
		debug "           vendor = {$vendor}"
		debug "           osname = {$osname}"
		debug "           osarch = {$osarch}"
		comp=0

		if [ -n "$javaVersion" ] && [ -n "$javaVmVersion" ] && [ -n "$vendor" ] && [ -n "$osname" ] && [ -n "$osarch" ] ; then
		    debug "... seems to be java indeed"
		    javaVersionEsc=`escapeBackslash "$javaVersion"`
                    javaVmVersionEsc=`escapeBackslash "$javaVmVersion"`
                    javaVersion=`awk 'END { idx = index(b,a); if(idx!=0) { print substr(b,idx,length(b)) } else { print a } }' a="$javaVersionEsc" b="$javaVmVersionEsc" < /dev/null`

		    #remove build number
		    javaVersion=`echo "$javaVersion" | sed 's/-.*$//;s/\ .*//'`
		    verifyResult=$VERIFY_UNCOMPATIBLE

	            if [ -n "$javaVersion" ] ; then
			debug " checking java version = {$javaVersion}"
			javaCompCounter=0

			while [ $javaCompCounter -lt $JAVA_COMPATIBLE_PROPERTIES_NUMBER ] && [ -z "$LAUNCHER_JAVA_EXE" ] ; do				
				comp=1
				setJavaCompatibilityProperties_$javaCompCounter
				debug "Min Java Version : $JAVA_COMP_VERSION_MIN"
				debug "Max Java Version : $JAVA_COMP_VERSION_MAX"
				debug "Java Vendor      : $JAVA_COMP_VENDOR"
				debug "Java OS Name     : $JAVA_COMP_OSNAME"
				debug "Java OS Arch     : $JAVA_COMP_OSARCH"

				if [ -n "$JAVA_COMP_VERSION_MIN" ] ; then
                                    compMin=`ifVersionLess "$javaVersion" "$JAVA_COMP_VERSION_MIN"`
                                    if [ 1 -eq $compMin ] ; then
                                        comp=0
                                    fi
				fi

		                if [ -n "$JAVA_COMP_VERSION_MAX" ] ; then
                                    compMax=`ifVersionGreater "$javaVersion" "$JAVA_COMP_VERSION_MAX"`
                                    if [ 1 -eq $compMax ] ; then
                                        comp=0
                                    fi
		                fi				
				if [ -n "$JAVA_COMP_VENDOR" ] ; then
					debug " checking vendor = {$vendor}, {$JAVA_COMP_VENDOR}"
					subs=`echo "$vendor" | sed "s/${JAVA_COMP_VENDOR}//"`
					if [ `ifEquals "$subs" "$vendor"` -eq 1 ]  ; then
						comp=0
						debug "... vendor incompatible"
					fi
				fi
	
				if [ -n "$JAVA_COMP_OSNAME" ] ; then
					debug " checking osname = {$osname}, {$JAVA_COMP_OSNAME}"
					subs=`echo "$osname" | sed "s/${JAVA_COMP_OSNAME}//"`
					
					if [ `ifEquals "$subs" "$osname"` -eq 1 ]  ; then
						comp=0
						debug "... osname incompatible"
					fi
				fi
				if [ -n "$JAVA_COMP_OSARCH" ] ; then
					debug " checking osarch = {$osarch}, {$JAVA_COMP_OSARCH}"
					subs=`echo "$osarch" | sed "s/${JAVA_COMP_OSARCH}//"`
					
					if [ `ifEquals "$subs" "$osarch"` -eq 1 ]  ; then
						comp=0
						debug "... osarch incompatible"
					fi
				fi
				if [ $comp -eq 1 ] ; then
				        LAUNCHER_JAVA_EXE="$javaExe"
					LAUNCHER_JAVA="$java"
					verifyResult=$VERIFY_OK
		    		fi
				debug "       compatible = [$comp]"
				javaCompCounter=`expr "$javaCompCounter" + 1`
			done
		    fi		    
		fi		
            fi	    
        done
   fi
}

checkFreeSpace() {
	size="$1"
	path="$2"

	if [ ! -d "$path" ] && [ ! $isSymlink "$path" ] ; then
		# if checking path is not an existing directory - check its parent dir
		path=`dirname "$path"`
	fi

	diskSpaceCheck=0

	if [ 0 -eq $PERFORM_FREE_SPACE_CHECK ] ; then
		diskSpaceCheck=1
	else
		# get size of the atomic entry (directory)
		freeSpaceDirCheck="$path"/freeSpaceCheckDir
		debug "Checking space in $path (size = $size)"
		mkdir -p "$freeSpaceDirCheck"
		# POSIX compatible du return size in 1024 blocks
		du --block-size=$DEFAULT_DISK_BLOCK_SIZE "$freeSpaceDirCheck" 1>/dev/null 2>&1
		
		if [ $? -eq 0 ] ; then 
			debug "    getting POSIX du with 512 bytes blocks"
			atomicBlock=`du --block-size=$DEFAULT_DISK_BLOCK_SIZE "$freeSpaceDirCheck" | awk ' { print $A }' A=1 2>/dev/null` 
		else
			debug "    getting du with default-size blocks"
			atomicBlock=`du "$freeSpaceDirCheck" | awk ' { print $A }' A=1 2>/dev/null` 
		fi
		rm -rf "$freeSpaceDirCheck"
	        debug "    atomic block size : [$atomicBlock]"

                isBlockNumber=`ifNumber "$atomicBlock"`
		if [ 0 -eq $isBlockNumber ] ; then
			out "Can\`t get disk block size"
			exitProgram $ERROR_INPUTOUPUT
		fi
		requiredBlocks=`expr \( "$1" / $DEFAULT_DISK_BLOCK_SIZE \) + $atomicBlock` 1>/dev/null 2>&1
		if [ `ifNumber $1` -eq 0 ] ; then 
		        out "Can\`t calculate required blocks size"
			exitProgram $ERROR_INPUTOUPUT
		fi
		# get free block size
		column=4
		df -P --block-size="$DEFAULT_DISK_BLOCK_SIZE" "$path" 1>/dev/null 2>&1
		if [ $? -eq 0 ] ; then 
			# gnu df, use POSIX output
			 debug "    getting GNU POSIX df with specified block size $DEFAULT_DISK_BLOCK_SIZE"
			 availableBlocks=`df -P --block-size="$DEFAULT_DISK_BLOCK_SIZE"  "$path" | sed "1d" | awk ' { print $A }' A=$column 2>/dev/null`
		else 
			# try POSIX output
			df -P "$path" 1>/dev/null 2>&1
			if [ $? -eq 0 ] ; then 
				 debug "    getting POSIX df with 512 bytes blocks"
				 availableBlocks=`df -P "$path" | sed "1d" | awk ' { print $A }' A=$column 2>/dev/null`
			# try  Solaris df from xpg4
			elif  [ -x /usr/xpg4/bin/df ] ; then 
				 debug "    getting xpg4 df with default-size blocks"
				 availableBlocks=`/usr/xpg4/bin/df -P "$path" | sed "1d" | awk ' { print $A }' A=$column 2>/dev/null`
			# last chance to get free space
			else		
				 debug "    getting df with default-size blocks"
				 availableBlocks=`df "$path" | sed "1d" | awk ' { print $A }' A=$column 2>/dev/null`
			fi
		fi
		debug "    available blocks : [$availableBlocks]"
		if [ `ifNumber "$availableBlocks"` -eq 0 ] ; then
			out "Can\`t get the number of the available blocks on the system"
			exitProgram $ERROR_INPUTOUTPUT
		fi
		
		# compare
                debug "    required  blocks : [$requiredBlocks]"

		if [ $availableBlocks -gt $requiredBlocks ] ; then
			debug "... disk space check OK"
			diskSpaceCheck=1
		else 
		        debug "... disk space check FAILED"
		fi
	fi
	if [ 0 -eq $diskSpaceCheck ] ; then
		mbDownSize=`expr "$size" / 1024 / 1024`
		mbUpSize=`expr "$size" / 1024 / 1024 + 1`
		mbSize=`expr "$mbDownSize" \* 1024 \* 1024`
		if [ $size -ne $mbSize ] ; then	
			mbSize="$mbUpSize"
		else
			mbSize="$mbDownSize"
		fi
		
		message "$MSG_ERROR_FREESPACE" "$mbSize" "$ARG_TEMPDIR"	
		exitProgram $ERROR_FREESPACE
	fi
}

prepareClasspath() {
    debug "Processing external jars ..."
    processJarsClasspath
 
    LAUNCHER_CLASSPATH=""
    if [ -n "$JARS_CLASSPATH" ] ; then
		if [ -z "$LAUNCHER_CLASSPATH" ] ; then
			LAUNCHER_CLASSPATH="$JARS_CLASSPATH"
		else
			LAUNCHER_CLASSPATH="$LAUNCHER_CLASSPATH":"$JARS_CLASSPATH"
		fi
    fi

    if [ -n "$PREPEND_CP" ] ; then
	debug "Appending classpath with [$PREPEND_CP]"
	PREPEND_CP=`resolveString "$PREPEND_CP"`

	if [ -z "$LAUNCHER_CLASSPATH" ] ; then
		LAUNCHER_CLASSPATH="$PREPEND_CP"		
	else
		LAUNCHER_CLASSPATH="$PREPEND_CP":"$LAUNCHER_CLASSPATH"	
	fi
    fi
    if [ -n "$APPEND_CP" ] ; then
	debug "Appending classpath with [$APPEND_CP]"
	APPEND_CP=`resolveString "$APPEND_CP"`
	if [ -z "$LAUNCHER_CLASSPATH" ] ; then
		LAUNCHER_CLASSPATH="$APPEND_CP"	
	else
		LAUNCHER_CLASSPATH="$LAUNCHER_CLASSPATH":"$APPEND_CP"	
	fi
    fi
    debug "Launcher Classpath : $LAUNCHER_CLASSPATH"
}

resolvePropertyStrings() {
	args="$1"
	escapeReplacedString="$2"
	propertyStart=`echo "$args" | sed "s/^.*\\$P{//"`
	propertyValue=""
	propertyName=""

	#Resolve i18n strings and properties
	if [ 0 -eq `ifEquals "$propertyStart" "$args"` ] ; then
		propertyName=`echo "$propertyStart" |  sed "s/}.*//" 2>/dev/null`
		if [ -n "$propertyName" ] ; then
			propertyValue=`getMessage "$propertyName"`

			if [ 0 -eq `ifEquals "$propertyValue" "$propertyName"` ] ; then				
				propertyName="\$P{$propertyName}"
				args=`replaceString "$args" "$propertyName" "$propertyValue" "$escapeReplacedString"`
			fi
		fi
	fi
			
	echo "$args"
}


resolveLauncherSpecialProperties() {
	args="$1"
	escapeReplacedString="$2"
	propertyValue=""
	propertyName=""
	propertyStart=`echo "$args" | sed "s/^.*\\$L{//"`

	
        if [ 0 -eq `ifEquals "$propertyStart" "$args"` ] ; then
 		propertyName=`echo "$propertyStart" |  sed "s/}.*//" 2>/dev/null`
		

		if [ -n "$propertyName" ] ; then
			case "$propertyName" in
		        	"nbi.launcher.tmp.dir")                        		
					propertyValue="$LAUNCHER_EXTRACT_DIR"
					;;
				"nbi.launcher.java.home")	
					propertyValue="$LAUNCHER_JAVA"
					;;
				"nbi.launcher.user.home")
					propertyValue="$HOME"
					;;
				"nbi.launcher.parent.dir")
					propertyValue="$LAUNCHER_DIR"
					;;
				*)
					propertyValue="$propertyName"
					;;
			esac
			if [ 0 -eq `ifEquals "$propertyValue" "$propertyName"` ] ; then				
				propertyName="\$L{$propertyName}"
				args=`replaceString "$args" "$propertyName" "$propertyValue" "$escapeReplacedString"`
			fi      
		fi
	fi            
	echo "$args"
}

resolveString() {
 	args="$1"
	escapeReplacedString="$2"
	last="$args"
	repeat=1

	while [ 1 -eq $repeat ] ; do
		repeat=1
		args=`resolvePropertyStrings "$args" "$escapeReplacedString"`
		args=`resolveLauncherSpecialProperties "$args" "$escapeReplacedString"`		
		if [ 1 -eq `ifEquals "$last" "$args"` ] ; then
		    repeat=0
		fi
		last="$args"
	done
	echo "$args"
}

replaceString() {
	initialString="$1"	
	fromString="$2"
	toString="$3"
	if [ -n "$4" ] && [ 0 -eq `ifEquals "$4" "false"` ] ; then
		toString=`escapeString "$toString"`
	fi
	fromString=`echo "$fromString" | sed "s/\\\//\\\\\\\\\//g" 2>/dev/null`
	toString=`echo "$toString" | sed "s/\\\//\\\\\\\\\//g" 2>/dev/null`
        replacedString=`echo "$initialString" | sed "s/${fromString}/${toString}/g" 2>/dev/null`        
	echo "$replacedString"
}

prepareJVMArguments() {
    debug "Prepare JVM arguments... "    

    jvmArgCounter=0
    debug "... resolving string : $LAUNCHER_JVM_ARGUMENTS"
    LAUNCHER_JVM_ARGUMENTS=`resolveString "$LAUNCHER_JVM_ARGUMENTS" true`
    debug "... resolved  string :  $LAUNCHER_JVM_ARGUMENTS"
    while [ $jvmArgCounter -lt $JVM_ARGUMENTS_NUMBER ] ; do		
	 argumentVar="$""JVM_ARGUMENT_$jvmArgCounter"
         arg=`eval "echo \"$argumentVar\""`
	 debug "... jvm argument [$jvmArgCounter] [initial]  : $arg"
	 arg=`resolveString "$arg"`
	 debug "... jvm argument [$jvmArgCounter] [resolved] : $arg"
	 arg=`escapeString "$arg"`
	 debug "... jvm argument [$jvmArgCounter] [escaped] : $arg"
	 LAUNCHER_JVM_ARGUMENTS="$LAUNCHER_JVM_ARGUMENTS $arg"	
 	 jvmArgCounter=`expr "$jvmArgCounter" + 1`
    done                
    if [ ! -z "${DEFAULT_USERDIR_ROOT}" ] ; then
            debug "DEFAULT_USERDIR_ROOT: $DEFAULT_USERDIR_ROOT"
            LAUNCHER_JVM_ARGUMENTS="$LAUNCHER_JVM_ARGUMENTS -Dnetbeans.default_userdir_root=\"${DEFAULT_USERDIR_ROOT}\""	
    fi
    if [ ! -z "${DEFAULT_CACHEDIR_ROOT}" ] ; then
            debug "DEFAULT_CACHEDIR_ROOT: $DEFAULT_CACHEDIR_ROOT"
            LAUNCHER_JVM_ARGUMENTS="$LAUNCHER_JVM_ARGUMENTS -Dnetbeans.default_cachedir_root=\"${DEFAULT_CACHEDIR_ROOT}\""	
    fi

    debug "Final JVM arguments : $LAUNCHER_JVM_ARGUMENTS"            
}

prepareAppArguments() {
    debug "Prepare Application arguments... "    

    appArgCounter=0
    debug "... resolving string : $LAUNCHER_APP_ARGUMENTS"
    LAUNCHER_APP_ARGUMENTS=`resolveString "$LAUNCHER_APP_ARGUMENTS" true`
    debug "... resolved  string :  $LAUNCHER_APP_ARGUMENTS"
    while [ $appArgCounter -lt $APP_ARGUMENTS_NUMBER ] ; do		
	 argumentVar="$""APP_ARGUMENT_$appArgCounter"
         arg=`eval "echo \"$argumentVar\""`
	 debug "... app argument [$appArgCounter] [initial]  : $arg"
	 arg=`resolveString "$arg"`
	 debug "... app argument [$appArgCounter] [resolved] : $arg"
	 arg=`escapeString "$arg"`
	 debug "... app argument [$appArgCounter] [escaped] : $arg"
	 LAUNCHER_APP_ARGUMENTS="$LAUNCHER_APP_ARGUMENTS $arg"	
 	 appArgCounter=`expr "$appArgCounter" + 1`
    done
    debug "Final application arguments : $LAUNCHER_APP_ARGUMENTS"            
}


runCommand() {
	cmd="$1"
	debug "Running command : $cmd"
	if [ -n "$OUTPUT_FILE" ] ; then
		#redirect all stdout and stderr from the running application to the file
		eval "$cmd" >> "$OUTPUT_FILE" 2>&1
	elif [ 1 -eq $SILENT_MODE ] ; then
		# on silent mode redirect all out/err to null
		eval "$cmd" > /dev/null 2>&1	
	elif [ 0 -eq $USE_DEBUG_OUTPUT ] ; then
		# redirect all output to null
		# do not redirect errors there but show them in the shell output
		eval "$cmd" > /dev/null	
	else
		# using debug output to the shell
		# not a silent mode but a verbose one
		eval "$cmd"
	fi
	return $?
}

executeMainClass() {
	prepareClasspath
	prepareJVMArguments
	prepareAppArguments
	debug "Running main jar..."
	message "$MSG_RUNNING"
	classpathEscaped=`escapeString "$LAUNCHER_CLASSPATH"`
	mainClassEscaped=`escapeString "$MAIN_CLASS"`
	launcherJavaExeEscaped=`escapeString "$LAUNCHER_JAVA_EXE"`
	tmpdirEscaped=`escapeString "$LAUNCHER_JVM_TEMP_DIR"`
	
	command="$launcherJavaExeEscaped $LAUNCHER_JVM_ARGUMENTS -Djava.io.tmpdir=$tmpdirEscaped -classpath $classpathEscaped $mainClassEscaped $LAUNCHER_APP_ARGUMENTS"

	debug "Running command : $command"
	runCommand "$command"
	exitCode=$?
	debug "... java process finished with code $exitCode"
	exitProgram $exitCode
}

escapeString() {
	echo "$1" | sed "s/\\\/\\\\\\\/g;s/\ /\\\\ /g;s/\"/\\\\\"/g;s/(/\\\\\(/g;s/)/\\\\\)/g;" # escape spaces, commas and parentheses
}

getMessage() {
        getLocalizedMessage_$LAUNCHER_LOCALE $@
}

POSSIBLE_JAVA_ENV="JAVA:JAVA_HOME:JAVAHOME:JAVA_PATH:JAVAPATH:JDK:JDK_HOME:JDKHOME:ANT_JAVA:"
POSSIBLE_JAVA_EXE_SUFFIX_SOLARIS="bin/java:bin/sparcv9/java:"
POSSIBLE_JAVA_EXE_SUFFIX_COMMON="bin/java:"
