Opening documents with their default application

When developing Java, 99% of all tasks can be solved in a platform independent manor right out of the box. But then there is that last tiny bit of tasks, that is inherently platform specific, as it has to deal with the weirdness of the host-OS.

For the Pentaho Report-Designer, we support the three major desktop platforms – Linux, Windows and Mac OS. When ever we generate a document (be it when we preview the report or when we do a actual report-run), we have to show the user the newly generated document. The cheesy way of doing this is to assume a reasonable set of default applications. For PDF, we would for instance default to launching the “Acrobat Reader”. “Hey, I dont use closed-source applications from monopolistic vendors on my machine!” you may scream out in terror. And yes, assuming a set of “standard” applications when there is no standard is not a good thing.

Luckily, there is hope. Each operating system has a magic way of launching the “right” application for a given document. Of course, its not documented at all. So calling on numerous years of messing around with operating systems, here’s my cook-book for opening documents.

1. Linux (and also Solaris)

On most modern distributions, the mapping between mime-types and corresponding applications happens based on the rules expressed in a file called /etc/mailcap(5). The command-line utility run-mailcap(8) reads the mailcap file and automatically launches the right application for the given file. So running the default application is easy:

run-mailcap 

or in Java:

Runtime.getRuntime().exec(new String[]{"run-mailcap", pathToYourFileAsString });

2. Windows

On Windows, file associations are stored in the registry. The registry is a binary file, so parsing that one is no fun. Of course, its also available via native C functions, but shipping platform dependent libraries is so 1995! Luckily, Microsoft drives a course of “never delete a documented function” and thus, the old tricks from Windows 95 still work on all recent Windows versions. Back in the old days, the most powerful toy to mess around with a system was the “rundll32” utility. This utility can be used to invoke functions from a library (dll-file), without having to write a C-programm (I’d rather read out Perl-regular expressions in the public than to go back to C again).

The Shell32.dll contains a nice function to run the default application called “ShellExec_RunDLL”. So let’s abuse that.

rundll32.exe "SHELL32.DLL,ShellExec_RunDLL" 

3. Mac OSX

MacOS is a weird thing. Applications are stored in bundles, well, directories with a lot of binary gibberish to know what entry in there is executable. Its equally inaccessible as the Windows Registry and the Apple Developer Connection is a great place to never find anything (who would have guessed that the entry called “CFBundle” describes the application directory structure). The File-open dialog of course, treats these application bundles as if they where files, but sadly no one told the Unix-shell that these things are executable.

So we have to find magic again, this time by using the open(1) command to parse whatever makes a bundle so special and then to execute the correct native application inside the bundle.

If you just want to open the file with the default application, use

open 

If you know the application bundle and want to open the file with that specific application, you cant do that directly. Again you have to use the open(1) command, but this time with a extra parameter:

open -a  

This entry was posted in Development on by .
Thomas

About Thomas

After working as all-hands guy and lead developer on Pentaho Reporting for over an decade, I have learned a thing or two about report generation, layouting and general BI practices. I have witnessed the remarkable growth of Pentaho Reporting from a small niche product to a enterprise class Business Intelligence product. This blog documents my own perspective on Pentaho Reporting's development process and our our steps towards upcoming releases.