Bundled app launcher changes

Greg Brown greg.x.brown at oracle.com
Fri Feb 10 14:28:35 PST 2012

> But bundle Info.plist and this can be heavily customized. Make sense to support that (e.g. like jar task supports customizing manifest)

Can you provide some examples of what you might want to customize in a Java app bundle's Info.plist? The Java app itself can't access that information, so I'm wondering why you'd want to do this.

>>> Questions:
>>>   a) How one specify set of jars?
>> Use one or more nested<classpath>  fileset elements.
>>>   b) What if application expects jars/resources to be in the multiple folders?
>> You can use multiple<classpath>  elements.
> Would you mind to give an example of this?
> E.g. NB typically generate something like
>   dist/app.jar
>   dist/lib/dep-lib1.jar
>   dist/lib/dep-lib2.jar

<classpath dir="dist" includes="*.jar"/>
<classpath dir="dist/lib" includes="*.jar"/>

> How do i package it to preserve structure?

That isn't currently supported. Why might you want to do that?

>>>   c) How do i specify data or other resource files to be included?
>> Include them on your classpath (e.g. in your class directory or JAR files), as you would with any other Java application.
> Do you mean i can include folder to the classpath and then all subdirectories will be copied over to the bundle?


> I am not sure how this classpath element work.

It's just a regular Ant FileSet.

> In your example you are using absolute path - do you mean user will not be able to install same app to other location (e.g. to Library in the home dir?)?
>>   <classpath file="/Library/Java/Demos/JFC/SwingSet2/SwingSet2.jar"/>

This has nothing to do with where the application is installed - only where the source JAR is located. Everything gets packaged into the app bundle, which can be installed anywhere on the user's system.

> Also, with this approach the app running in the dev environment will be different from app running from the bundle.
> E.g. you have to set classpath again.

Yes. But this is no different from the existing JarBundler tool provided with OS X or the open-source JarBundler Ant task that serves a similar purpose:


> Can you elaborate a bit why do we want to set classpath at the package time?

Because we need to know which JARs/class files need to be added to the app bundle.

>>>   d) How do i add native libs?
>> It isn't shown in this example, but the task also supports a nested<nativeLibrary>  element that you can use for this purpose.
> Any other examples to look at?

Not yet.

>>>   e) Can i add custom frameworks, etc?
>> Not at present.
> IMHO, thinks like Sparkle, etc. are relatively popular.
> Would be good to support them.

It may make sense to add support for add support for custom plugins.

>>>   f) Why we refer to Java Runtime?
>>>         runtime="${env.JAVA_HOME}/../.."
>>>      IMHO, we could assume people install JDK and should point to JDK bundle root as root for cobundle.
>> In order to comply with Apple's licensing policy for app store redistribution, we need to support an embedded JRE. If you do not specify a JRE, the launcher will look for a locally-installed shared runtime.
> I understand why we cobundle JRE. I do not understand why we expect developer to provide reference to it in this way.

How would you expect developers to reference it?

> My understanding is that JRE to cobundle will always be in the
>   jdk.bundle/MacOS/Contents/Home/jre

I'm not sure that is a reasonable assumption. Why not allow the developer to choose?

> Based on your example it seem that developer need to point to "jdk.bundle/MacOS/Contents/Home" and this exposes internals of jdk bundle.

No, the developer just needs to point at the top-level bundle directory (e.g. /Library/Java/JavaVirtualMachines/1.7.0.jre).

>>>  g) Any way to specify minimum platform requirements (even dmg has it)?
>> Which platform? Java, OS X, or both?
> OS X version.
> E.g. need 10.7.3, etc.

I see. We could add attributes for this to the Ant task.

>>> Specifically i am thinking it will be useful to have
>>>   a) some kind of "resource" element that could include arbitrary set of filesets
>>>       And resources could be of different types (e.g. jars, native, frameworks, icon, "custom", etc)
>> Fundamentally, this is a tool for packaging Java apps, so I'm not sure what the value would be in supporting non-Java resources. All of your Java resources just need to be on your classpath.
> I do not follow here.
> ...
> Assuming everything is on classpath is not realistic, IMHO.

OK, sure. But if your app needs access to something outside of the class path, you can still use standard Java APIs to get to it (e.g. java.io.File). There are no standard Java APIs for accessing the contents of a Mac app bundle, so (IMO) there's not much point in supporting bundle-specific customizations.

>>>   b) application descriptor - most of what you have on bundledapp right now
>>>         (but not java runtime location, dest file, etc.)
>> Can you elaborate on this? I'm not sure what you mean.
> Ok, here is tentative example
>   <bundleapp outputdirectory="." name="SwingSet2">
>      <!-- Application properties. This is effectively plist. May be wise to support reference to predefined plist in the file -->
>      <properties
>        displayname="SwingSet 2"
>        identifier="com.oracle.javax.swing.SwingSet2"
>        shortversion="1.0"
>        >
>        <!-- custom plist property, see "/usr/libexec/PlistBuddy -h" -->
>        <property name=":SUFeedURL" value="http://somewhere/sparkle-appcast.xml"/>
>        <property name=":CFBundleDocumentTypes:2:CFBundleTypeExtensions" value="aaa"/>
>      </properties>
>       <javaruntime sdk="path/to/jdk.bundle">
>        <option value="-Xms32M"/>
>        <option value="-Xmx256M"/>
>        <option value="-Dapple.laf.useScreenMenuBar=true"/>
>      </javaruntime>
>      <!-- Expect that SwingSet2.jar has classpath element pointing to other dependent jars -->
>      <application main="SwingSet2.jar">
>        <argument value="foo=bar"/>
>      </application>
>      <resources>  <!-- default type are "app" resources -->
>         <!-- includes both jar and native libs -->
>         <!-- e.g. we could have SwingSet.jar, lib/one.jar, lib/two.jar, docs/README.html, lib/macosx/something-native.dylib -->
>         <fileset basedir="${dist.dir}" includes="**"/>
>      </resources>
>      <resources type="framework">
>         <fileset basedir="Sparkle.src" includes="**"/>
>      </resources>
>      <resource type="icon">  <!-- if present then copied and used as bundle icon -->
>         <fileset .../>
>      </resource>
>   </bundleapp>

This just seems like a more verbose way of representing the same information. What would be the advantage of restructuring it this way?

The current task properties are designed to map basically 1:1 to the java command-line executable arguments. The generated app bundle is simply a more "Mac-friendly" way of launching a standard Java app. From the command line:

Usage: java [-options] class [args...]

In the Ant task, [-options] are specified using <option> elements, "class" is specified via the "mainclassname" attribute, and [args…] are specified via <argument> elements. So it's pretty obvious how they map to their command-line equivalents:

   <bundleapp outputdirectory="." 
       displayname="SwingSet 2"
       <classpath file="/Library/Java/Demos/JFC/SwingSet2/SwingSet2.jar"/>
       <option value="-Xms32M"/>
       <option value="-Xmx256M"/>
       <option value="-Dapple.laf.useScreenMenuBar=true"/>
       <argument value="foo=bar"/>

The class path and native library path are handled separately because we need to know which files to embed in the app bundle. However, <classpath> corresponds directly to -Djava.class.path, and <nativeLibrary> corresponds directly to -Djava.library.path; again, pretty obvious. All of the other attributes are simply used to configure various aspects of the generated bundle. 

So, you should be able to use the existing task to package nearly any Java application that you can run from the command line as a Mac app bundle. If your app has more complex installation requirements than the Ant task can address, then it may not be the right tool for you. It should, however, allow a typical developer to easily package a Java app for redistribution via the Mac app store or otherwise.


More information about the macosx-port-dev mailing list