Requiring a minimum version of OS X for your Java application

There was a recent blog post Apple Bug Friday: Minimum Application Version where Dan Wood complained about Apple's code to check that an application was being run on a suitable version of Mac OS. Chris Campbell responded in Requiring a minimum version of OS X for your application by supplying an executable that would perform the check, present a better dialog on failure than Apple's one, and call your actual executable on success.

I write Java applications, mostly, so I don't really care all that much about the OS version. I'm usually more interested in the Java VM version. Plus I don't want the hassle of more native code. I'd rather have a script.

At the moment, my requirement is Java 5 which in turn means Mac OS 10.4, so I wrote a little Ruby script to make those checks and prompt the user to upgrade appropriately. At the time of writing, Apple hasn't released a Java 5 VM that makes itself the default, so the calling script is expected to work around that by putting /System/Library/Frameworks/JavaVM.framework/Versions/1.5.0/Commands/ at the head of $PATH.

I had to learn a little AppleScript to present the error because Mac OS doesn't have an equivalent of zenity(1) yet. In particular, Jon Gruber's BBEdit and TextWrangler CSS Syntax Checker 1.0.1 showed how to display the best error dialog possible on Mac OS 10.4 (where it looks exactly how you'd expect from a Cocoa program) but fall back to a crude approximation on earlier versions. Someone who knew enough AppleScript (if it weren't for Jon Gruber, I wouldn't believe anyone actually still used it) could probably knock up a decent imitation of zenity(1) for Mac OS. (I'll get round to it myself if I ever come across a useful enough script that uses it.)

Anyway, the idea with this script is that it displays an error dialog if necessary, and reports via its exit status whether you should carry on and try to launch. This is quite convenient in conjunction with && in your launch script. (And probably not much use to you if you're a JarBundler user.)

Anyway, no screenshots on my blog. Just code:

#!/usr/bin/ruby -w

# Reports (via its status code on exit) whether we're running on a suitable
# Mac OS installation.

# Usage: ensure-suitable-mac-os-version.rb && program-requiring-10.4-with-Java-5.0

# FIXME: we should take the required Mac OS and Java versions as parameters.
# FIXME: we should be clever enough to offer to open Software Update if you
# only need to go up a minor revision.

def informational_alert(title, message)
# The whole point of this script is to cope with old software, and
# "display alert" is only available on 10.4.
# Before then we need "display dialog".
has_display_alert = `osascript -e 'property AS_VERSION_1_10 : 17826208' -e '((system attribute \"ascv\") >= AS_VERSION_1_10)'`.chomp() == "true"
if has_display_alert
display_command = "display alert \"#{title}\" message \"#{message}\" as informational"
display_command = "display dialog \"#{title}\" & return & return & \"#{message}\" buttons { \"OK\" } default button 1 with icon note"
system("osascript -e 'tell application \"Finder\"' -e 'activate' -e '#{display_command}' -e 'end tell' > /dev/null")

# Do we have a good enough version of Mac OS?
actual_mac_os_version = `sw_vers -productVersion`.chomp()
if actual_mac_os_version.match(/^10\.[4-9]/) == nil
informational_alert("This application requires a newer version of Mac OS X.", "This application requires Mac OS 10.4, but you have Mac OS #{actual_mac_os_version}.\n\nPlease upgrade.")

# Do we have a good enough version of Java?
actual_java_version = `java -fullversion 2>&1`.chomp()
actual_java_version.match(/java full version "(.*)"/)
actual_java_version = $1
if actual_java_version.match(/^1\.[5-9]\.0/) == nil
informational_alert("This application requires a newer version of Java.", "This application requires Java 5, but you have Java #{actual_java_version} for Mac OS #{actual_mac_os_version}.\n\nPlease upgrade.")

# Everything's cool.

You'll have to excuse the long lines because Blogger's been broken for a year now when it comes to handling backslash. I'd like to use backslashes for line continuation in pre-formatted text because I've no desire to manually break lines. That's a sure-fire way to introduce errors. No matter how you write the backslashes, Blogger still thinks they're its to mangle. I reported the bug, but they don't care.

"Do no evil"? "Do nothing", more like.

As usual, the latest version of the script will be in the salma-hayek library linked to somewhere on this page.