diff --git a/installer/launch4j/LICENSE.txt b/installer/launch4j/LICENSE.txt
index bf03c83..38af528 100644
--- a/installer/launch4j/LICENSE.txt
+++ b/installer/launch4j/LICENSE.txt
@@ -1,7 +1,7 @@
Launch4j (http://launch4j.sourceforge.net/)
Cross-platform Java application wrapper for creating Windows native executables.
-Copyright (c) 2004, 2015 Grzegorz Kowal
+Copyright (c) 2004, 2017 Grzegorz Kowal
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
diff --git a/installer/launch4j/demo/ConsoleApp/ConsoleApp.exe b/installer/launch4j/demo/ConsoleApp/ConsoleApp.exe
index ad6cb45..c6ef711 100644
Binary files a/installer/launch4j/demo/ConsoleApp/ConsoleApp.exe and b/installer/launch4j/demo/ConsoleApp/ConsoleApp.exe differ
diff --git a/installer/launch4j/demo/ConsoleApp/ConsoleApp.jar b/installer/launch4j/demo/ConsoleApp/ConsoleApp.jar
index 4ce267d..e10435c 100644
Binary files a/installer/launch4j/demo/ConsoleApp/ConsoleApp.jar and b/installer/launch4j/demo/ConsoleApp/ConsoleApp.jar differ
diff --git a/installer/launch4j/demo/ConsoleApp/build.xml b/installer/launch4j/demo/ConsoleApp/build.xml
index 78be0ae..b53d77f 100644
--- a/installer/launch4j/demo/ConsoleApp/build.xml
+++ b/installer/launch4j/demo/ConsoleApp/build.xml
@@ -42,7 +42,7 @@
-
+
diff --git a/installer/launch4j/demo/SimpleApp/SimpleApp.exe b/installer/launch4j/demo/SimpleApp/SimpleApp.exe
index 8b8e67e..8af3f35 100644
Binary files a/installer/launch4j/demo/SimpleApp/SimpleApp.exe and b/installer/launch4j/demo/SimpleApp/SimpleApp.exe differ
diff --git a/installer/launch4j/demo/SimpleApp/SimpleApp.jar b/installer/launch4j/demo/SimpleApp/SimpleApp.jar
index 777fece..aca3235 100644
Binary files a/installer/launch4j/demo/SimpleApp/SimpleApp.jar and b/installer/launch4j/demo/SimpleApp/SimpleApp.jar differ
diff --git a/installer/launch4j/demo/SimpleApp/l4j/SimpleApp.xml b/installer/launch4j/demo/SimpleApp/l4j/SimpleApp.xml
index bb5804d..eacd757 100644
--- a/installer/launch4j/demo/SimpleApp/l4j/SimpleApp.xml
+++ b/installer/launch4j/demo/SimpleApp/l4j/SimpleApp.xml
@@ -1,6 +1,7 @@
gui
- ../SimpleApp.jar
+ SimpleApp.jar
+ true
../SimpleApp.exe
SimpleApp
.
diff --git a/installer/launch4j/head/head.o b/installer/launch4j/head/head.o
index d5d63d6..849299f 100644
Binary files a/installer/launch4j/head/head.o and b/installer/launch4j/head/head.o differ
diff --git a/installer/launch4j/head_jni_BETA/head.o b/installer/launch4j/head_jni_BETA/head.o
index f9e9f90..bd99219 100644
Binary files a/installer/launch4j/head_jni_BETA/head.o and b/installer/launch4j/head_jni_BETA/head.o differ
diff --git a/installer/launch4j/head_jni_BETA/jnihead.o b/installer/launch4j/head_jni_BETA/jnihead.o
index 1512568..5b65824 100644
Binary files a/installer/launch4j/head_jni_BETA/jnihead.o and b/installer/launch4j/head_jni_BETA/jnihead.o differ
diff --git a/installer/launch4j/head_src/head.c b/installer/launch4j/head_src/head.c
index d36873f..659bb89 100644
--- a/installer/launch4j/head_src/head.c
+++ b/installer/launch4j/head_src/head.c
@@ -207,6 +207,7 @@ BOOL loadString(const int resID, char* buffer)
HRSRC hResource;
HGLOBAL hResourceLoaded;
LPBYTE lpBuffer;
+ debugAll("Resource %d:\t", resID);
hResource = FindResourceEx(hModule, RT_RCDATA, MAKEINTRESOURCE(resID),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT));
@@ -224,10 +225,7 @@ BOOL loadString(const int resID, char* buffer)
buffer[x] = (char) lpBuffer[x];
} while (buffer[x++] != 0);
- if (debugAll)
- {
- debug("Resource %d:\t%s\n", resID, buffer);
- }
+ debugAll("%s\n", buffer);
return TRUE;
}
}
@@ -237,6 +235,8 @@ BOOL loadString(const int resID, char* buffer)
SetLastError(0);
buffer[0] = 0;
}
+
+ debugAll("\n");
return FALSE;
}
@@ -312,27 +312,118 @@ BOOL regQueryValue(const char* regPath, unsigned char* buffer,
return result;
}
+int findNextVersionPart(const char* startAt)
+{
+ if (startAt == NULL || strlen(startAt) == 0)
+ {
+ return 0;
+ }
+
+ char* firstSeparatorA = strchr(startAt, '.');
+ char* firstSeparatorB = strchr(startAt, '_');
+ char* firstSeparator;
+ if (firstSeparatorA == NULL)
+ {
+ firstSeparator = firstSeparatorB;
+ }
+ else if (firstSeparatorB == NULL)
+ {
+ firstSeparator = firstSeparatorA;
+ }
+ else
+ {
+ firstSeparator = min(firstSeparatorA, firstSeparatorB);
+ }
+
+ if (firstSeparator == NULL)
+ {
+ return strlen(startAt);
+ }
+
+ return firstSeparator - startAt;
+}
+
+/**
+ * This method will take java version from `originalVersion` string and convert/format it
+ * into `version` string that can be used for string comparison with other versions.
+ *
+ * Due to different version schemas <=8 vs. >=9 it will "normalize" versions to 1 format
+ * so we can directly compare old and new versions.
+ */
void formatJavaVersion(char* version, const char* originalVersion)
{
- char* updatePart = strchr(originalVersion, '_');
+ strcpy(version, "");
+ if (originalVersion == NULL || strlen(originalVersion) == 0)
+ {
+ return;
+ }
+
+ int partsAdded = 0;
+ int i;
+ char* pos = (char*) originalVersion;
+ int curPartLen;
- if (updatePart != NULL)
+ while ((curPartLen = findNextVersionPart(pos)) > 0)
{
- // skip underscore
- updatePart++;
+ char number[curPartLen + 1];
+ memset(number, 0, curPartLen + 1);
+ strncpy(number, pos, curPartLen);
- if (strlen(updatePart) < 3)
+ if (partsAdded == 0 && (curPartLen != 1 || number[0] != '1'))
{
- const int majorVersionLength = updatePart - originalVersion;
- strncpy(version, originalVersion, majorVersionLength);
- *(version + majorVersionLength) = 0;
- strcat(version, "0");
- strcat(version, updatePart);
- return;
- }
- }
-
- strcpy(version, originalVersion);
+ // NOTE: When it's java 9+ we'll add "1" as the first part of the version
+ strcpy(version, "1");
+ partsAdded++;
+ }
+
+ if (partsAdded < 3)
+ {
+ if (partsAdded > 0)
+ {
+ strcat(version, ".");
+ }
+ for (i = 0;
+ (partsAdded > 0)
+ && (i < JRE_VER_MAX_DIGITS_PER_PART - strlen(number));
+ i++)
+ {
+ strcat(version, "0");
+ }
+ strcat(version, number);
+ }
+ else if (partsAdded == 3)
+ {
+ // add as an update
+ strcat(version, "_");
+ for (i = 0; i < JRE_VER_MAX_DIGITS_PER_PART - strlen(number); i++)
+ {
+ strcat(version, "0");
+ }
+ strcat(version, number);
+ }
+ else if (partsAdded >= 4)
+ {
+ debug("Warning:\tformatJavaVersion() too many parts added.\n");
+ break;
+ }
+ partsAdded++;
+
+ pos += curPartLen + 1;
+ if (pos >= originalVersion + strlen(originalVersion))
+ {
+ break;
+ }
+ }
+
+ for (i = partsAdded; i < 3; i++)
+ {
+ strcat(version, ".");
+ int j;
+ for (j = 0; j < JRE_VER_MAX_DIGITS_PER_PART; j++)
+ {
+ strcat(version, "0");
+ }
+ }
}
void regSearch(const char* keyName, const int searchType)
@@ -419,10 +510,6 @@ BOOL isJavaHomeValid(const char* keyName, const int searchType)
path[i] = buffer[i];
} while (path[i++] != 0);
- if (searchType & FOUND_SDK)
- {
- appendPath(path, "jre");
- }
valid = isLauncherPathValid(path);
}
RegCloseKey(hKey);
@@ -511,6 +598,10 @@ void regSearchWow(const char* keyName, const int searchType)
case USE_32_BIT_RUNTIME:
regSearch(keyName, searchType);
break;
+
+ default:
+ debug("Runtime bits:\tFailed to load.\n");
+ break;
}
}
@@ -538,10 +629,25 @@ void regSearchJreSdk(const char* jreKeyName, const char* sdkKeyName,
BOOL findJavaHome(char* path, const int jdkPreference)
{
+ debugAll("findJavaHome()\n");
regSearchJreSdk("SOFTWARE\\JavaSoft\\Java Runtime Environment",
"SOFTWARE\\JavaSoft\\Java Development Kit",
jdkPreference);
+ // Java 9 support
+ regSearchJreSdk("SOFTWARE\\JavaSoft\\JRE",
+ "SOFTWARE\\JavaSoft\\JDK",
+ jdkPreference);
+
+ // IBM Java 1.8
+ if (search.foundJava == NO_JAVA_FOUND)
+ {
+ regSearchJreSdk("SOFTWARE\\IBM\\Java Runtime Environment",
+ "SOFTWARE\\IBM\\Java Development Kit",
+ jdkPreference);
+ }
+
+ // IBM Java 1.7 and earlier
if (search.foundJava == NO_JAVA_FOUND)
{
regSearchJreSdk("SOFTWARE\\IBM\\Java2 Runtime Environment",
@@ -648,6 +754,10 @@ BOOL expandVars(char *dst, const char *src, const char *exePath, const int pathL
else if (strstr(varName, HKEY_STR) == varName)
{
regQueryValue(varName, dst + strlen(dst), BIG_STR);
+ }
+ else if (strcmp(varName, "") == 0)
+ {
+ strcat(dst, "%");
}
else if (GetEnvironmentVariable(varName, varValue, MAX_VAR_SIZE) > 0)
{
@@ -768,6 +878,7 @@ BOOL createMutex()
if (*mutexName)
{
+ debug("Create mutex:\t%s\n", mutexName);
SECURITY_ATTRIBUTES security;
security.nLength = sizeof(SECURITY_ATTRIBUTES);
security.bInheritHandle = TRUE;
@@ -802,8 +913,16 @@ void setWorkingDirectory(const char *exePath, const int pathLen)
BOOL bundledJreSearch(const char *exePath, const int pathLen)
{
+ debugAll("bundledJreSearch()\n");
char tmpPath[_MAX_PATH] = {0};
+ BOOL is64BitJre = loadBool(BUNDLED_JRE_64_BIT);
+ if (!wow64 && is64BitJre)
+ {
+ debug("Bundled JRE:\tCannot use 64-bit runtime on 32-bit OS.\n");
+ return FALSE;
+ }
+
if (loadString(JRE_PATH, tmpPath))
{
char jrePath[MAX_ARGS] = {0};
@@ -824,9 +943,7 @@ BOOL bundledJreSearch(const char *exePath, const int pathLen)
if (isLauncherPathValid(launcher.cmd))
{
- search.foundJava = (wow64 && loadBool(BUNDLED_JRE_64_BIT))
- ? FOUND_BUNDLED | KEY_WOW64_64KEY
- : FOUND_BUNDLED;
+ search.foundJava = is64BitJre ? FOUND_BUNDLED | KEY_WOW64_64KEY : FOUND_BUNDLED;
strcpy(search.foundJavaHome, launcher.cmd);
return TRUE;
}
@@ -837,6 +954,7 @@ BOOL bundledJreSearch(const char *exePath, const int pathLen)
BOOL installedJreSearch()
{
+ debugAll("installedJreSearch()\n");
return *search.javaMinVer && findJavaHome(launcher.cmd, loadInt(JDK_PREFERENCE));
}
@@ -883,13 +1001,16 @@ void createJreSearchError()
BOOL jreSearch(const char *exePath, const int pathLen)
{
+ debugAll("jreSearch()\n");
BOOL result = TRUE;
search.bundledJreAsFallback = loadBool(BUNDLED_JRE_AS_FALLBACK);
loadString(JAVA_MIN_VER, search.originalJavaMinVer);
formatJavaVersion(search.javaMinVer, search.originalJavaMinVer);
+ debug("Java min ver:\t%s\n", search.javaMinVer);
loadString(JAVA_MAX_VER, search.originalJavaMaxVer);
formatJavaVersion(search.javaMaxVer, search.originalJavaMaxVer);
+ debug("Java max ver:\t%s\n", search.javaMaxVer);
if (search.bundledJreAsFallback)
{
@@ -978,6 +1099,8 @@ void setMainClassAndClassPath(const char *exePath, const int pathLen)
if (loadString(MAIN_CLASS, launcher.mainClass))
{
+ debug("Main class:\t%s\n", launcher.mainClass);
+
if (!loadString(CLASSPATH, classPath))
{
debug("Info:\t\tClasspath not defined.\n");
diff --git a/installer/launch4j/head_src/head.h b/installer/launch4j/head_src/head.h
index 682af3b..6e2057b 100644
--- a/installer/launch4j/head_src/head.h
+++ b/installer/launch4j/head_src/head.h
@@ -54,7 +54,9 @@
#include
#define LAUNCH4j "Launch4j"
-#define VERSION "3.9"
+#define VERSION "3.12"
+
+#define JRE_VER_MAX_DIGITS_PER_PART 3
#define NO_JAVA_FOUND 0
#define FOUND_JRE 1
@@ -91,6 +93,7 @@
#define ERROR_FORMAT "Error:\t\t%s\n"
#define debug(args...) if (hLog != NULL) fprintf(hLog, ## args);
+#define debugAll(args...) if (debugAll && hLog != NULL) fprintf(hLog, ## args);
typedef void (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
diff --git a/installer/launch4j/head_src/jnihead.c b/installer/launch4j/head_src/jnihead.c
index 4b88601..16464dd 100644
--- a/installer/launch4j/head_src/jnihead.c
+++ b/installer/launch4j/head_src/jnihead.c
@@ -35,7 +35,6 @@ JavaVM* g_pJavaVM = NULL;
JNIEnv* g_pJNIEnv = NULL;
JavaVMInitArgs g_sJavaVMInitArgs;
char g_rgcMnClsArgs[MAX_ARGS] = {0};
-char g_rgcClsPth[MAX_ARGS] = {0};
char g_rgcMnCls[_MAX_PATH] = {0};
char g_rgcCurrJrePth[_MAX_PATH] = {0};
HINSTANCE g_hInstance;
@@ -67,6 +66,8 @@ void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOp
char *pcCurrOpt;
char **prgcVmArgs = NULL;
strncpy(rgcOptCpy, pcOpts, MAX_ARGS - 1);
+
+
iArgCnt = getArgCount(rgcOptCpy);
if (iArgCnt > 0)
{
@@ -80,6 +81,7 @@ void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOp
/* Allocat iArgCnt JavaVMOptions for the g_sJavaVMInitArgs struct */
g_sJavaVMInitArgs.options = malloc(iArgCnt * sizeof(JavaVMOption));
memset(g_sJavaVMInitArgs.options, 0, iArgCnt * sizeof(JavaVMOption));
+ char* rgcClsPth = 0;
/* Copy the tokenized array into the allocated JavaVMOption array,
* with some special handling for classpath related arguments */
for (iCurrArg = 0; iCurrArg < iArgCnt; iCurrArg++)
@@ -100,16 +102,18 @@ void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOp
rgcTmp[strlen(rgcTmp)-1] = '\0';
/* If we haven't defined a classpath yet start one, otherwise
* we just append the this classpath to it */
- if (g_rgcClsPth[0] == '\0')
+ if (!rgcClsPth)
{
- sprintf(g_rgcClsPth,"-Djava.class.path=%s", rgcTmp);
- g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString = g_rgcClsPth;
+ rgcClsPth = malloc(MAX_ARGS * sizeof(char));
+ memset(rgcClsPth, 0, MAX_ARGS * sizeof(char));
+ sprintf(rgcClsPth,"-Djava.class.path=%s", rgcTmp);
+ g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString = rgcClsPth;
}
else
{
iSkipArgCnt++;
- strcat(g_rgcClsPth,";");
- strcat(g_rgcClsPth,rgcTmp);
+ strcat(rgcClsPth,";");
+ strcat(rgcClsPth,rgcTmp);
}
}
diff --git a/installer/launch4j/launch4j.exe b/installer/launch4j/launch4j.exe
index ad1ccd6..9acf516 100644
Binary files a/installer/launch4j/launch4j.exe and b/installer/launch4j/launch4j.exe differ
diff --git a/installer/launch4j/launch4j.jar b/installer/launch4j/launch4j.jar
index 6daad70..f4d6774 100644
Binary files a/installer/launch4j/launch4j.jar and b/installer/launch4j/launch4j.jar differ
diff --git a/installer/launch4j/launch4jc.exe b/installer/launch4j/launch4jc.exe
index 736e37c..d63fbce 100644
Binary files a/installer/launch4j/launch4jc.exe and b/installer/launch4j/launch4jc.exe differ
diff --git a/installer/launch4j/maven/assembly/assemble-linux.xml b/installer/launch4j/maven/assembly/assemble-linux.xml
index aa4abd0..94d4cf9 100644
--- a/installer/launch4j/maven/assembly/assemble-linux.xml
+++ b/installer/launch4j/maven/assembly/assemble-linux.xml
@@ -44,7 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
${finalName}-workdir-linux
w32api/**/*
+ w32api_jni/**/*
head/**/*
+ head_jni_BETA/**/*
diff --git a/installer/launch4j/maven/assembly/assemble-linux64.xml b/installer/launch4j/maven/assembly/assemble-linux64.xml
new file mode 100644
index 0000000..d116be7
--- /dev/null
+++ b/installer/launch4j/maven/assembly/assemble-linux64.xml
@@ -0,0 +1,53 @@
+
+
+
+ workdir-linux64
+
+ jar
+
+ false
+
+
+ bin/bin-linux64
+ ${finalName}-workdir-linux64/bin
+
+
+ ${finalName}-workdir-linux64
+
+ w32api/**/*
+ w32api_jni/**/*
+ head/**/*
+ head_jni_BETA/**/*
+
+
+
+
diff --git a/installer/launch4j/maven/assembly/assemble-mac.xml b/installer/launch4j/maven/assembly/assemble-mac.xml
index 30453be..e813f72 100644
--- a/installer/launch4j/maven/assembly/assemble-mac.xml
+++ b/installer/launch4j/maven/assembly/assemble-mac.xml
@@ -44,7 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
${finalName}-workdir-mac
w32api/**/*
+ w32api_jni/**/*
head/**/*
+ head_jni_BETA/**/*
diff --git a/installer/launch4j/maven/assembly/assemble-win32.xml b/installer/launch4j/maven/assembly/assemble-win32.xml
index 5f382fc..4680f89 100644
--- a/installer/launch4j/maven/assembly/assemble-win32.xml
+++ b/installer/launch4j/maven/assembly/assemble-win32.xml
@@ -41,11 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
${finalName}-workdir-win32/bin
-
${finalName}-workdir-win32
w32api/**/*
+ w32api_jni/**/*
head/**/*
+ head_jni_BETA/**/*
diff --git a/installer/launch4j/maven/maven-readme.txt b/installer/launch4j/maven/maven-readme.txt
index 8429754..c977ad8 100644
--- a/installer/launch4j/maven/maven-readme.txt
+++ b/installer/launch4j/maven/maven-readme.txt
@@ -5,6 +5,4 @@ Windows: mvn -P dist,win32 clean package
Linux: mvn -P dist,linux clean package
-MacOsX 10.8: mvn -P dist,macosx-x86-10.8 clean package
-
MacOsX: mvn -P dist,macosx-x86 clean package
diff --git a/installer/launch4j/maven/pom.xml b/installer/launch4j/maven/pom.xml
index 0b8b72e..b9f0db5 100644
--- a/installer/launch4j/maven/pom.xml
+++ b/installer/launch4j/maven/pom.xml
@@ -236,9 +236,9 @@
assembly/assemble-linux.xml
+ assembly/assemble-linux64.xml
assembly/assemble-win32.xml
assembly/assemble-mac.xml
- assembly/assemble-osx.xml
@@ -360,13 +360,6 @@
-
-
- macosx-x86-10.8
-
- bin-macosx-x86-10.8
-
-
macosx-x86
@@ -419,7 +412,7 @@
${versionNumber}
${version}
Cross-platform Java application wrapper
- Copyright (C) 2004, 2014 Grzegorz Kowal
+ Copyright (C) 2004, 2017 Grzegorz Kowal
launch4j
http://launch4j.sourceforge.net/
GUI launcher
diff --git a/installer/launch4j/src/LICENSE.txt b/installer/launch4j/src/LICENSE.txt
index bf03c83..38af528 100644
--- a/installer/launch4j/src/LICENSE.txt
+++ b/installer/launch4j/src/LICENSE.txt
@@ -1,7 +1,7 @@
Launch4j (http://launch4j.sourceforge.net/)
Cross-platform Java application wrapper for creating Windows native executables.
-Copyright (c) 2004, 2015 Grzegorz Kowal
+Copyright (c) 2004, 2017 Grzegorz Kowal
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
diff --git a/installer/launch4j/src/launch4j.properties b/installer/launch4j/src/launch4j.properties
index 7268b62..a14697f 100644
--- a/installer/launch4j/src/launch4j.properties
+++ b/installer/launch4j/src/launch4j.properties
@@ -1,2 +1,2 @@
-versionNumber=3.9.0.0
-version=3.9
+versionNumber=3.12.0.0
+version=3.12
diff --git a/installer/launch4j/src/net/sf/launch4j/Main.java b/installer/launch4j/src/net/sf/launch4j/Main.java
index 4a139b5..820f4be 100644
--- a/installer/launch4j/src/net/sf/launch4j/Main.java
+++ b/installer/launch4j/src/net/sf/launch4j/Main.java
@@ -86,7 +86,7 @@ private static void setDescription(Properties props) {
" (http://launch4j.sourceforge.net/)\n" +
"Cross-platform Java application wrapper" +
" for creating Windows native executables.\n\n" +
- "Copyright (C) 2004, 2015 Grzegorz Kowal\n\n" +
+ "Copyright (C) 2004, 2018 Grzegorz Kowal\n\n" +
"Launch4j comes with ABSOLUTELY NO WARRANTY.\n" +
"This is free software, licensed under the BSD License.\n" +
"This product includes software developed by the Apache Software Foundation" +
diff --git a/installer/launch4j/src/net/sf/launch4j/RcBuilder.java b/installer/launch4j/src/net/sf/launch4j/RcBuilder.java
index 11188b0..45f2339 100644
--- a/installer/launch4j/src/net/sf/launch4j/RcBuilder.java
+++ b/installer/launch4j/src/net/sf/launch4j/RcBuilder.java
@@ -112,7 +112,7 @@ public class RcBuilder {
public static final int INSTANCE_ALREADY_EXISTS_MSG = 105;
private final StringBuffer _sb = new StringBuffer();
-
+
public String getContent() {
return _sb.toString();
}
diff --git a/installer/launch4j/src/net/sf/launch4j/config/Jre.java b/installer/launch4j/src/net/sf/launch4j/config/Jre.java
index ceb2801..cd91661 100644
--- a/installer/launch4j/src/net/sf/launch4j/config/Jre.java
+++ b/installer/launch4j/src/net/sf/launch4j/config/Jre.java
@@ -54,8 +54,8 @@ public class Jre implements IValidatable {
public static final String ARGS = "jvmArgs";
// __________________________________________________________________________________
- public static final String VERSION_PATTERN = "(\\d\\.){2}\\d(_\\d+)?";
-
+ public static final String VERSION_PATTERN = "(1\\.\\d\\.\\d(_\\d{1,3})?)|[1-9][0-9]{0,2}(\\.\\d{1,3}){0,2}";
+
public static final String JDK_PREFERENCE_JRE_ONLY = "jreOnly";
public static final String JDK_PREFERENCE_PREFER_JRE = "preferJre";
public static final String JDK_PREFERENCE_PREFER_JDK = "preferJdk";
@@ -98,9 +98,9 @@ public class Jre implements IValidatable {
private List options;
public void checkInvariants() {
- Validator.checkOptString(minVersion, 10, VERSION_PATTERN,
+ Validator.checkOptString(minVersion, 20, VERSION_PATTERN,
"jre.minVersion", Messages.getString("Jre.min.version"));
- Validator.checkOptString(maxVersion, 10, VERSION_PATTERN,
+ Validator.checkOptString(maxVersion, 20, VERSION_PATTERN,
"jre.maxVersion", Messages.getString("Jre.max.version"));
if (Validator.isEmpty(path)) {
Validator.checkFalse(bundledJre64Bit, "jre.bundledJre64Bit",
@@ -116,7 +116,7 @@ public void checkInvariants() {
if (!Validator.isEmpty(maxVersion)) {
Validator.checkFalse(Validator.isEmpty(minVersion),
"jre.minVersion", Messages.getString("Jre.specify.min.version"));
- Validator.checkTrue(minVersion.compareTo(maxVersion) < 0,
+ Validator.checkTrue(JreVersion.parseString(minVersion).compareTo(JreVersion.parseString(maxVersion)) < 0,
"jre.maxVersion", Messages.getString("Jre.max.greater.than.min"));
}
Validator.checkTrue(initialHeapSize == null || maxHeapSize != null,
@@ -155,7 +155,7 @@ public void checkInvariants() {
Validator.checkOptStrings(options,
Validator.MAX_ARGS,
Validator.MAX_ARGS,
- "[^%]*|([^%]*([^%]*%[^%]+%[^%]*)+[^%]*)*",
+ "[^%]*|([^%]*([^%]*%[^%]*%[^%]*)+[^%]*)*",
"jre.options",
Messages.getString("Jre.jvm.options"),
Messages.getString("Jre.jvm.options.variable"));
diff --git a/installer/launch4j/src/net/sf/launch4j/config/JreVersion.java b/installer/launch4j/src/net/sf/launch4j/config/JreVersion.java
new file mode 100644
index 0000000..185257e
--- /dev/null
+++ b/installer/launch4j/src/net/sf/launch4j/config/JreVersion.java
@@ -0,0 +1,124 @@
+package net.sf.launch4j.config;
+
+/**
+ * This class will abstract application from JRE versioning schema and provide
+ * comparing capabilities
+ *
+ * @author sergeyk
+ *
+ */
+public class JreVersion implements Comparable {
+ private int x1;
+ private int x2;
+ private int x3;
+ private int x4;
+
+ public static JreVersion parseString(String versionStr) {
+ JreVersion ret = new JreVersion();
+ if (versionStr == null || versionStr.trim().length() == 0) {
+ return ret;
+ }
+ if (!versionStr.matches(Jre.VERSION_PATTERN)) {
+ // NOTE: This is actually shouldn't happen because version format had to be
+ // checked by Jre#checkInvariants BEFORE calling this method
+ throw new IllegalArgumentException("JRE version is not in a right format.");
+ }
+
+ String[] parts = versionStr.split("[\\._]");
+ int first = Integer.parseInt(parts[0]);
+ if (first > 1) {
+ // java 9+ version schema
+ ret.x1 = 1;
+ ret.x2 = first;
+ if (parts.length >= 2) {
+ ret.x3 = Integer.parseInt(parts[1]);
+ if (parts.length >= 3) {
+ ret.x4 = Integer.parseInt(parts[2]);
+ }
+ }
+ } else {
+ // java <= 1.8 version schema
+ ret.x1 = first;
+ if (parts.length >= 2) {
+ ret.x2 = Integer.parseInt(parts[1]);
+ if (parts.length >= 3) {
+ ret.x3 = Integer.parseInt(parts[2]);
+ if (parts.length == 4) {
+ ret.x4 = Integer.parseInt(parts[3]);
+ }
+ }
+ }
+ }
+
+ return ret;
+ }
+
+ @Override
+ public String toString() {
+ if (x2 >= 9) {
+ return x2 + "." + x3 + "." + x4;
+ }
+
+ return x1 + "." + x2 + "." + x3 + (x4 > 0 ? "_" + x4 : "");
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + x1;
+ result = prime * result + x2;
+ result = prime * result + x3;
+ result = prime * result + x4;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ JreVersion other = (JreVersion) obj;
+ if (x1 != other.x1) {
+ return false;
+ }
+ if (x2 != other.x2) {
+ return false;
+ }
+ if (x3 != other.x3) {
+ return false;
+ }
+ if (x4 != other.x4) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int compareTo(JreVersion o) {
+ if (this.equals(o)) {
+ return 0;
+ }
+
+ if (x1 != o.x1) {
+ return x1 - o.x1;
+ }
+ if (x2 != o.x2) {
+ return x2 - o.x2;
+ }
+ if (x3 != o.x3) {
+ return x3 - o.x3;
+ }
+ if (x4 != o.x4) {
+ return x4 - o.x4;
+ }
+
+ throw new IllegalStateException("If you see this exception it means JreVersion::equals() method is buggy");
+ }
+}
diff --git a/installer/launch4j/src/net/sf/launch4j/config/messages.properties b/installer/launch4j/src/net/sf/launch4j/config/messages.properties
index 560554c..b2eecc4 100644
--- a/installer/launch4j/src/net/sf/launch4j/config/messages.properties
+++ b/installer/launch4j/src/net/sf/launch4j/config/messages.properties
@@ -69,8 +69,8 @@ VersionInfo.internal.name.not.exe=Internal name shouldn't have the .exe extensio
VersionInfo.original.filename=Original filename
VersionInfo.original.filename.exe=Original filename should end with the .exe extension.
-Jre.min.version=Minimum JRE version should be x.x.x[_xx]
-Jre.max.version=Maximum JRE version should be x.x.x[_xx]
+Jre.min.version=Minimum JRE version should be 1.x.x[_xxx] or the Java 9 new version scheme xxx[.xxx[.xxx]], e.g., 1.5, 1.8.0_121, 10.0.1
+Jre.max.version=Maximum JRE version should be 1.x.x[_xxx] or the Java 9 new version scheme xxx[.xxx[.xxx]], e.g., 1.5, 1.8.0_121, 10.0.1
Jre.specify.jre.min.version.or.path=Specify minimum JRE version and/or bundled JRE path.
Jre.bundled.path=Bundled JRE path
Jre.bundled.64bit.invalid=The bundled JRE 64-bit option can only be used if the JRE path is specified.
diff --git a/installer/launch4j/src/net/sf/launch4j/messages.properties b/installer/launch4j/src/net/sf/launch4j/messages.properties
index 9895ca3..db2f9cc 100644
--- a/installer/launch4j/src/net/sf/launch4j/messages.properties
+++ b/installer/launch4j/src/net/sf/launch4j/messages.properties
@@ -35,7 +35,7 @@ Main.usage=usage
Builder.compiling.resources=Compiling resources
Builder.linking=Linking
-Builder.wrapping=Wrapping
+Builder.wrapping=Wrapping\nWARNING: Sign the executable to minimize antivirus false positives or use launching instead of wrapping.
Builder.success=Successfully created
Builder.generated.resource.file=Generated resource file...\n
Builder.line.has.errors=Line {0} has errors...
diff --git a/installer/launch4j/web/changelog.html b/installer/launch4j/web/changelog.html
index c753be4..450a2c0 100644
--- a/installer/launch4j/web/changelog.html
+++ b/installer/launch4j/web/changelog.html
@@ -11,7 +11,7 @@
-
3.9
+
3.12
Changelog
+
Changes in version 3.12 (17-05-2018)
+
+ - Ticket #179, #183 The generated executable fully supports Java 9 and newer (Sergey Karpushin).
+ - Ticket #161 Support of update version higher than 99 (Sergey Karpushin).
+ - Ticket #177 Launching on Java 9 JDK and newer is now possible (not just JRE).
+ - Known issue: launch4j itself does not support Java 9 Early Access, use a public release instead or Java 10.
+
+
+
Changes in version 3.11 (27-06-2017)
+
+ - Log more regarding Java search and missing resources.
+ - Log resource file during build.
+ - Added basic Java 9 support (only major version is detected right now due to version scheme change).
+ - Ticket #145 Allow literal use of % in JRE options and set environment variables, use %% (blueskyhigh).
+ - Added Linux 64-bit binaries (Sebastian Bögl).
+ - Added IBM Java 1.8 support.
+ - JNI header: fixed a crash where launch4j would try to `free` non-heap memory (Alexander Floh).
+ - Ticket #160 Removed old Mac OS X package which caused problems on newer versions of the system.
+
+
Changes in version 3.9 (20-07-2016)
- - Ticket #146 Fixed java version check where the update number was greater than 99 (e.g. 1.8.0_101).
+ - Ticket #146 Fixed java version check where the update number was greater than 99 (e.g. 1.8.0_101).
- Enlarged the total classpath length to 30KB.
- Ticket #142 Unbound VersionInfo returns wrong LanguageID (Sebastian Bögl).
- Ticket #141 Ensure encoding of resource file to be iso-8859-1 (Thomas Scheithauer).
@@ -438,7 +458,7 @@ Changes in version 1.2.0 (10-09-2004)