Skip to content
This repository was archived by the owner on Feb 4, 2023. It is now read-only.

Commit f9011dd

Browse files
authored
Merge pull request #44 from tofi86/develop
version 2.1.0
2 parents b782b01 + 5c4d1d5 commit f9011dd

File tree

4 files changed

+305
-143
lines changed

4 files changed

+305
-143
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
ChangeLog
22
---------
33

4+
### v2.1.0 (2017-07-28)
5+
* Support for Java 9 which introduces a new version number schema (fixes #43)
6+
47
### v2.0.2 (2017-04-23)
58
* Bugfix: do NOT expand/evaluate the default Oracle Classpath (`App.app/Contents/Java/*`) (PR #42, Thanks to @mguessan for his contribution)
69

README.md

Lines changed: 29 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
universalJavaApplicationStub
22
=====================
33

4-
[![Join the chat at https://gitter.im/tofi86/universalJavaApplicationStub](https://badges.gitter.im/tofi86/universalJavaApplicationStub.svg)](https://gitter.im/tofi86/universalJavaApplicationStub?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4+
[![Current release](https://img.shields.io/github/release/tofi86/universalJavaApplicationStub.svg)](https://github.com/tofi86/universalJavaApplicationStub/releases) [![Join the chat at https://gitter.im/tofi86/universalJavaApplicationStub](https://badges.gitter.im/tofi86/universalJavaApplicationStub.svg)](https://gitter.im/tofi86/universalJavaApplicationStub?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
55

66
A BASH based *JavaApplicationStub* for Java Apps on Mac OS X that works with both Apple's and Oracle's plist format. It is released under the MIT License.
77

@@ -13,34 +13,34 @@ Whilst developing some Java apps for Mac OS X I was facing the problem of suppor
1313

1414
**Is there some difference, you might ask?** Yes, there is!
1515

16-
1. The spot in the file system where the JRE or JDK is stored is different:
16+
1. The installation directory differs:
1717
* Apple Java 1.5/1.6: `/System/Library/Java/JavaVirtualMachines/`
1818
* Oracle JRE 1.7/1.8: `/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/`
1919
* Oracle JDK 1.7/1.8: `/System/Library/Java/JavaVirtualMachines/`
2020

21-
2. Mac Apps built with tools designed for Apple's Java (like Apple's JarBundler or the [ANT task "Jarbundler"](http://informagen.com/JarBundler/)) won't work on Macs with Oracle Java 7 and no Apple Java installed.
22-
* This is because the Apple `JavaApplicationStub` only works for Apple's Java and their `Info.plist` style to store Java properties.
23-
* To support Oracle Java 7 you would need to built a separate App package with Oracles [ANT task "Appbundler"](https://java.net/projects/appbundler).
21+
2. Mac Apps built with tools designed for Apple's Java (like Apple's *JarBundler* or the OpenSource [ANT task "Jarbundler"](https://github.com/UltraMixer/JarBundler)) won't work on Macs with Oracle Java 7 and no Apple Java installed.
22+
* This is because Apple's `JavaApplicationStub` only works for Apple's Java and their style to store Java properties in the `Info.plist` file.
23+
* To support Oracle Java 7 you would need to built a separate App package with [Oracles ANT task "Appbundler"](https://java.net/projects/appbundler).
2424
* Thus you would need the user to know which Java distribution he has installed on his Mac. Not very user friendly...
2525

2626
3. Oracle uses a different syntax to store Java properties in the applications `Info.plist` file. A Java app packaged as a Mac app with Oracles Appbundler also needs a different `JavaApplicationStub` and therefore won't work on systems with Apple's Java...
2727

28-
4. Starting with Mac OS X 10.10 *(Yosemite)*, app packages won't open up anymore if they contain the *deprecated* Plist `Java` dictionary. This isn't confirmed by Apple, but [issue #9](https://github.com/tofi86/universalJavaApplicationStub/issues/9) leads to this assumption:
29-
* Apple seems to declare the `Java` dictionary as *deprecated* and requires the old Apple Java 6 to be installed. Otherwise the app doesn't open.
28+
4. Starting with Mac OS X 10.10 *(Yosemite)*, Java Apps won't open anymore if they contain the *deprecated* Plist dictionary `Java`. This isn't confirmed by Apple, but [issue #9](https://github.com/tofi86/universalJavaApplicationStub/issues/9) leads to this assumption:
29+
* Apple seems to declare the `Java` dictionary as *deprecated* and ties it to the old Apple Java 6. If you have a newer version installed the app won't open.
3030
* If Java 7/8 is installed, Apple doesn't accept those java versions as suitable
3131
* Apple prompts for JRE 6 download even before the `JavaApplicationStub` is executed. This is why we can't intercept at this level and need to replace the `Java` dictionary by a `JavaX` dictionary key.
3232
* This requires to use the latest [JarBundler](https://github.com/UltraMixer/JarBundler/) version (see below for more details)
3333

3434
*So why, oh why, couldn't Oracle just use the old style of storing Java properties in `Info.plist` and offer a universal JavaApplicationStub?!* :rage:
3535

36-
Well, since I can't write such a script in C, C# or whatever fancy language, I wrote it as a shell script. And it works! ;-)
36+
Well, since I can't write such a script in C, C# or whatever fancy language, I wrote it as a Shell script. And it works!
3737

3838
How the script works
3939
--------------------
4040

41-
You don't need a native `JavaApplicationStub` file anymore...
41+
You don't need a native `JavaApplicationStub` file anymore. The Shell script needs to be executable – that's all.
4242

43-
The shell script reads JVM properties from `Info.plist` regardless of which format they have, Apple or Oracle, and feeds it to a commandline `java` call:
43+
The script reads JVM properties from `Info.plist` regardless of whether it's Apple or Oracle flavour and feeds it to a commandline `java` call like the following:
4444

4545
```Bash
4646
# execute Java and set
@@ -51,33 +51,37 @@ The shell script reads JVM properties from `Info.plist` regardless of which form
5151
# - JVM default options
5252
# - main class
5353
# - JVM arguments
54-
exec "$JAVACMD" \
55-
-cp "${JVMClassPath}" \
56-
-Xdock:icon="${ResourcesFolder}/${CFBundleIconFile}" \
57-
-Xdock:name="${CFBundleName}" \
58-
${JVMOptions:+$JVMOptions }\
59-
${JVMDefaultOptions:+$JVMDefaultOptions }\
60-
${JVMMainClass}\
61-
${JVMArguments:+ $JVMArguments}
54+
exec "$JAVACMD" \
55+
-cp "${JVMClassPath}" \
56+
-splash:"${ResourcesFolder}/${JVMSplashFile}" \
57+
-Xdock:icon="${ResourcesFolder}/${CFBundleIconFile}" \
58+
-Xdock:name="${CFBundleName}" \
59+
${JVMOptions:+$JVMOptions }\
60+
${JVMDefaultOptions:+$JVMDefaultOptions }\
61+
${JVMMainClass}\
62+
${JVMArguments:+ $JVMArguments}\
63+
${ArgsPassthru:+ $ArgsPassthru}
6264
```
6365

6466
It sets the classpath, the dock icon, the *AboutMenuName* (in Xdock style) and then every *JVMOptions*, *JVMDefaultOptions* or *JVMArguments* found in the `Info.plist` file.
6567

66-
The WorkingDirectory is either retrieved from Apple's `Info.plist` key `Java/WorkingDirectory` or set to the JavaRoot directory within the app bundle.
68+
The WorkingDirectory is either retrieved from Apple's Plist key `Java/WorkingDirectory` or set to the JavaRoot directory within the app bundle.
6769

68-
The name of the *main class* is also retrieved from `Info.plist`. If no *main class* could be found, an applescript error dialog is shown and the script exits with *exit code 1*.
70+
The name of the *main class* is also retrieved from `Info.plist`. If no *main class* is found, an applescript error dialog is shown and the script exits with *exit code 1*.
6971

7072
There is some *foo* happening to determine which Java versions are installed – here's the list in which order system properties are checked:
7173

72-
1. system variable `$JAVA_HOME`
74+
1. System variable `$JAVA_HOME`
7375
* can also be set to a relative path using the [`<LSEnvironment>` Plist dictionary key](https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/LaunchServicesKeys.html#//apple_ref/doc/uid/20001431-106825)
7476
* which allows for bundling a custom version of Java inside your app!
75-
2. highest available Java version found in one of these locations:
77+
2. Highest available Java version *(Java 8 trumps 7)* found in one of these locations:
7678
* `/usr/libexec/java_home` symlinks
7779
* Oracle's JRE Plugin: `/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java`
7880
* Symlink for old Apple Java: `/Library/Java/Home/bin/java`
81+
3. If you require a specific Java version with the Plist key `JVMVersion` the script will try to find a matching JDK or JRE in all of the above locations
82+
* if multiple matching JVM's are found, the script will pick the latest (highest version number)
7983

80-
If none of these could be found or executed, an applescript error dialog is shown saying that Java need to be installed:
84+
If none of these could be found or executed the script shows an applescript error dialog saying that Java needs to be installed:
8185

8286
![Error Dialog No Java Found](/docs/java-error.png?raw=true)
8387

@@ -90,7 +94,7 @@ Use whichever ANT task you like:
9094
* the opensource ["JarBundler"](https://github.com/UltraMixer/JarBundler) *(recommended)*
9195
* or my [JarBundler fork](https://github.com/tofi86/Jarbundler) *(deprecated)*
9296
* _both support the newly introduced and recommended `JavaX` dict key_
93-
* Oracle's opensource ["Appbundler"](https://java.net/projects/appbundler)
97+
* Oracle's opensource ["Appbundler"](https://java.net/projects/appbundler) *(seems to be dead)*
9498
* or [*infinitekind*'s fork](https://bitbucket.org/infinitekind/appbundler/overview)
9599

96100
### JarBundler (≥ v3.3) example
@@ -101,7 +105,7 @@ Download the latest JarBundler release [from its github repo](https://github.com
101105
>
102106
> If you don't want to care about compatibility issues between OS X and Java versions, make sure to use the [latest JarBundler version ≥ 3.3](https://github.com/UltraMixer/JarBundler/releases)
103107
104-
Then place the `universalJavaApplicationStub` from this repo in your build resources folder and link it in your ANT task (attribute `stubfile`). Don't forget to set the newly introduced `useJavaXKey` option:
108+
Then place the `universalJavaApplicationStub` from this repo in your build resources folder and link it in your ANT task (attribute `stubfile`). Don't forget to set the newly introduced `useJavaXKey` option for compatibility:
105109
```XML
106110
<jarbundler
107111
name="Your-App"
@@ -110,7 +114,6 @@ Then place the `universalJavaApplicationStub` from this repo in your build resou
110114
stubfile="${resources.dir}/universalJavaApplicationStub"
111115
useJavaXKey="true"
112116
... >
113-
114117
</jarbundler>
115118
```
116119

@@ -128,7 +131,6 @@ Just place the `universalJavaApplicationStub` from this repo in your build resou
128131
icon="${resources.dir}/icon.icns"
129132
executableName="${resources.dir}/universalJavaApplicationStub"
130133
... >
131-
132134
</appbundler>
133135
```
134136

src/universalJavaApplicationStub

Lines changed: 51 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
# #
1414
# @author Tobias Fischer #
1515
# @url https://github.com/tofi86/universalJavaApplicationStub #
16-
# @date 2017-11-27 #
17-
# @version 2.0.2 #
16+
# @date 2017-07-28 #
17+
# @version 2.1.0 #
1818
# #
1919
# #
2020
##################################################################################
2121
# #
2222
# #
2323
# The MIT License (MIT) #
2424
# #
25-
# Copyright (c) 2016 Tobias Fischer #
25+
# Copyright (c) 2017 Tobias Fischer #
2626
# #
2727
# Permission is hereby granted, free of charge, to any person obtaining a copy #
2828
# of this software and associated documentation files (the "Software"), to deal #
@@ -289,58 +289,69 @@ fi
289289

290290

291291

292-
# helper
293-
# function: extract Java version string
294-
# from java -version command
295-
############################################
296-
292+
# helper function:
293+
# extract Java version string from `java -version` command
294+
# works for both old (1.8) and new (9) version schema
295+
##########################################################
297296
function extractJavaVersionString() {
298-
echo `"$1" -version 2>&1 | awk '/version/{print $NF}' | sed -E 's/"//g'`
297+
# second sed command strips " and -ea from the version string
298+
echo `"$1" -version 2>&1 | awk '/version/{print $NF}' | sed -E 's/"//g;s/-ea//g'`
299299
}
300300

301-
# helper
302-
# function: extract Java major version
303-
# from java version string
304-
############################################
305301

302+
# helper function:
303+
# extract Java major version from java version string
304+
# - input '1.7.0_76' returns '7'
305+
# - input '1.8.0_121' returns '8'
306+
# - input '9-ea' returns '9'
307+
# - input '9.0.3' returns '9'
308+
##########################################################
306309
function extractJavaMajorVersion() {
307-
version_str=$(extractJavaVersionString "$1")
308-
echo ${version_str} | sed -E 's/([0-9.]{3})[0-9_.]{5,6}/\1/g'
310+
java_ver=$1
311+
# Java 6, 7, 8 starts with 1.x
312+
if [ ${java_ver:0:2} == "1." ] ; then
313+
echo ${java_ver} | sed -E 's/1\.([0-9])[0-9_.]{2,6}/\1/g'
314+
else
315+
# Java 9+ starts with x using semver versioning
316+
echo ${java_ver} | sed -E 's/([0-9]+)(-ea|(\.[0-9]+)*)/\1/g'
317+
fi
309318
}
310319

311-
# helper
312-
# function: generate comparable Java version
313-
# number from java version string
314-
############################################
315320

321+
# helper function:
322+
# return comparable version for java version string
323+
# basically just strip punctuation and leading '1.'
324+
##########################################################
316325
function comparableJavaVersionNumber() {
317-
echo $1 | sed -E 's/[[:punct:]]//g'
326+
echo $1 | sed -E 's/^1\.//g;s/[[:punct:]]//g'
318327
}
319328

320329

321-
322-
#
323-
# function: Java version tester
324-
# check whether a given java version
325-
# satisfies the given requirement
326-
############################################
327-
330+
# function:
331+
# Java version tester checks whether a given java version
332+
# satisfies the given requirement
333+
# - parameter1: the java major version (6, 7, 8, 9, etc.)
334+
# - parameter2: the java requirement (1.6, 1.7+, etc.)
335+
# - return: 0 (satiesfies), 1 (does not), 2 (error)
336+
##########################################################
328337
function JavaVersionSatisfiesRequirement() {
329338
java_ver=$1
330339
java_req=$2
331340

332-
# e.g. 1.8*
333-
if [[ ${java_req} =~ ^[0-9]\.[0-9]\*$ ]] ; then
334-
java_req_num=${java_req:0:3}
335-
java_ver_num=${java_ver:0:3}
336-
if [ ${java_ver_num} == ${java_req_num} ] ; then
341+
# matches requirements with * modifier
342+
# e.g. 1.8*, 9*, 9.1*, 9.2.4*, 10*, 10.1*, 10.1.35*
343+
if [[ ${java_req} =~ ^[0-9]+(\.[0-9]+)*\*$ ]] ; then
344+
# remove last char (*) from requirement string for comparison
345+
java_req_num=${java_req::${#java_req}-1}
346+
if [ ${java_ver} == ${java_req_num} ] ; then
337347
return 0
338348
else
339349
return 1
340350
fi
341351

342-
# e.g. 1.8+
343-
elif [[ ${java_req} =~ ^[0-9]\.[0-9]\+$ ]] ; then
352+
# matches requirements with + modifier
353+
# e.g. 1.8+, 9+, 9.1+, 9.2.4+, 10+, 10.1+, 10.1.35+
354+
elif [[ ${java_req} =~ ^[0-9]+(\.[0-9]+)*\+$ ]] ; then
344355
java_req_num=$(comparableJavaVersionNumber ${java_req})
345356
java_ver_num=$(comparableJavaVersionNumber ${java_ver})
346357
if [ ${java_ver_num} -ge ${java_req_num} ] ; then
@@ -349,15 +360,17 @@ function JavaVersionSatisfiesRequirement() {
349360
return 1
350361
fi
351362

352-
# e.g. 1.8
353-
elif [[ ${java_req} =~ ^[0-9]\.[0-9]$ ]] ; then
363+
# matches standard requirements without modifier
364+
# e.g. 1.8, 9, 9.1, 9.2.4, 10, 10.1, 10.1.35
365+
elif [[ ${java_req} =~ ^[0-9]+(\.[0-9]+)*$ ]] ; then
354366
if [ ${java_ver} == ${java_req} ] ; then
355367
return 0
356368
else
357369
return 1
358370
fi
359371

360372
# not matching any of the above patterns
373+
# results in an error
361374
else
362375
return 2
363376
fi
@@ -370,9 +383,9 @@ function JavaVersionSatisfiesRequirement() {
370383
############################################
371384

372385
apple_jre_plugin="/Library/Java/Home/bin/java"
373-
apple_jre_version=`extractJavaMajorVersion "${apple_jre_plugin}"`
386+
apple_jre_version=$(extractJavaMajorVersion $(extractJavaVersionString "${apple_jre_plugin}"))
374387
oracle_jre_plugin="/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/bin/java"
375-
oracle_jre_version=`extractJavaMajorVersion "${oracle_jre_plugin}"`
388+
oracle_jre_version=$(extractJavaMajorVersion $(extractJavaVersionString "${oracle_jre_plugin}"))
376389

377390
# first check system variable "$JAVA_HOME"
378391
if [ -n "$JAVA_HOME" ] ; then

0 commit comments

Comments
 (0)