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 @@
- launch4j 3.9 + launch4j 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)