mac: Use universalJavaApplicationStub

Here's a (very rough) implementation of a macBundle task using the
universalJavaApplicationStub and jarbundler.  Jarbundler's support files
(ant build system and docs) are suffering bitrot, and I don't grok maven
yet, so I'm really flying blind with it, so basically I'm committing it
in a "baseline" working (if ugly) state.

So ... _why_ use this?

The old way of bundling Java apps doesn't work anymore.  It tells you to
get Apple's (compromised/unsafe) Java 6 and when you do it throws an
error because your code compiled on Oracle JDK 8/9 won't run on it
anymore.

You're supposed to duplicate the JRE in each Java program you bundle as
you would a private/custom framework.  Yes, really.  This solves the
dependency issues at the cost of heavy resource waste.  Except every new
JDK generation changes HOW you do that, and the current method is
totally proprietary to Oracle's JDK.  For cross-platform development, it
is NOT fun.

So there's uJAS, which is literally a complex shell script to magically
do the equivalent of typing java -jar <your program> from the command
line—which does work BTW if all your dependencies are properly in your
default classpath, etc.  There used to be a couple of application
bundler options, but the one that still works (only with uJAS if you
have the most recent JDKs), is jarbundler.

TODO: Clean this up, restore original functionality (zipball), include
the commandline jar, etc.

committing it in this state is that jarbundler's repo is a bit of a
mess.  The current version (and the version we need) is 3.3.0, the
"latest" from 2015.  The docs, examples, and the ant build system are
all literally bitrotting from version 2.x, and do not work without some
fixes.

So in other words, I'm committing this in a state that I got to work so
that if I screw it up, since I'm flying blind, I'll have a messy but
working fallback.

Okay, so _why_ use any of this at all?

If you create an ACBuild.properties file and run ant, you can get
AppleCommander.app to build, but it won't run.  It tells you that you
need to download Apple's legacy Java 6 which is neither safe nor
supported anymore.  If you install this, it will still give you an
error because the generated code can't run under Java 6.

What you're supposed to do now is bundle your JRE with every Java
application bundle, which means multiple copies of libs on disk and in
memory.  Yes, really.  Except Oracle keeps changing how you do this with
each new JDK generation, and the current way is pretty much totally
proprietary so that you're locked in to Oracle's JDK and couldn't use
OpenJDK or something if that were an option.

That's what universalJavaApplicationStub resolves—it builds an app
bundle that uses whatever JDK/JRE you have installed from 6 onwards.
And it in turn needs jarbundler or something like it.  Except all of the
"something like it" solutions are dead or deprecated save the latest
release of jarbundler which was modified to support uJAS and then
promptly left more or less untouched since.  But it "works".
This commit is contained in:
T. Joseph Carter 2017-10-30 06:14:13 -07:00
parent 752cdc91b6
commit 2e2a34e77e
3 changed files with 562 additions and 1 deletions

View File

@ -29,6 +29,10 @@
<available file="${keyconf}" property="keyconf-exists" /> <available file="${keyconf}" property="keyconf-exists" />
</condition> </condition>
<taskdef name="jarbundler"
classname="com.ultramixer.jarbundler.JarBundler"
classpath="mac/jarbundler-core-3.3.0.jar" />
<target name="version" description="Get version from source."> <target name="version" description="Get version from source.">
<property name="main.path" value="src/com/webcodepro/applecommander/ui"/> <property name="main.path" value="src/com/webcodepro/applecommander/ui"/>
<loadfile srcfile="${main.path}/AppleCommander.java" property="acVersion"> <loadfile srcfile="${main.path}/AppleCommander.java" property="acVersion">
@ -128,21 +132,43 @@
<target name="macBundle" depends="init,jars" description="Build Mac application bundle."> <target name="macBundle" depends="init,jars" description="Build Mac application bundle.">
<property name="mac.dir" value="mac"/> <property name="mac.dir" value="mac"/>
<!--
<property name="mac.app" value="${mac.dir}/AppleCommander.app"/> <property name="mac.app" value="${mac.dir}/AppleCommander.app"/>
<property name="mac.Contents" value="${mac.app}/Contents"/> <property name="mac.Contents" value="${mac.app}/Contents"/>
<property name="mac.Java" value="${mac.Contents}/Resources/Java"/> <property name="mac.Java" value="${mac.Contents}/Resources/Java"/>
-->
<!--
<copy file="${mac.dir}/Info.plist" todir="${mac.Contents}" overwrite="true"> <copy file="${mac.dir}/Info.plist" todir="${mac.Contents}" overwrite="true">
<filterset> <filterset>
<filter token="version" value="${acVersion}"/> <filter token="version" value="${acVersion}"/>
</filterset> </filterset>
</copy> </copy>
-->
<jarbundler dir="${dist}" verbose="true" showPlist="true"
name="AppleCommander"
mainclass="com.webcodepro.applecommander.ui.AppleCommander"
bundleid="com.webcodepro.applecommander"
jar="${dist}/AppleCommander-${acVersion}.jar"
version="${acVersion}" build="${acVersion}"
stubfile="mac/universalJavaApplicationStub"
icon="mac/AppleCommander.app/Contents/Resources/AppleCommander.icns"
useJavaXKey="true"
developmentregion="English"
copyright="Copyright 2002-2008 Rob Greene and John B. Matthews."
jvmversion="1.4*"
/>
<!--
<copy file="${guijar}" tofile="${mac.Java}/AppleCommander.jar"/> <copy file="${guijar}" tofile="${mac.Java}/AppleCommander.jar"/>
<copy file="${cmdjar}" tofile="${user.home}/bin/ac.jar"/> <copy file="${cmdjar}" tofile="${user.home}/bin/ac.jar"/>
-->
<!--
<zip destfile="${maczip}"> <zip destfile="${maczip}">
<zipfileset dir="${mac.app}" prefix="AppleCommander.app"/> <zipfileset dir="${mac.app}" prefix="AppleCommander.app"/>
<zipfileset dir="${mac.app}" prefix="AppleCommander.app" <zipfileset dir="${mac.app}" prefix="AppleCommander.app"
includes="Contents/MacOS/JavaApplicationStub" filemode="755"/> includes="Contents/MacOS/JavaApplicationStub" filemode="755"/>
</zip> </zip>
-->
</target> </target>
<target name="sourceZip" depends="init" description="Build source ZIP archive"> <target name="sourceZip" depends="init" description="Build source ZIP archive">

Binary file not shown.

535
mac/universalJavaApplicationStub Executable file
View File

@ -0,0 +1,535 @@
#!/bin/bash
##################################################################################
# #
# universalJavaApplicationStub #
# #
# #
# A shellscript JavaApplicationStub for Java Apps on Mac OS X #
# that works with both Apple's and Oracle's plist format. #
# #
# Inspired by Ian Roberts stackoverflow answer #
# at http://stackoverflow.com/a/17546508/1128689 #
# #
# #
# @author Tobias Fischer #
# @url https://github.com/tofi86/universalJavaApplicationStub #
# @date 2017-07-28 #
# @version 2.1.0 #
# #
# #
##################################################################################
# #
# #
# The MIT License (MIT) #
# #
# Copyright (c) 2017 Tobias Fischer #
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy #
# of this software and associated documentation files (the "Software"), to deal #
# in the Software without restriction, including without limitation the rights #
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell #
# copies of the Software, and to permit persons to whom the Software is #
# furnished to do so, subject to the following conditions: #
# #
# The above copyright notice and this permission notice shall be included in all #
# copies or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR #
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, #
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE #
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER #
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, #
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE #
# SOFTWARE. #
# #
##################################################################################
#
# resolve symlinks
############################################
PRG=$0
while [ -h "$PRG" ]; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '^.*-> \(.*\)$' 2>/dev/null`
if expr "$link" : '^/' 2> /dev/null >/dev/null; then
PRG="$link"
else
PRG="`dirname "$PRG"`/$link"
fi
done
# set the directory abspath of the current shell script
PROGDIR=`dirname "$PRG"`
#
# set files and folders
############################################
# the absolute path of the app package
cd "$PROGDIR"/../../
AppPackageFolder=`pwd`
# the base path of the app package
cd ..
AppPackageRoot=`pwd`
# set Apple's Java folder
AppleJavaFolder="${AppPackageFolder}"/Contents/Resources/Java
# set Apple's Resources folder
AppleResourcesFolder="${AppPackageFolder}"/Contents/Resources
# set Oracle's Java folder
OracleJavaFolder="${AppPackageFolder}"/Contents/Java
# set Oracle's Resources folder
OracleResourcesFolder="${AppPackageFolder}"/Contents/Resources
# set path to Info.plist in bundle
InfoPlistFile="${AppPackageFolder}"/Contents/Info.plist
# set the default JVM Version to a null string
JVMVersion=""
#
# read Info.plist and extract JVM options
############################################
# read the program name from CFBundleName
CFBundleName=`/usr/libexec/PlistBuddy -c "print :CFBundleName" "${InfoPlistFile}"`
# read the icon file name
CFBundleIconFile=`/usr/libexec/PlistBuddy -c "print :CFBundleIconFile" "${InfoPlistFile}"`
# check Info.plist for Apple style Java keys -> if key :Java is present, parse in apple mode
/usr/libexec/PlistBuddy -c "print :Java" "${InfoPlistFile}" > /dev/null 2>&1
exitcode=$?
JavaKey=":Java"
# if no :Java key is present, check Info.plist for universalJavaApplication style JavaX keys -> if key :JavaX is present, parse in apple mode
if [ $exitcode -ne 0 ]; then
/usr/libexec/PlistBuddy -c "print :JavaX" "${InfoPlistFile}" > /dev/null 2>&1
exitcode=$?
JavaKey=":JavaX"
fi
# read Info.plist in Apple style if exit code returns 0 (true, :Java key is present)
if [ $exitcode -eq 0 ]; then
# set Java and Resources folder
JavaFolder="${AppleJavaFolder}"
ResourcesFolder="${AppleResourcesFolder}"
APP_PACKAGE="${AppPackageFolder}"
JAVAROOT="${AppleJavaFolder}"
USER_HOME="$HOME"
# read the Java WorkingDirectory
JVMWorkDir=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:WorkingDirectory" "${InfoPlistFile}" 2> /dev/null | xargs`
# set Working Directory based upon Plist info
if [[ ! -z ${JVMWorkDir} ]]; then
WorkingDirectory="${JVMWorkDir}"
else
# AppPackageRoot is the standard WorkingDirectory when the script is started
WorkingDirectory="${AppPackageRoot}"
fi
# expand variables $APP_PACKAGE, $JAVAROOT, $USER_HOME
WorkingDirectory=`eval "echo ${WorkingDirectory}"`
# read the MainClass name
JVMMainClass=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:MainClass" "${InfoPlistFile}" 2> /dev/null`
# read the SplashFile name
JVMSplashFile=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:SplashFile" "${InfoPlistFile}" 2> /dev/null`
# read the JVM Options
JVMOptions=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:Properties" "${InfoPlistFile}" 2> /dev/null | grep " =" | sed 's/^ */-D/g' | tr '\n' ' ' | sed 's/ */ /g' | sed 's/ = /=/g' | xargs`
# replace occurences of $APP_ROOT with its content
JVMOptions=`eval "echo ${JVMOptions}"`
# read StartOnMainThread
JVMStartOnMainThread=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:StartOnMainThread" "${InfoPlistFile}" 2> /dev/null`
if [ "${JVMStartOnMainThread}" == "true" ]; then
JVMOptions+=" -XstartOnFirstThread"
fi
# read the ClassPath in either Array or String style
JVMClassPath_RAW=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:ClassPath" "${InfoPlistFile}" 2> /dev/null`
if [[ $JVMClassPath_RAW == *Array* ]] ; then
JVMClassPath=.`/usr/libexec/PlistBuddy -c "print ${JavaKey}:ClassPath" "${InfoPlistFile}" 2> /dev/null | grep " " | sed 's/^ */:/g' | tr -d '\n' | xargs`
else
JVMClassPath=${JVMClassPath_RAW}
fi
# expand variables $APP_PACKAGE, $JAVAROOT, $USER_HOME
JVMClassPath=`eval "echo ${JVMClassPath}"`
# read the JVM Default Options in either Array or String style
JVMDefaultOptions_RAW=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:VMOptions" "${InfoPlistFile}" 2> /dev/null | xargs`
if [[ $JVMDefaultOptions_RAW == *Array* ]] ; then
JVMDefaultOptions=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:VMOptions" "${InfoPlistFile}" 2> /dev/null | grep " " | sed 's/^ */ /g' | tr -d '\n' | xargs`
else
JVMDefaultOptions=${JVMDefaultOptions_RAW}
fi
# read the JVM Arguments
JVMArguments=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:Arguments" "${InfoPlistFile}" 2> /dev/null | xargs`
# replace occurences of $APP_ROOT with its content
JVMArguments=`eval "echo ${JVMArguments}"`
# read the Java version we want to find
JVMVersion=`/usr/libexec/PlistBuddy -c "print ${JavaKey}:JVMVersion" "${InfoPlistFile}" 2> /dev/null | xargs`
# read Info.plist in Oracle style
else
# set Working Directory and Java and Resources folder
JavaFolder="${OracleJavaFolder}"
ResourcesFolder="${OracleResourcesFolder}"
WorkingDirectory="${OracleJavaFolder}"
APP_ROOT="${AppPackageFolder}"
# read the MainClass name
JVMMainClass=`/usr/libexec/PlistBuddy -c "print :JVMMainClassName" "${InfoPlistFile}" 2> /dev/null`
# read the SplashFile name
JVMSplashFile=`/usr/libexec/PlistBuddy -c "print :JVMSplashFile" "${InfoPlistFile}" 2> /dev/null`
# read the JVM Options
JVMOptions=`/usr/libexec/PlistBuddy -c "print :JVMOptions" "${InfoPlistFile}" 2> /dev/null | grep " -" | tr -d '\n' | sed 's/ */ /g' | xargs`
# replace occurences of $APP_ROOT with its content
JVMOptions=`eval "echo ${JVMOptions}"`
# read the ClassPath in either Array or String style
JVMClassPath_RAW=`/usr/libexec/PlistBuddy -c "print JVMClassPath" "${InfoPlistFile}" 2> /dev/null`
if [[ $JVMClassPath_RAW == *Array* ]] ; then
JVMClassPath=.`/usr/libexec/PlistBuddy -c "print JVMClassPath" "${InfoPlistFile}" 2> /dev/null | grep " " | sed 's/^ */:/g' | tr -d '\n' | xargs`
# expand variables $APP_PACKAGE, $JAVAROOT, $USER_HOME
JVMClassPath=`eval "echo ${JVMClassPath}"`
elif [[ ! -z ${JVMClassPath_RAW} ]] ; then
JVMClassPath=${JVMClassPath_RAW}
# expand variables $APP_PACKAGE, $JAVAROOT, $USER_HOME
JVMClassPath=`eval "echo ${JVMClassPath}"`
else
#default: fallback to OracleJavaFolder
JVMClassPath="${JavaFolder}/*"
# Do NOT expand the default App.app/Contents/Java/* classpath (#42)
fi
# read the JVM Default Options
JVMDefaultOptions=`/usr/libexec/PlistBuddy -c "print :JVMDefaultOptions" "${InfoPlistFile}" 2> /dev/null | grep -o " \-.*" | tr -d '\n' | xargs`
# read the JVM Arguments
JVMArguments=`/usr/libexec/PlistBuddy -c "print :JVMArguments" "${InfoPlistFile}" 2> /dev/null | tr -d '\n' | sed -E 's/Array \{ *(.*) *\}/\1/g' | sed 's/ */ /g' | xargs`
# replace occurences of $APP_ROOT with its content
JVMArguments=`eval "echo ${JVMArguments}"`
fi
#
# internationalized messages
#
############################################
LANG=`defaults read -g AppleLocale`
# French localization
if [[ $LANG == fr* ]] ; then
MSG_ERROR_LAUNCHING="Erreur au lancement de '${CFBundleName}'."
MSG_MISSING_MAINCLASS="'MainClass' n'est pas spécifié.\nL'application Java ne peut pas être lancée."
MSG_NO_SUITABLE_JAVA="La version de Java installée sur votre système ne convient pas.\nCe programme nécessite Java"
MSG_JAVA_VERSION_OR_LATER="ou ultérieur"
MSG_JAVA_VERSION_LATEST="(dernière mise à jour)"
MSG_NO_SUITABLE_JAVA_CHECK="Merci de bien vouloir installer la version de Java requise."
MSG_INSTALL_JAVA="Java doit être installé sur votre système.\nRendez-vous sur java.com et suivez les instructions d'installation..."
MSG_LATER="Plus tard"
MSG_VISIT_JAVA_DOT_COM="Visiter java.com"
# German localization
elif [[ $LANG == de* ]] ; then
MSG_ERROR_LAUNCHING="FEHLER beim Starten von '${CFBundleName}'."
MSG_MISSING_MAINCLASS="Die 'MainClass' ist nicht spezifiziert!\nDie Java-Anwendung kann nicht gestartet werden!"
MSG_NO_SUITABLE_JAVA="Es wurde keine passende Java-Version auf Ihrem System gefunden!\nDieses Programm benötigt Java"
MSG_JAVA_VERSION_OR_LATER="oder neuer"
MSG_JAVA_VERSION_LATEST="(neuste Unterversion)"
MSG_NO_SUITABLE_JAVA_CHECK="Stellen Sie sicher, dass die angeforderte Java-Version installiert ist."
MSG_INSTALL_JAVA="Auf Ihrem System muss die 'Java'-Software installiert sein.\nBesuchen Sie java.com für weitere Installationshinweise."
MSG_LATER="Später"
MSG_VISIT_JAVA_DOT_COM="java.com öffnen"
# English default localization
else
MSG_ERROR_LAUNCHING="ERROR launching '${CFBundleName}'."
MSG_MISSING_MAINCLASS="'MainClass' isn't specified!\nJava application cannot be started!"
MSG_NO_SUITABLE_JAVA="No suitable Java version found on your system!\nThis program requires Java"
MSG_JAVA_VERSION_OR_LATER="or later"
MSG_JAVA_VERSION_LATEST="(latest update)"
MSG_NO_SUITABLE_JAVA_CHECK="Make sure you install the required Java version."
MSG_INSTALL_JAVA="You need to have JAVA installed on your Mac!\nVisit java.com for installation instructions..."
MSG_LATER="Later"
MSG_VISIT_JAVA_DOT_COM="Visit java.com"
fi
# helper function:
# extract Java version string from `java -version` command
# works for both old (1.8) and new (9) version schema
##########################################################
function extractJavaVersionString() {
# second sed command strips " and -ea from the version string
echo `"$1" -version 2>&1 | awk '/version/{print $NF}' | sed -E 's/"//g;s/-ea//g'`
}
# helper function:
# extract Java major version from java version string
# - input '1.7.0_76' returns '7'
# - input '1.8.0_121' returns '8'
# - input '9-ea' returns '9'
# - input '9.0.3' returns '9'
##########################################################
function extractJavaMajorVersion() {
java_ver=$1
# Java 6, 7, 8 starts with 1.x
if [ ${java_ver:0:2} == "1." ] ; then
echo ${java_ver} | sed -E 's/1\.([0-9])[0-9_.]{2,6}/\1/g'
else
# Java 9+ starts with x using semver versioning
echo ${java_ver} | sed -E 's/([0-9]+)(-ea|(\.[0-9]+)*)/\1/g'
fi
}
# helper function:
# return comparable version for java version string
# basically just strip punctuation and leading '1.'
##########################################################
function comparableJavaVersionNumber() {
echo $1 | sed -E 's/^1\.//g;s/[[:punct:]]//g'
}
# function:
# Java version tester checks whether a given java version
# satisfies the given requirement
# - parameter1: the java major version (6, 7, 8, 9, etc.)
# - parameter2: the java requirement (1.6, 1.7+, etc.)
# - return: 0 (satiesfies), 1 (does not), 2 (error)
##########################################################
function JavaVersionSatisfiesRequirement() {
java_ver=$1
java_req=$2
# matches requirements with * modifier
# e.g. 1.8*, 9*, 9.1*, 9.2.4*, 10*, 10.1*, 10.1.35*
if [[ ${java_req} =~ ^[0-9]+(\.[0-9]+)*\*$ ]] ; then
# remove last char (*) from requirement string for comparison
java_req_num=${java_req::${#java_req}-1}
if [ ${java_ver} == ${java_req_num} ] ; then
return 0
else
return 1
fi
# matches requirements with + modifier
# e.g. 1.8+, 9+, 9.1+, 9.2.4+, 10+, 10.1+, 10.1.35+
elif [[ ${java_req} =~ ^[0-9]+(\.[0-9]+)*\+$ ]] ; then
java_req_num=$(comparableJavaVersionNumber ${java_req})
java_ver_num=$(comparableJavaVersionNumber ${java_ver})
if [ ${java_ver_num} -ge ${java_req_num} ] ; then
return 0
else
return 1
fi
# matches standard requirements without modifier
# e.g. 1.8, 9, 9.1, 9.2.4, 10, 10.1, 10.1.35
elif [[ ${java_req} =~ ^[0-9]+(\.[0-9]+)*$ ]] ; then
if [ ${java_ver} == ${java_req} ] ; then
return 0
else
return 1
fi
# not matching any of the above patterns
# results in an error
else
return 2
fi
}
#
# find installed Java versions
############################################
apple_jre_plugin="/Library/Java/Home/bin/java"
apple_jre_version=$(extractJavaMajorVersion $(extractJavaVersionString "${apple_jre_plugin}"))
oracle_jre_plugin="/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java"
oracle_jre_version=$(extractJavaMajorVersion $(extractJavaVersionString "${oracle_jre_plugin}"))
# first check system variable "$JAVA_HOME"
if [ -n "$JAVA_HOME" ] ; then
# PR 26: Allow specifying "$JAVA_HOME" relative to "$AppPackageFolder"
# which allows for bundling a custom version of Java inside your app!
if [[ $JAVA_HOME == /* ]] ; then
# if "$JAVA_HOME" starts with a Slash it's an absolute path
JAVACMD="$JAVA_HOME/bin/java"
else
# otherwise it's a relative path to "$AppPackageFolder"
JAVACMD="$AppPackageFolder/$JAVA_HOME/bin/java"
fi
# check for a specific Java version, specified in JVMversion Plist key
elif [ ! -z ${JVMVersion} ] ; then
# first check "/usr/libexec/java_home" symlinks
if [ -x /usr/libexec/java_home ] && /usr/libexec/java_home -F -v ${JVMVersion} > /dev/null 2>&1 ; then
JAVACMD="`/usr/libexec/java_home -F -v ${JVMVersion} 2> /dev/null`/bin/java"
JAVACMD_version=$(comparableJavaVersionNumber $(extractJavaVersionString "${JAVACMD}"))
fi
# then additionally check the Oracle JRE plugin whether it's a higher/newer compatible version
if [ -x "${oracle_jre_plugin}" ] && JavaVersionSatisfiesRequirement ${oracle_jre_version} ${JVMVersion} ; then
this_java_ver=$(comparableJavaVersionNumber $(extractJavaVersionString "${oracle_jre_plugin}"))
# use this compatible version only if the above returned empty or if the version number is higher
if [ -z ${JAVACMD} ] || [ ${this_java_ver} -ge ${JAVACMD_version} ] ; then
JAVACMD="${oracle_jre_plugin}"
JAVACMD_version=${this_java_ver}
fi
fi
# then additionally check the Apple JRE plugin whether it's a higher/newer compatible version
if [ -x "${apple_jre_plugin}" ] && JavaVersionSatisfiesRequirement ${apple_jre_version} ${JVMVersion} ; then
this_java_ver=$(comparableJavaVersionNumber $(extractJavaVersionString "${apple_jre_plugin}"))
# use this compatible version only if the above returned empty or if the version number is higher
if [ -z ${JAVACMD} ] || [ ${this_java_ver} -ge ${JAVACMD_version} ] ; then
JAVACMD="${apple_jre_plugin}"
JAVACMD_version=${this_java_ver}
fi
fi
if [ -z "$JAVACMD" ] ; then
# display human readable java version (#28)
java_version_hr=`echo ${JVMVersion} | sed -E 's/[0-9]\.([0-9+*]+)/ \1/g' | sed "s/+/ ${MSG_JAVA_VERSION_OR_LATER}/" | sed "s/*/ ${MSG_JAVA_VERSION_LATEST}/"`
# display error message with applescript
osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_NO_SUITABLE_JAVA}${java_version_hr}.\n${MSG_NO_SUITABLE_JAVA_CHECK}\" with title \"${CFBundleName}\" buttons {\" OK \", \"${MSG_VISIT_JAVA_DOT_COM}\"} default button \"${MSG_VISIT_JAVA_DOT_COM}\" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)" \
-e "set response to button returned of the result" \
-e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"http://java.com\""
# exit with error
exit 3
fi
# otherwise check "/usr/libexec/java_home" and Oracle and Apple JRE paths and use highest version available
else
# first check "/usr/libexec/java_home" symlinks
if [ -x /usr/libexec/java_home ] && /usr/libexec/java_home -F > /dev/null 2>&1 ; then
JAVACMD="`/usr/libexec/java_home 2> /dev/null`/bin/java"
JAVACMD_version=$(comparableJavaVersionNumber $(extractJavaVersionString "${JAVACMD}"))
fi
# then additionally check the Oracle JRE plugin whether it's a higher/newer compatible version
if [ -x "${oracle_jre_plugin}" ] ; then
this_java_ver=$(comparableJavaVersionNumber $(extractJavaVersionString "${oracle_jre_plugin}"))
# use this compatible version only if the above returned empty or if the version number is higher
if [ -z ${JAVACMD} ] || [ ${this_java_ver} -ge ${JAVACMD_version} ] ; then
JAVACMD="${oracle_jre_plugin}"
JAVACMD_version=${this_java_ver}
fi
fi
# then additionally check the Apple JRE plugin whether it's a higher/newer compatible version
if [ -x "${apple_jre_plugin}" ] ; then
this_java_ver=$(comparableJavaVersionNumber $(extractJavaVersionString "${apple_jre_plugin}"))
# use this compatible version only if the above returned empty or if the version number is higher
if [ -z ${JAVACMD} ] || [ ${this_java_ver} -ge ${JAVACMD_version} ] ; then
JAVACMD="${apple_jre_plugin}"
JAVACMD_version=${this_java_ver}
fi
fi
fi
# fallback fallback: /usr/bin/java
# but this would prompt to install deprecated Apple Java 6
#
# execute JAVA commandline and do some pre-checks
####################################################
# display error message if MainClassName is empty
if [ -z ${JVMMainClass} ]; then
# display error message with applescript
osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_MISSING_MAINCLASS}\" with title \"${CFBundleName}\" buttons {\" OK \"} default button 1 with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)"
# exit with error
exit 2
# check whether $JAVACMD is a file and executable
elif [ -f "$JAVACMD" ] && [ -x "$JAVACMD" ] ; then
# enable drag&drop to the dock icon
export CFProcessPath="$0"
# remove Apples ProcessSerialNumber from passthru arguments (#39)
if [[ $@ == -psn* ]] ; then
ArgsPassthru=""
else
ArgsPassthru=$@
fi
# change to Working Directory based upon Apple/Oracle Plist info
cd "${WorkingDirectory}"
# execute Java and set
# - classpath
# - dock icon
# - application name
# - JVM options
# - JVM default options
# - main class
# - JVM arguments
exec "$JAVACMD" \
-cp "${JVMClassPath}" \
-splash:"${ResourcesFolder}/${JVMSplashFile}" \
-Xdock:icon="${ResourcesFolder}/${CFBundleIconFile}" \
-Xdock:name="${CFBundleName}" \
${JVMOptions:+$JVMOptions }\
${JVMDefaultOptions:+$JVMDefaultOptions }\
${JVMMainClass}\
${JVMArguments:+ $JVMArguments}\
${ArgsPassthru:+ $ArgsPassthru}
else
# display error message with applescript
osascript -e "tell application \"System Events\" to display dialog \"${MSG_ERROR_LAUNCHING}\n\n${MSG_INSTALL_JAVA}\" with title \"${CFBundleName}\" buttons {\"${MSG_LATER}\", \"${MSG_VISIT_JAVA_DOT_COM}\"} default button \"${MSG_VISIT_JAVA_DOT_COM}\" with icon path to resource \"${CFBundleIconFile}\" in bundle (path to me)" \
-e "set response to button returned of the result" \
-e "if response is \"${MSG_VISIT_JAVA_DOT_COM}\" then open location \"http://java.com\""
# exit with error
exit 1
fi