views:

1455

answers:

2

I have an application bundle on Mac OS X 10.4 on the desktop. My application looks for a folder named "resources" in which files to be displayed are kept (kept in the same location as the runnable JAR). I know there is a folder named "Resources" within the app bundle too, sorry if thats confusing, but I never programmed on a Mac and didnt know this would be the same name.

In Windows, when I call System.getProperty("user.dir") I get the location at which the runnable JAR file is located. Exactly what I wanted.

Why then when I run an application bundle is the getProperty returning "/"? Thats all. I expected it to return something like "/Users/user_name/Desktop"...which is where my app bundle is located.

A: 

That's because "user.dir" indicates the current user directory in effect when the JVM is run; in Windows, this is often the location of the JAR unless you specify otherwise. In OSX there may well be no concept of a current dir, but more likely it just has a different default.

Though I have never specifically tested this code under OSX, you can try this to locate the directory from which any class was loaded:

static public File getClassLocation(Class cls, boolean trmjar) {
    ClassLoader                         cl;                                     // class loader
    URL                                 uo;                                     // url object
    String                              ef;                                     // external form of URL
    String                              lc;                                     // lowercase external form of URL
    File                                rf;                                     // return file

    if((cl=cls.getClassLoader())==null) { cl=ClassLoader.getSystemClassLoader(); }

    if((uo=cl.getResource(cls.getName().replace('.','/')+".class"))==null) {
        return null;
        }

    ef=uo.toExternalForm();
    lc=ef.toLowerCase();
    while(lc.startsWith("jar:") || lc.startsWith("file:/")) {
        if(lc.startsWith("jar:")) {
            if(lc.indexOf("!/")!=-1) { ef=ef.substring("jar:".length(),(ef.indexOf("!/"))); } // strip encapsulating "jar:" and "!/..." from JAR url
            else                     { ef=ef.substring("jar:".length()                   ); } // strip encapsulating "jar:"
            }
        if(lc.startsWith("file:/")) {
            ef=ef.substring("file:/".length());                                 // strip encapsulating "file:/"
            if(!ef.startsWith("/")) { ef=("/"+ef); }
            while(ef.length()>1 && ef.charAt(1)=='/') { ef=ef.substring(1); }
            }
        lc=ef.toLowerCase();
        }
    ef=TextDecode.urlString(ef);
    rf=new File(ef);
    if(lc.endsWith(".class") || (trmjar && lc.endsWith(".jar"))) { rf=rf.getParentFile(); }
    if(rf.exists()) { rf=rf.getAbsoluteFile(); }
    return rf;
    }

it's worked reliably for me for years under Windows for all versions of Java since Java 1.

Software Monkey
Thanks for the reply. How can I see in OSX where the the JVM is running from? I am not a Mac user.
Thanks for the code, I will give it a try and see if it works.
And of course there are two separate things, the location of the JVM executable (which should be of no concern), and the location of the principle JAR that it is running - the latter is what my code addresses.
Software Monkey
Yes the JVM exe is located at:System/Library/Frameworks/JavaVM.framework/Versions/CurrentNot sure if this code will apply but its a start.
+1  A: 

I instead used the system property "user.home" instead of "user.dir". This way i do not have to worry about where the JVM is looking. I have the application bundle refernce my jar file directly using a bash script as the executeable called by the info.plist file. i can always place the files to be displayed by the app on the users home because that location will always return a path.