Can I handle the Apple Event "open" within a bash shell script using osascript command?
I use a bash script (myJavaBash.sh) within an Application Bundle (myJavaJar.app), that starts "java -jar myJarFile.jar" with additional JVM arguments (which works fine so far). My goal is to pass a file name as argument to the application, too, whenever the user opens a file via "open with ... myJavaJar.app".
Edit: to clarify: I do not pass arguments to the bash script. I want the bash script to get filenames from wherever it can so it can pass the first of them to myJarFile.jar.
I tried to implement OpenFilesHandler in the java application and to copy an AppleScript-scpt-file into the bundle that calls myJavaBash.sh without success.
Last thing I tried just for the sake of testing every possibility was to call osascript within the bash
#!/bin/bash
#test: set command line args
MY_TITLE="Launching myJavaJarApp"
ARGS_MSG="command line args: "
osascript <<-EndOfScript
set arguments to ""
on open theFiles
repeat with anItem in theFiles
set arguments to arguments & space & (quoted form of POSIX path of anItem)
end repeat
end open
display dialog "$ARGS_MSG" & arguments with title "$MY_TITLE"
EndOfScript
Did not work out, the dialog just states $ARGS_MSG an no arguments, when I open a file with the myJavaJar.app.
Seems to me that setting the bash-script as CFBundleExecutable "consumes" all AppleEvents.
Or is there a way?
Edit: This is the complete bash script. I got the first version from Sri Harsha Chilakapati's YouTube video "Bundling Java JAR files into Mac Applications" and edited it so it finds out the installed Java versions and chooses the most fitting. It also starts the JVM with additional parameters if Java version is > 1.8 to bind JAXB classes.
#!/bin/bash
# Constants
JAVA_MAJOR=1
# treat Java 1.8 other than Java 9
JAVA_MINOR=8
JAVA_MINOR_A=9
# Java higher than 10.x doesn't have java.xml.bind any more
JAVA_MAJOR_MAX=10
java_supported_versions=(1.8 9 10)
LIB_EXEC="/usr/libexec/java_home -v"
APP_JAR="myJarFile.jar"
APP_NAME="Setrok's Java Application"
APP_ICNS="myIcons.icns"
# different arguments for Java 1.8 than 1.9
VM_ARGS=""
VM_ARGS_A="--add-modules=java.xml.bind"
# Set the working directory
DIR=$(cd "$(dirname "$0")"; pwd)
#test: set command line args
MY_ARGS="$1"
ARGS_MSG="command line: $MY_ARGS"
osascript <<-EndOfScript
set arguments to ""
on open theFiles
repeat with anItem in theFiles
set arguments to arguments & space & (quoted form of POSIX path of anItem)
end repeat
end open
display dialog "$ARGS_MSG" & arguments & "$MY_ARGS" with title "$ERROR_TITLE"
EndOfScript
#end test
# Error message for NO JAVA dialog
ERROR_TITLE="Cannot launch $APP_NAME"
ERROR_MSG="$APP_NAME requires Java version $JAVA_MAJOR.$JAVA_MINOR up to $JAVA_MAJOR_MAX to run."
DOWNLOAD_URL="https://www.oracle.com/java/technologies/javase-jre8-downloads.html"
# Is Java installed?
if type -p java; then
_java="java"
elif [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then
_java="$JAVA_HOME/bin/java"
else
osascript \
-e "set question to display dialog \"$ERROR_MSG\" with title \"$ERROR_TITLE\" buttons {\"Cancel\", \"Download\"} default button 2" \
-e "if button returned of question is equal to \"Download\" then open location \"$DOWNLOAD_URL\""
echo "$ERROR_TITLE"
echo "$ERROR_MSG"
exit 1
fi
# Java version check
if [[ "$_java" ]]; then
version=$("$_java" -version 2>&1 | awk -F '"' '/version/ {print $2}')
# Is version too high or too low?
# Are there other (supported) java versions installed?
if [[ "$version" < "$JAVA_MAJOR.$JAVA_MINOR" ]] || [[ "$version" > "$JAVA_MAJOR_MAX" ]]; then
for i in "${java_supported_versions[@]}";
do
java_other=$($LIB_EXEC "$i")
_java="$java_other/bin/java"
version=$("$_java" -version 2>&1 | awk -F '"' '/version/ {print $2}')
if [[ "$version" < "$JAVA_MAJOR.$JAVA_MINOR" ]] || [[ "$version" > "$JAVA_MAJOR_MAX" ]]; then
echo "Java Version does not match: $i"
else
break
fi
done
fi
ur_version="Your Java version is $version!"
# Is version still too high or too low?
if [[ "$version" < "$JAVA_MAJOR.$JAVA_MINOR" ]] || [[ "$version" > "$JAVA_MAJOR_MAX" ]]; then
osascript \
-e "set question to display dialog \"$ERROR_MSG $ur_version\" with title \"$ERROR_TITLE\" buttons {\"Cancel\", \"Download\"} default button 2" \
-e "if button returned of question is equal to \"Download\" then open location \"$DOWNLOAD_URL\""
echo "$ERROR_TITLE"
echo "$ERROR_MSG"
echo "$ur_version"
exit 1
fi
fi
# Run the application -cp ".;$DIR;" -cp ".;$DIR;"
if [[ "$version" < "$JAVA_MAJOR.$JAVA_MINOR_A" ]]; then
exec $_java $VM_ARGS -Dapple.laf.useScreenMenuBar=true -Dcom.apple.macos.use-file-dialog-packages=true -Xdock:name="$APP_NAME" -Xdock:icon="$DIR/../Resources/$APP_ICNS" -jar "$DIR/$APP_JAR"
else
exec $_java $VM_ARGS_A -Dapple.laf.useScreenMenuBar=true -Dcom.apple.macos.use-file-dialog-packages=true -Xdock:name="$APP_NAME" -Xdock:icon="$DIR/../Resources/$APP_ICNS" -jar "$DIR/$APP_JAR"
fi
Edit: I forgot to give the Info.plist:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>German</string>
<key>CFBundleDisplayName</key>
<string>Setrok's Java Application</string>
<key>CFBundleIdentifier</key>
<string>eu.gronos.myJavaJar</string>
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeExtensions</key>
<array>
<string>skktx</string>
</array>
<key>CFBundleTypeIconFile</key>
<string>myIcons.icns</string>
<key>CFBundleTypeName</key>
<string>myJavaJar calculation</string>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
<key>LSHandlerRank</key>
<string>Owner</string>
</dict>
</array>
<key>CFBundleExecutable</key>
<string>myJavaBash.sh</string>
<key>CFBundleIconFile</key>
<string>myIcons.icns</string>
<key>CFBundleGetInfoString</key>
<string>Setrok's Java Application (C) 2014-2020 (GPL)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.6.0</string>
<key>CFBundleSignature</key>
<string>xmmd</string>
<key>CFBundleVersion</key>
<string>0.6.0</string>
<key>NSAppleScriptEnabled</key>
<string>YES</string>
<key>NSHumanReadableCopyright</key>
<string>Setrok's Java Application (C) 2014-2020 (GPL)</string>
</dict>
</plist>
Solution 1:
Arguments for a stand-alone osascript
are passed as a list of strings to the AppleScript run
handler, for example on run argv
- see the osascript man page. If you are using osascript
inside another script, you can just use the arguments you already have - expanding variables in a heredoc, for example.
The following example will use arguments from the command line, or if none, from an array defined in the shell script. The arguments are separated by a newline, which is used by the AppleScript to get the list:
#!/bin/bash
dialog_title="Command Line Argument Test"
dialog_header="Arguments:"
args=(
argument1
argument2
"argument with spaces"
argumentN
)
osascript <<-SCRIPT
if "$@" is "" then -- use args array
set arg_list to "$(printf '%s\n' "${args[@]}")"
else -- use cli arguments
set arg_list to "$(printf '%s\n' "$@")"
end if
set arguments to ""
repeat with anArg in paragraphs of arg_list
set arguments to arguments & return & tab & anArg
end repeat
display dialog "$dialog_header" & arguments with title "$dialog_title"
SCRIPT
Solution 2:
red_menace gave a hint about sending commandline arguments into osascript
to be received by the AppleScript run
handler, but given that he didn't show how this would be done, I thought it might be helpful to demonstrate this method, especially as it's by far the simplest.
The beginning of the script is going to look identical to red_menace's, and indeed they produce identical results. But the key difference is where the call to osascript
is made:
#!/usr/bin/env bash
dialog_title="Command Line Argument Test"
dialog_header="Arguments:"
args=(arg1 arg2 "argument the third (avec une espace)" argN)
osascript - "${@:-${args[@]}}" <<OSA
prop text item delimiters : "\n\t"
on run args
display dialog {"$dialog_header", args} as text with title "$dialog_title"
end
OSA