1

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>
6
  • Arguments for a command line script are passed as a list of strings to the run handler, for example on run argv - see the osascript man page.
    – red_menace
    Apr 4, 2020 at 11:52
  • Thank you! I looked up the usage at this site. But when I replace the osascript Block with shell osascript <<-EndOfScript set arguments to "" on run argv repeat with anArg in argv set arguments to arguments & space & anArg end repeat end run display dialog "$ARGS_MSG" & arguments with title "$ERROR_TITLE" EndOfScript the dialog is not shown at all.
    – setrok
    Apr 4, 2020 at 14:01
  • The script is not compiling, since you are using more than one run handler (a run handler is implied for statements outside any other handler). Moving the set arguments and display dialog statements into the declared run handler should do it.
    – red_menace
    Apr 4, 2020 at 14:35
  • Thanks! The osascript block is compiled again and displays a dialog. But the dialog message is as short as before: displays only $ARGS_MSG.
    – setrok
    Apr 4, 2020 at 16:10
  • Your command line script needs to get its arguments from somewhere. If the Java application is getting the arguments you need, you can just have that pass them on when calling the script.
    – red_menace
    Apr 8, 2020 at 13:22

2 Answers 2

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
4
  • Thank you! And; Sorry, if I confused any reader with bad wording. No, I don‘t give any arguments. That was the problem in the first place. My goal was to make the OS give me arguments, i.e. the file names (paths) of the files openend with myJavaJar.app so I can pass them through to the jvm. MacOS doesn’t pass file names to the bash script on its own, so I tried to fish them out of the Apple Event “open” with AppleScript “on open”. Sorry if I didn’t point that out clearly enough in my question.
    – setrok
    Apr 5, 2020 at 5:02
  • The OS just passes the files to the application (calling its application:openFiles: method), Apple Events aren't involved. Some applications will also accept command line arguments to their executable. Another option would be to run your helper application first, where it does its thing with the file arguments, then run the other application, passing those same files to it.
    – red_menace
    Apr 5, 2020 at 13:38
  • I guess there is no way to have an application:openFiles: section in a bash shell, is there? ;) Well, thanks!
    – setrok
    Apr 5, 2020 at 14:43
  • The other application would utilize that or use the command line, so your script would be the one to get the files from the command line, then pass them on. You can also use a regular application bundle (with menus, icon, etc) to launch your script or perform the same things using the language of your choice (well almost). You might even be able to use an Automator workflow.
    – red_menace
    Apr 5, 2020 at 15:06
1

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
4
  • Thanks! My problem is that macOS calls the bash script without any argument. I wanted to get file names from the Open-AppleEvent so the bash script can pass them to myJarFile.jar.
    – setrok
    Apr 5, 2020 at 11:33
  • This script, like red_menace's, optionally uses command-line arguments passed into it; and if none are, then it uses whatever is contained in the $args array that is declared manually in the script. So this is taking a series of items from bash and giving them to AppleScript. But it sounds like that's not what you wanted. Can you describe where and what your implementation is (or will) with regards to the aevtodoc (open) event ?
    – CJK
    Apr 5, 2020 at 18:31
  • Actually I've just seen the comments between you and red_menace regarding the event handling, which now makes more sense. I was thrown by how your application was supposed to receive an aevtodoc, and wanted to check if you already knew it would be getting sent. But, it won't be. Perhaps putting the app bundle(s) and related program files on GitHub? That would reduce the to and fro here, and get you an indication straight away of whether or not we'll be able to help.
    – CJK
    Apr 5, 2020 at 21:44
  • No github account, sorry. I could take this as the perfect opportunity to learn svn or github and Swift. At the least I will supply the complete bash code and Info.plist as soon as I get back to my computer. And finally learn Swift, to write a replacement for the bash script.
    – setrok
    Apr 6, 2020 at 9:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .