diff --git a/launch4j/.classpath b/launch4j/.classpath index 36815f9..2082e35 100644 --- a/launch4j/.classpath +++ b/launch4j/.classpath @@ -1,6 +1,7 @@ + diff --git a/launch4j/.gitignore b/launch4j/.gitignore index 796b96d..c3dca1b 100644 --- a/launch4j/.gitignore +++ b/launch4j/.gitignore @@ -1 +1,2 @@ /build +/target diff --git a/launch4j/LICENSE.txt b/launch4j/LICENSE.txt index bf03c83..38af528 100644 --- a/launch4j/LICENSE.txt +++ b/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/launch4j/build.xml b/launch4j/build.xml index be5abf8..9264ea9 100644 --- a/launch4j/build.xml +++ b/launch4j/build.xml @@ -4,6 +4,8 @@ + + @@ -59,4 +61,17 @@ + + + + + + + + + + + + + diff --git a/launch4j/demo/ConsoleApp/ConsoleApp.jar b/launch4j/demo/ConsoleApp/ConsoleApp.jar index 2ddc626..14b8319 100644 --- a/launch4j/demo/ConsoleApp/ConsoleApp.jar +++ b/launch4j/demo/ConsoleApp/ConsoleApp.jar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:53c6d6a97267f788462aad0d1a89e90f73a0e583d12506fd114fc97f3f8d5235 +oid sha256:590ea97379013c8b186810a1a81e2001f8f63d042b0f02789a31f99a270c590d size 2099 diff --git a/launch4j/demo/ConsoleApp/build.xml b/launch4j/demo/ConsoleApp/build.xml index 78be0ae..b53d77f 100644 --- a/launch4j/demo/ConsoleApp/build.xml +++ b/launch4j/demo/ConsoleApp/build.xml @@ -42,7 +42,7 @@ - + diff --git a/launch4j/demo/ExitCodeApp/.gitignore b/launch4j/demo/ExitCodeApp/.gitignore new file mode 100644 index 0000000..c3dca1b --- /dev/null +++ b/launch4j/demo/ExitCodeApp/.gitignore @@ -0,0 +1,2 @@ +/build +/target diff --git a/launch4j/demo/ExitCodeApp/pom.xml b/launch4j/demo/ExitCodeApp/pom.xml new file mode 100644 index 0000000..cc7a008 --- /dev/null +++ b/launch4j/demo/ExitCodeApp/pom.xml @@ -0,0 +1,72 @@ + + 4.0.0 + net.sf.launch4j.example + ExitCodeApp + 1.0 + ExitCodeApp + jar + + + UTF-8 + + + + src + + + src + + **/*.java + + + + + + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + + + + com.akathist.maven.plugins.launch4j + launch4j-maven-plugin + 1.7.6 + + + l4j + package + launch4j + + console + target/ExitCodeApp.exe + target/ExitCodeApp-1.0.jar + ExitCodeApp + + net.sf.launch4j.example.ExitCodeApp + false + anything + + + 1.5.0 + + + 1.0.0.0 + 1.0 + Simple app for testing exit code. + Copyright (C) 2015 GK + 3.9.0.0 + 3.9 + ExitCodeApp + ExitCodeApp + ExitCodeApp.exe + + + + + + + + \ No newline at end of file diff --git a/launch4j/demo/ExitCodeApp/src/net/sf/launch4j/example/ExitCodeApp.java b/launch4j/demo/ExitCodeApp/src/net/sf/launch4j/example/ExitCodeApp.java new file mode 100644 index 0000000..7738b49 --- /dev/null +++ b/launch4j/demo/ExitCodeApp/src/net/sf/launch4j/example/ExitCodeApp.java @@ -0,0 +1,47 @@ +/* + Launch4j (http://launch4j.sourceforge.net/) + Cross-platform Java application wrapper for creating Windows native executables. + + Copyright (c) 2004, 2015 Grzegorz Kowal + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package net.sf.launch4j.example; + +public class ExitCodeApp { + public static void main(String[] args) { + int exitCode = 0; + + if (args.length > 0) { + exitCode = Integer.parseInt(args[0]); + } + + System.out.println("Exit code: " + String.valueOf(exitCode)); + System.exit(exitCode); + } +} diff --git a/launch4j/demo/SimpleApp/SimpleApp.jar b/launch4j/demo/SimpleApp/SimpleApp.jar index 4a71422..22316c6 100644 --- a/launch4j/demo/SimpleApp/SimpleApp.jar +++ b/launch4j/demo/SimpleApp/SimpleApp.jar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:58b032fd1b0589cd3ec291f9fbccdccbcd97bd800cfda9c8ee959b2c7a1f5173 -size 4588 +oid sha256:6317805991aa6bb8094a2e7c39dd2604f804d761a7cca231c07b9906e43a91e1 +size 5942 diff --git a/launch4j/demo/SimpleApp/l4j/SimpleApp.xml b/launch4j/demo/SimpleApp/l4j/SimpleApp.xml index bb5804d..eacd757 100644 --- a/launch4j/demo/SimpleApp/l4j/SimpleApp.xml +++ b/launch4j/demo/SimpleApp/l4j/SimpleApp.xml @@ -1,6 +1,7 @@ gui - ../SimpleApp.jar + SimpleApp.jar + true ../SimpleApp.exe SimpleApp . diff --git a/launch4j/demo/SimpleApp/src/net/sf/launch4j/example/SimpleApp.java b/launch4j/demo/SimpleApp/src/net/sf/launch4j/example/SimpleApp.java index 51d1109..1b6fc5d 100644 --- a/launch4j/demo/SimpleApp/src/net/sf/launch4j/example/SimpleApp.java +++ b/launch4j/demo/SimpleApp/src/net/sf/launch4j/example/SimpleApp.java @@ -34,31 +34,63 @@ package net.sf.launch4j.example; import java.awt.Dimension; +import java.awt.Font; import java.awt.Toolkit; import java.awt.event.ActionEvent; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import javax.swing.AbstractAction; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; -import javax.swing.JOptionPane; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; import javax.swing.UIManager; public class SimpleApp extends JFrame { - public SimpleApp(String[] args) { - super("Java Application"); + public SimpleApp(String[] args) { + super("Java Application"); - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + if (args.length == 1 && "throw".equals(args[0])) { + throw new IllegalStateException("Exception thrown from SimpleApp."); + } + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); setBounds (screenSize.width / 4, screenSize.height / 4, screenSize.width / 2, screenSize.height / 2); - JMenu menu = new JMenu("File"); - menu.add(new JMenuItem("Open")); - menu.add(new JMenuItem("Save")); - - menu.addSeparator(); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + }}); + + initializeMenu(); + initializeTextArea(args); + setVisible(true); + } + + public static void setLAF() { + JFrame.setDefaultLookAndFeelDecorated(true); + Toolkit.getDefaultToolkit().setDynamicLayout(true); + System.setProperty("sun.awt.noerasebackground","true"); + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + } catch (Exception e) { + System.err.println("Failed to set LookAndFeel"); + } + } + + public static void main(String[] args) { + setLAF(); + new SimpleApp(args); + } + + private final void initializeMenu() { + JMenu menu = new JMenu("Exit with code"); menu.add(new JMenuItem(new AbstractAction("Exit with code 0") { @Override @@ -78,45 +110,86 @@ public class SimpleApp extends JFrame { mb.setOpaque(true); mb.add(menu); setJMenuBar(mb); + } + + private final void initializeTextArea(String[] args) { + JTextArea textArea = new JTextArea(); + textArea.setFont(new Font(Font.MONOSPACED, Font.PLAIN, 12)); + textArea.setEditable(false); + + JScrollPane scrollPane = new JScrollPane(); + scrollPane.setViewportView(textArea); + scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); + scrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); + getContentPane().add(scrollPane); - this.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - System.exit(0); - }}); - setVisible(true); + textArea.setText(getMainProperties(args)); + textArea.append(getAllProperties()); + textArea.append(getEnvironmentVariables()); + } + private final String getMainProperties(String[] args) { StringBuffer sb = new StringBuffer("Java version: "); sb.append(System.getProperty("java.version")); sb.append("\nJava home: "); sb.append(System.getProperty("java.home")); sb.append("\nCurrent dir: "); sb.append(System.getProperty("user.dir")); - if (args.length > 0) { - sb.append("\nArgs: "); - for (int i = 0; i < args.length; i++) { - sb.append(args[i]); + sb.append("\nCommand line args: {"); + + for (int i = 0; i < args.length; i++) { + if (i > 0) + { sb.append(' '); } + sb.append(args[i]); } - JOptionPane.showMessageDialog(this, - sb.toString(), - "Info", - JOptionPane.INFORMATION_MESSAGE); - } - public static void setLAF() { - JFrame.setDefaultLookAndFeelDecorated(true); - Toolkit.getDefaultToolkit().setDynamicLayout(true); - System.setProperty("sun.awt.noerasebackground","true"); - try { - UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); - } catch (Exception e) { - System.err.println("Failed to set LookAndFeel"); - } + sb.append("}\n"); + + final int mb = 1024 * 1024; + sb.append("Free memory (MB): "); + sb.append(Runtime.getRuntime().freeMemory() / mb); + sb.append("\nTotal memory (MB): "); + sb.append(Runtime.getRuntime().totalMemory() / mb); + sb.append("\nMax memory (MB): "); + sb.append(Runtime.getRuntime().maxMemory() / mb); + sb.append("\n"); + + return sb.toString(); } + + private final String getAllProperties() { + StringBuffer sb = new StringBuffer("\n========== All properties ==========\n"); - public static void main(String[] args) { - setLAF(); - new SimpleApp(args); + List keys = new ArrayList(); + keys.addAll(System.getProperties().stringPropertyNames()); + Collections.sort(keys); + + for (String key : keys) { + sb.append(key); + sb.append(": "); + sb.append(System.getProperty(key)); + sb.append("\n"); + } + + return sb.toString(); + } + + private final String getEnvironmentVariables() { + StringBuffer sb = new StringBuffer("\n========== Environment variables ==========\n"); + + List keys = new ArrayList(); + keys.addAll(System.getenv().keySet()); + Collections.sort(keys); + + for (String key : keys) { + sb.append(key); + sb.append(": "); + sb.append(System.getenv(key)); + sb.append("\n"); + } + + return sb.toString(); } } diff --git a/launch4j/head/guihead.o b/launch4j/head/guihead.o index 9cc215d..7cff132 100644 Binary files a/launch4j/head/guihead.o and b/launch4j/head/guihead.o differ diff --git a/launch4j/head/head.o b/launch4j/head/head.o index 9ed33e0..849299f 100644 Binary files a/launch4j/head/head.o and b/launch4j/head/head.o differ diff --git a/launch4j/head_jni_BETA/LICENSE.txt b/launch4j/head_jni_BETA/LICENSE.txt new file mode 100644 index 0000000..e95c830 --- /dev/null +++ b/launch4j/head_jni_BETA/LICENSE.txt @@ -0,0 +1,26 @@ +Launch4j (http://launch4j.sourceforge.net/) +Cross-platform Java application wrapper for creating Windows native executables. + +Copyright (c) 2004, 2015 Grzegorz Kowal + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +Except as contained in this notice, the name(s) of the above copyright holders +shall not be used in advertising or otherwise to promote the sale, use or other +dealings in this Software without prior written authorization. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. \ No newline at end of file diff --git a/launch4j/head_jni_BETA/head.o b/launch4j/head_jni_BETA/head.o new file mode 100644 index 0000000..bd99219 Binary files /dev/null and b/launch4j/head_jni_BETA/head.o differ diff --git a/launch4j/head_jni_BETA/jniconsolehead.o b/launch4j/head_jni_BETA/jniconsolehead.o new file mode 100644 index 0000000..2070023 Binary files /dev/null and b/launch4j/head_jni_BETA/jniconsolehead.o differ diff --git a/launch4j/head_jni_BETA/jniguihead.o b/launch4j/head_jni_BETA/jniguihead.o new file mode 100644 index 0000000..6ece617 Binary files /dev/null and b/launch4j/head_jni_BETA/jniguihead.o differ diff --git a/launch4j/head_jni_BETA/jnihead.o b/launch4j/head_jni_BETA/jnihead.o new file mode 100644 index 0000000..5b65824 Binary files /dev/null and b/launch4j/head_jni_BETA/jnihead.o differ diff --git a/launch4j/head_src/guihead/guihead.c b/launch4j/head_src/guihead/guihead.c index f0d9935..6d165a2 100644 --- a/launch4j/head_src/guihead/guihead.c +++ b/launch4j/head_src/guihead/guihead.c @@ -91,6 +91,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, splashTimeout = DEFAULT_SPLASH_TIMEOUT; } } + splashTimeout = splashTimeout * 1000; // to millis splashTimeoutErr = loadBool(SPLASH_TIMEOUT_ERR) && strstr(lpCmdLine, "--l4j-no-splash-err") == NULL; waitForWindow = loadBool(SPLASH_WAITS_FOR_WINDOW); @@ -120,7 +121,7 @@ int APIENTRY WinMain(HINSTANCE hInstance, { if (splash || stayAlive) { - if (!SetTimer (hWnd, ID_TIMER, 1000 /* 1s */, TimerProc)) + if (!SetTimer (hWnd, ID_TIMER, TIMER_PROC_INTERVAL, TimerProc)) { signalError(); return 1; @@ -222,7 +223,7 @@ VOID CALLBACK TimerProc( } else { - splashTimeout--; + splashTimeout -= TIMER_PROC_INTERVAL; if (waitForWindow) { EnumWindows(enumwndfn, 0); diff --git a/launch4j/head_src/guihead/guihead.h b/launch4j/head_src/guihead/guihead.h index ebef396..e8208d3 100644 --- a/launch4j/head_src/guihead/guihead.h +++ b/launch4j/head_src/guihead/guihead.h @@ -30,6 +30,7 @@ #define ID_TIMER 1 #define DEFAULT_SPLASH_TIMEOUT 60 /* 60 seconds */ #define MAX_SPLASH_TIMEOUT 60 * 15 /* 15 minutes */ +#define TIMER_PROC_INTERVAL 100 /* interval in ms between calls to EnumWindows */ HWND getInstanceWindow(); diff --git a/launch4j/head_src/head.c b/launch4j/head_src/head.c index dd093d7..bc13caa 100644 --- a/launch4j/head_src/head.c +++ b/launch4j/head_src/head.c @@ -55,6 +55,8 @@ struct int foundJava; BOOL bundledJreAsFallback; BOOL corruptedJreFound; + char originalJavaMinVer[STR]; + char originalJavaMaxVer[STR]; char javaMinVer[STR]; char javaMaxVer[STR]; char foundJavaVer[STR]; @@ -64,6 +66,7 @@ struct struct { + char mainClass[_MAX_PATH]; char cmd[_MAX_PATH]; char args[MAX_ARGS]; } launcher; @@ -150,7 +153,14 @@ void msgBox(const char* text) { if (console) { - printf("%s: %s\n", error.title, text); + if (*error.title) + { + printf("%s: %s\n", error.title, text); + } + else + { + printf("%s\n", text); + } } else { @@ -197,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)); @@ -214,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; } } @@ -227,6 +235,8 @@ BOOL loadString(const int resID, char* buffer) SetLastError(0); buffer[0] = 0; } + + debugAll("\n"); return FALSE; } @@ -302,6 +312,120 @@ 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) +{ + strcpy(version, ""); + if (originalVersion == NULL || strlen(originalVersion) == 0) + { + return; + } + + int partsAdded = 0; + int i; + char* pos = (char*) originalVersion; + int curPartLen; + + while ((curPartLen = findNextVersionPart(pos)) > 0) + { + char number[curPartLen + 1]; + memset(number, 0, curPartLen + 1); + strncpy(number, pos, curPartLen); + + if (partsAdded == 0 && (curPartLen != 1 || number[0] != '1')) + { + // 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) { HKEY hKey; @@ -322,12 +446,13 @@ void regSearch(const char* keyName, const int searchType) unsigned long versionSize = _MAX_PATH; FILETIME time; char fullKeyName[_MAX_PATH] = {0}; + char originalVersion[_MAX_PATH] = {0}; char version[_MAX_PATH] = {0}; while (RegEnumKeyEx( hKey, // handle to key to enumerate x++, // index of subkey to enumerate - version, // address of buffer for subkey name + originalVersion,// address of buffer for subkey name &versionSize, // address for size of subkey buffer NULL, // reserved NULL, // address of buffer for class string @@ -335,8 +460,9 @@ void regSearch(const char* keyName, const int searchType) &time) == ERROR_SUCCESS) { strcpy(fullKeyName, keyName); - appendPath(fullKeyName, version); + appendPath(fullKeyName, originalVersion); debug("Check:\t\t%s\n", fullKeyName); + formatJavaVersion(version, originalVersion); if (strcmp(version, search.javaMinVer) >= 0 && (!*search.javaMaxVer || strcmp(version, search.javaMaxVer) <= 0) @@ -384,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); @@ -476,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; } } @@ -503,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", @@ -613,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) { @@ -733,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; @@ -767,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}; @@ -789,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; } @@ -802,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)); } @@ -811,12 +964,12 @@ void createJreSearchError() { loadString(JRE_VERSION_ERR, error.msg); strcat(error.msg, " "); - strcat(error.msg, search.javaMinVer); + strcat(error.msg, search.originalJavaMinVer); if (*search.javaMaxVer) { strcat(error.msg, " - "); - strcat(error.msg, search.javaMaxVer); + strcat(error.msg, search.originalJavaMaxVer); } if (search.runtimeBits == USE_64_BIT_RUNTIME @@ -848,11 +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.javaMinVer); - loadString(JAVA_MAX_VER, search.javaMaxVer); + 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) { @@ -934,14 +1092,15 @@ void setMainClassAndClassPath(const char *exePath, const int pathLen) { char classPath[MAX_ARGS] = {0}; char expandedClassPath[MAX_ARGS] = {0}; - char mainClass[STR] = {0}; char jar[_MAX_PATH] = {0}; char fullFileName[_MAX_PATH] = {0}; const BOOL wrapper = loadBool(WRAPPER); loadString(JAR, jar); - if (loadString(MAIN_CLASS, mainClass)) + 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"); @@ -997,7 +1156,7 @@ void setMainClassAndClassPath(const char *exePath, const int pathLen) *(launcher.args + strlen(launcher.args) - 1) = 0; strcat(launcher.args, "\" "); - strcat(launcher.args, mainClass); + strcat(launcher.args, launcher.mainClass); } else if (wrapper) { @@ -1158,3 +1317,19 @@ BOOL execute(const BOOL wait, DWORD *dwExitCode) *dwExitCode = -1; return FALSE; } + +const char* getJavaHome() +{ + return search.foundJavaHome; +} + +const char* getMainClass() +{ + return launcher.mainClass; +} + +const char* getLauncherArgs() +{ + return launcher.args; +} + diff --git a/launch4j/head_src/head.h b/launch4j/head_src/head.h index c5da257..2d56a2d 100644 --- a/launch4j/head_src/head.h +++ b/launch4j/head_src/head.h @@ -28,10 +28,13 @@ THE SOFTWARE. */ +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0501 +#endif // _WIN32_WINNT + #ifndef _LAUNCH4J_HEAD__INCLUDED_ #define _LAUNCH4J_HEAD__INCLUDED_ -#define _WIN32_WINNT 0x0501 #define WIN32_LEAN_AND_MEAN // VC - Exclude rarely-used stuff from Windows headers // Windows Header Files: @@ -51,7 +54,9 @@ #include #define LAUNCH4j "Launch4j" -#define VERSION "3.7" +#define VERSION "3.12" + +#define JRE_VER_MAX_DIGITS_PER_PART 3 #define NO_JAVA_FOUND 0 #define FOUND_JRE 1 @@ -88,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); @@ -102,6 +108,7 @@ BOOL loadBool(const int resID); int loadInt(const int resID); BOOL regQueryValue(const char* regPath, unsigned char* buffer, unsigned long bufferLength); +void formatJavaVersion(char* version, const char* originalVersion); void regSearch(const char* keyName, const int searchType); BOOL isJavaHomeValid(const char* keyName, const int searchType); BOOL isLauncherPathValid(const char* path); @@ -132,5 +139,8 @@ void setCommandLineArgs(const char *lpCmdLine); int prepare(const char *lpCmdLine); void closeProcessHandles(); BOOL execute(const BOOL wait, DWORD *dwExitCode); +const char* getJavaHome(); +const char* getMainClass(); +const char* getLauncherArgs(); #endif // _LAUNCH4J_HEAD__INCLUDED_ diff --git a/launch4j/head_src/jniconsolehead_BETA/.gitignore b/launch4j/head_src/jniconsolehead_BETA/.gitignore new file mode 100644 index 0000000..1c252a6 --- /dev/null +++ b/launch4j/head_src/jniconsolehead_BETA/.gitignore @@ -0,0 +1,2 @@ +/jniconsolehead.exe +/jniconsolehead.layout diff --git a/launch4j/head_src/jniconsolehead_BETA/Makefile.win b/launch4j/head_src/jniconsolehead_BETA/Makefile.win new file mode 100644 index 0000000..b2357ac --- /dev/null +++ b/launch4j/head_src/jniconsolehead_BETA/Makefile.win @@ -0,0 +1,34 @@ +# Project: jniconsolehead +# Makefile created by Dev-C++ 5.7.1 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +OBJ = ../../head_jni_BETA/jniconsolehead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o +LINKOBJ = ../../head_jni_BETA/jniconsolehead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o +LIBS = -L"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib" -L"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/lib" -static-libstdc++ -static-libgcc -n -s +INCS = -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include/win32" +CXXINCS = -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include/c++" -I"C:/Program Files (x86)/Java/jdk 1.4/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include/win32" +BIN = jniconsolehead.exe +CXXFLAGS = $(CXXINCS) -Os +CFLAGS = $(INCS) -Os +RM = rm.exe -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) all-after + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CC) $(LINKOBJ) -o $(BIN) $(LIBS) + +../../head_jni_BETA/jniconsolehead.o: jniconsolehead.c + $(CC) -c jniconsolehead.c -o ../../head_jni_BETA/jniconsolehead.o $(CFLAGS) + +../../head_jni_BETA/head.o: ../head.c + $(CC) -c ../head.c -o ../../head_jni_BETA/head.o $(CFLAGS) + +../../head_jni_BETA/jnihead.o: ../jnihead.c + $(CC) -c ../jnihead.c -o ../../head_jni_BETA/jnihead.o $(CFLAGS) diff --git a/launch4j/head_src/jniconsolehead_BETA/jniconsolehead.c b/launch4j/head_src/jniconsolehead_BETA/jniconsolehead.c new file mode 100644 index 0000000..0e7f6dd --- /dev/null +++ b/launch4j/head_src/jniconsolehead_BETA/jniconsolehead.c @@ -0,0 +1,99 @@ +/* + Launch4j (http://launch4j.sourceforge.net/) + Cross-platform Java application wrapper for creating Windows native executables. + + Copyright (c) 2004, 2007 Grzegorz Kowal + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + Except as contained in this notice, the name(s) of the above copyright holders + shall not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include "../resource.h" +#include "../head.h" +#include "../jnihead.h" + +extern FILE* hLog; + +BOOL restartOnCrash = FALSE; + +int main(int argc, char* argv[]) +{ + setConsoleFlag(); + LPTSTR cmdLine = GetCommandLine(); + + if (*cmdLine == '"') + { + if (*(cmdLine = strchr(cmdLine + 1, '"') + 1)) + { + cmdLine++; + } + } + else if ((cmdLine = strchr(cmdLine, ' ')) != NULL) + { + cmdLine++; + } + else + { + cmdLine = ""; + } + + int result = prepare(cmdLine); + + if (result == ERROR_ALREADY_EXISTS) + { + char errMsg[BIG_STR] = {0}; + loadString(INSTANCE_ALREADY_EXISTS_MSG, errMsg); + msgBox(errMsg); + closeLogFile(); + return 2; + } + + if (result != TRUE) + { + signalError(); + return 1; + } + + restartOnCrash = loadBool(RESTART_ON_CRASH); + DWORD dwExitCode; + + do + { + dwExitCode = 0; + saveJvmOptions(getJavaHome(), getMainClass(), getLauncherArgs()); + + if (!executeVm(&dwExitCode)) + { + signalError(); + break; + } + + if (restartOnCrash && dwExitCode != 0) + { + debug("Exit code:\t%d, restarting the application!\n", dwExitCode); + } + } while (restartOnCrash && dwExitCode != 0); + + debug("Exit code:\t%d\n", dwExitCode); + closeLogFile(); + return (int) dwExitCode; +} diff --git a/launch4j/head_src/jniconsolehead_BETA/jniconsolehead.dev b/launch4j/head_src/jniconsolehead_BETA/jniconsolehead.dev new file mode 100644 index 0000000..0b585a5 --- /dev/null +++ b/launch4j/head_src/jniconsolehead_BETA/jniconsolehead.dev @@ -0,0 +1,112 @@ +[Project] +FileName=jniconsolehead.dev +Name=jniconsolehead +UnitCount=6 +Type=1 +Ver=2 +ObjFiles= +Includes="C:\Program Files (x86)\Java\jdk 1.4\include";"C:\Program Files (x86)\Java\jdk 1.4\include\win32" +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker=-n_@@_ +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput=..\..\head_jni_BETA +OverrideOutput=0 +OverrideOutputName=jniconsolehead.exe +HostApplication= +Folders= +CommandLine= +UseCustomMakefile=0 +CustomMakefile=Makefile.win +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=000000d000000000000001000 +LogOutput= +LogOutputEnabled=0 + +[Unit1] +FileName=jniconsolehead.c +CompileCpp=0 +Folder=jniconsolehead +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1.1.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 +SyncProduct=0 + +[Unit2] +FileName=..\resource.h +CompileCpp=0 +Folder=jniconsolehead +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\head.c +CompileCpp=0 +Folder=jniconsolehead +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit4] +FileName=..\head.h +CompileCpp=0 +Folder=jniconsolehead +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit5] +FileName=..\jnihead.h +Folder=jniconsolehead +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= +CompileCpp=0 + +[Unit6] +FileName=..\jnihead.c +CompileCpp=0 +Folder=jniconsolehead +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/launch4j/head_src/jniguihead_BETA/.gitignore b/launch4j/head_src/jniguihead_BETA/.gitignore new file mode 100644 index 0000000..033e91b --- /dev/null +++ b/launch4j/head_src/jniguihead_BETA/.gitignore @@ -0,0 +1,2 @@ +/jniguihead.exe +/jniguihead.layout diff --git a/launch4j/head_src/jniguihead_BETA/Makefile.win b/launch4j/head_src/jniguihead_BETA/Makefile.win new file mode 100644 index 0000000..8bdac72 --- /dev/null +++ b/launch4j/head_src/jniguihead_BETA/Makefile.win @@ -0,0 +1,34 @@ +# Project: jniguihead +# Makefile created by Dev-C++ 5.7.1 + +CPP = g++.exe +CC = gcc.exe +WINDRES = windres.exe +OBJ = ../../head_jni_BETA/jniguihead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o +LINKOBJ = ../../head_jni_BETA/jniguihead.o ../../head_jni_BETA/head.o ../../head_jni_BETA/jnihead.o +LIBS = -L"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib" -L"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/lib" -static-libstdc++ -static-libgcc -mwindows -n -s +INCS = -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include/win32" +CXXINCS = -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/mingw32/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include" -I"C:/Users/GMan/Dev-Cpp 5.7.1/MinGW32/lib/gcc/mingw32/4.8.1/include/c++" -I"C:/Program Files (x86)/Java/jdk 1.4/include" -I"C:/Program Files (x86)/Java/jdk 1.4/include/win32" +BIN = jniguihead.exe +CXXFLAGS = $(CXXINCS) -Os +CFLAGS = $(INCS) -Os +RM = rm.exe -f + +.PHONY: all all-before all-after clean clean-custom + +all: all-before $(BIN) all-after + +clean: clean-custom + ${RM} $(OBJ) $(BIN) + +$(BIN): $(OBJ) + $(CC) $(LINKOBJ) -o $(BIN) $(LIBS) + +../../head_jni_BETA/jniguihead.o: jniguihead.c + $(CC) -c jniguihead.c -o ../../head_jni_BETA/jniguihead.o $(CFLAGS) + +../../head_jni_BETA/head.o: ../head.c + $(CC) -c ../head.c -o ../../head_jni_BETA/head.o $(CFLAGS) + +../../head_jni_BETA/jnihead.o: ../jnihead.c + $(CC) -c ../jnihead.c -o ../../head_jni_BETA/jnihead.o $(CFLAGS) diff --git a/launch4j/head_src/jniguihead_BETA/jniguihead.c b/launch4j/head_src/jniguihead_BETA/jniguihead.c new file mode 100644 index 0000000..0259a27 --- /dev/null +++ b/launch4j/head_src/jniguihead_BETA/jniguihead.c @@ -0,0 +1,244 @@ +/* + Launch4j (http://launch4j.sourceforge.net/) + Cross-platform Java application wrapper for creating Windows native executables. + + Copyright (c) 2004, 2015 Grzegorz Kowal + Sylvain Mina (single instance patch) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + Except as contained in this notice, the name(s) of the above copyright holders + shall not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include "../resource.h" +#include "../head.h" +#include "../jnihead.h" +#include "jniguihead.h" + +extern FILE* hLog; +extern PROCESS_INFORMATION processInformation; + +HWND hWnd; +DWORD dwExitCode = 0; +BOOL stayAlive = FALSE; +BOOL splash = FALSE; +BOOL splashTimeoutErr; +BOOL waitForWindow; +BOOL restartOnCrash = FALSE; +int splashTimeout = DEFAULT_SPLASH_TIMEOUT; + +int APIENTRY WinMain(HINSTANCE hInstance, + HINSTANCE hPrevInstance, + LPSTR lpCmdLine, + int nCmdShow) +{ + int result = prepare(lpCmdLine); + + if (result == ERROR_ALREADY_EXISTS) + { + HWND handle = getInstanceWindow(); + ShowWindow(handle, SW_SHOW); + SetForegroundWindow(handle); + closeLogFile(); + return 2; + } + + if (result != TRUE) + { + signalError(); + return 1; + } + + splash = loadBool(SHOW_SPLASH) + && strstr(lpCmdLine, "--l4j-no-splash") == NULL; + restartOnCrash = loadBool(RESTART_ON_CRASH); + + // if we should restart on crash, we must also stay alive to check for crashes + stayAlive = restartOnCrash || + (loadBool(GUI_HEADER_STAYS_ALIVE) + && strstr(lpCmdLine, "--l4j-dont-wait") == NULL); + + if (splash || stayAlive) + { + hWnd = CreateWindowEx(WS_EX_TOOLWINDOW, "STATIC", "", + WS_POPUP | SS_BITMAP, + 0, 0, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL); + if (splash) + { + char timeout[10] = {0}; + if (loadString(SPLASH_TIMEOUT, timeout)) + { + splashTimeout = atoi(timeout); + if (splashTimeout <= 0 || splashTimeout > MAX_SPLASH_TIMEOUT) + { + splashTimeout = DEFAULT_SPLASH_TIMEOUT; + } + } + splashTimeoutErr = loadBool(SPLASH_TIMEOUT_ERR) + && strstr(lpCmdLine, "--l4j-no-splash-err") == NULL; + waitForWindow = loadBool(SPLASH_WAITS_FOR_WINDOW); + HANDLE hImage = LoadImage(hInstance, // handle of the instance containing the image + MAKEINTRESOURCE(SPLASH_BITMAP), // name or identifier of image + IMAGE_BITMAP, // type of image + 0, // desired width + 0, // desired height + LR_DEFAULTSIZE); + if (hImage == NULL) + { + signalError(); + return 1; + } + SendMessage(hWnd, STM_SETIMAGE, IMAGE_BITMAP, (LPARAM) hImage); + RECT rect; + GetWindowRect(hWnd, &rect); + int x = (GetSystemMetrics(SM_CXSCREEN) - (rect.right - rect.left)) / 2; + int y = (GetSystemMetrics(SM_CYSCREEN) - (rect.bottom - rect.top)) / 2; + SetWindowPos(hWnd, HWND_TOP, x, y, 0, 0, SWP_NOSIZE); + ShowWindow(hWnd, nCmdShow); + UpdateWindow (hWnd); + } + } + + do + { + if (splash || stayAlive) + { + if (!SetTimer (hWnd, ID_TIMER, 1000 /* 1s */, TimerProc)) + { + signalError(); + return 1; + } + } + + debug(getJavaHome()); + saveJvmOptions(getJavaHome(), getMainClass(), getLauncherArgs()); + + if (!executeVm(&dwExitCode)) + { + signalError(); + return 1; + } + + if (!(splash || stayAlive)) + { + debug("Exit code:\t0\n"); + closeProcessHandles(); + closeLogFile(); + return 0; + } + + MSG msg; + while (GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + if (restartOnCrash && dwExitCode != 0) + { + debug("Exit code:\t%d, restarting the application!\n", dwExitCode); + } + + closeProcessHandles(); + } while (restartOnCrash && dwExitCode != 0); + + debug("Exit code:\t%d\n", dwExitCode); + closeLogFile(); + return dwExitCode; +} + +HWND getInstanceWindow() +{ + char windowTitle[STR]; + char instWindowTitle[STR] = {0}; + if (loadString(INSTANCE_WINDOW_TITLE, instWindowTitle)) + { + HWND handle = FindWindowEx(NULL, NULL, NULL, NULL); + while (handle != NULL) + { + GetWindowText(handle, windowTitle, STR - 1); + if (strstr(windowTitle, instWindowTitle) != NULL) + { + return handle; + } + else + { + handle = FindWindowEx(NULL, handle, NULL, NULL); + } + } + } + return NULL; +} + +BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam) +{ + DWORD processId; + GetWindowThreadProcessId(hwnd, &processId); + if (processInformation.dwProcessId == processId) + { + LONG styles = GetWindowLong(hwnd, GWL_STYLE); + if ((styles & WS_VISIBLE) != 0) + { + splash = FALSE; + ShowWindow(hWnd, SW_HIDE); + return FALSE; + } + } + return TRUE; +} + +VOID CALLBACK TimerProc( + HWND hwnd, // handle of window for timer messages + UINT uMsg, // WM_TIMER message + UINT idEvent, // timer identifier + DWORD dwTime) // current system time +{ + if (splash) + { + if (splashTimeout == 0) + { + splash = FALSE; + ShowWindow(hWnd, SW_HIDE); + if (waitForWindow && splashTimeoutErr) + { + KillTimer(hwnd, ID_TIMER); + signalError(); + PostQuitMessage(0); + } + } + else + { + splashTimeout--; + if (waitForWindow) + { + EnumWindows(enumwndfn, 0); + } + } + } + + GetExitCodeProcess(processInformation.hProcess, &dwExitCode); + if (dwExitCode != STILL_ACTIVE + || !(splash || stayAlive)) + { + KillTimer(hWnd, ID_TIMER); + PostQuitMessage(0); + } +} diff --git a/launch4j/head_src/jniguihead_BETA/jniguihead.dev b/launch4j/head_src/jniguihead_BETA/jniguihead.dev new file mode 100644 index 0000000..a2667ed --- /dev/null +++ b/launch4j/head_src/jniguihead_BETA/jniguihead.dev @@ -0,0 +1,122 @@ +[Project] +FileName=jniguihead.dev +Name=jniguihead +UnitCount=7 +Type=0 +Ver=2 +ObjFiles= +Includes="C:\Program Files (x86)\Java\jdk 1.4\include";"C:\Program Files (x86)\Java\jdk 1.4\include\win32" +Libs= +PrivateResource= +ResourceIncludes= +MakeIncludes= +Compiler= +CppCompiler= +Linker=-n_@@_ +IsCpp=0 +Icon= +ExeOutput= +ObjectOutput=..\..\head_jni_BETA +OverrideOutput=0 +OverrideOutputName=jniguihead.exe +HostApplication= +Folders= +CommandLine= +UseCustomMakefile=0 +CustomMakefile=Makefile.win +IncludeVersionInfo=0 +SupportXPThemes=0 +CompilerSet=0 +CompilerSettings=000000d000000000000001000 +LogOutput= +LogOutputEnabled=0 + +[Unit1] +FileName=jniguihead.c +CompileCpp=0 +Folder=jniguihead_BETA +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c jniguihead.c -o ../../head_jni_BETA/jniguihead.o $(CFLAGS) + +[Unit2] +FileName=jniguihead.h +CompileCpp=0 +Folder=jniguihead_BETA +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[VersionInfo] +Major=0 +Minor=1 +Release=1 +Build=1 +LanguageID=1033 +CharsetID=1252 +CompanyName= +FileVersion=0.1.1.1 +FileDescription=Developed using the Dev-C++ IDE +InternalName= +LegalCopyright= +LegalTrademarks= +OriginalFilename= +ProductName= +ProductVersion= +AutoIncBuildNr=0 +SyncProduct=0 + +[Unit4] +FileName=..\head.h +CompileCpp=0 +Folder=jniguihead_BETA +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit6] +FileName=..\jnihead.c +CompileCpp=0 +Folder=jniguihead_BETA +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit3] +FileName=..\head.c +CompileCpp=0 +Folder=jniguihead_BETA +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd=$(CC) -c head.c -o ../../head/head.o $(CFLAGS) + +[Unit5] +FileName=..\resource.h +CompileCpp=0 +Folder=jniguihead_BETA +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + +[Unit7] +FileName=..\jnihead.h +CompileCpp=0 +Folder=jniguihead_BETA +Compile=1 +Link=1 +Priority=1000 +OverrideBuildCmd=0 +BuildCmd= + diff --git a/launch4j/head_src/jniguihead_BETA/jniguihead.h b/launch4j/head_src/jniguihead_BETA/jniguihead.h new file mode 100644 index 0000000..ebef396 --- /dev/null +++ b/launch4j/head_src/jniguihead_BETA/jniguihead.h @@ -0,0 +1,43 @@ +/* + Launch4j (http://launch4j.sourceforge.net/) + Cross-platform Java application wrapper for creating Windows native executables. + + Copyright (c) 2004, 2007 Grzegorz Kowal + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + Except as contained in this notice, the name(s) of the above copyright holders + shall not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#define ID_TIMER 1 +#define DEFAULT_SPLASH_TIMEOUT 60 /* 60 seconds */ +#define MAX_SPLASH_TIMEOUT 60 * 15 /* 15 minutes */ + +HWND getInstanceWindow(); + +BOOL CALLBACK enumwndfn(HWND hwnd, LPARAM lParam); + +VOID CALLBACK TimerProc( + HWND hwnd, // handle of window for timer messages + UINT uMsg, // WM_TIMER message + UINT idEvent, // timer identifier + DWORD dwTime // current system time +); diff --git a/launch4j/head_src/jnihead.c b/launch4j/head_src/jnihead.c new file mode 100644 index 0000000..e62dc03 --- /dev/null +++ b/launch4j/head_src/jnihead.c @@ -0,0 +1,284 @@ +/* + Launch4j (http://launch4j.sourceforge.net/) + Cross-platform Java application wrapper for creating Windows native executables. + + Copyright (c) 2007 Ryan Rusaw + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + Except as contained in this notice, the name(s) of the above copyright holders + shall not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include "jnihead.h" + +/* Java Invocation API stuff */ +typedef jint (JNICALL CreateJavaVM_t)(JavaVM **pvm, void **env, void *args); +JavaVM* g_pJavaVM = NULL; +JNIEnv* g_pJNIEnv = NULL; +JavaVMInitArgs g_sJavaVMInitArgs; +char g_rgcMnClsArgs[MAX_ARGS] = {0}; +char g_rgcMnCls[_MAX_PATH] = {0}; +char g_rgcCurrJrePth[_MAX_PATH] = {0}; +HINSTANCE g_hInstance; +const char* g_pcSep = " \t\f\r\n\v"; + +int getArgCount(const char* pcArgStr) +{ + const char *pCopy; + int iArgCnt= 0; + int bInWtSpc = 1; + for(pCopy = pcArgStr; *pCopy; pCopy++) + { + if (!isspace(*pCopy) && bInWtSpc) + { + iArgCnt++; + } + bInWtSpc = isspace(*pCopy); + } + return iArgCnt; +} + +void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOpts) +{ + strcpy(g_rgcCurrJrePth, jrePath); + strcpy(g_rgcMnCls, mainClass); + + char rgcOptCpy[MAX_ARGS] = {0}; + int iArgCnt = 0, iCurrArg = 0, iSkipArgCnt = 0; + char *pcCurrOpt; + char **prgcVmArgs = NULL; + strncpy(rgcOptCpy, pcOpts, MAX_ARGS - 1); + + + iArgCnt = getArgCount(rgcOptCpy); + if (iArgCnt > 0) + { + /* Allocate iArgCnt char pointers */ + prgcVmArgs = malloc(iArgCnt * sizeof(char *)); + for (pcCurrOpt = strtok(rgcOptCpy, g_pcSep); pcCurrOpt; pcCurrOpt = strtok(NULL, g_pcSep), iCurrArg++) + { + /* Use the allocated pointers to make an array of substrings */ + prgcVmArgs[iCurrArg] = pcCurrOpt; + } + /* 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++) + { + if ((strcmp(prgcVmArgs[iCurrArg], "-classpath") == 0) || + (strcmp(prgcVmArgs[iCurrArg], "-jar") == 0)) + { + iCurrArg++; + iSkipArgCnt++; + if (iCurrArg < iArgCnt) + { + int iOffset = *prgcVmArgs[iCurrArg] == '"' ? 1 : 0; + char rgcTmp[MAX_ARGS] = {0}; + /* Remove leading and trailing "'s */\ + strncpy(rgcTmp, prgcVmArgs[iCurrArg] + iOffset, + strlen(prgcVmArgs[iCurrArg]) - iOffset); + if (rgcTmp[strlen(rgcTmp)-1] == '"') + 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 (!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(rgcClsPth,";"); + strcat(rgcClsPth,rgcTmp); + } + + } + } + else + { + g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString + = malloc(strlen(prgcVmArgs[iCurrArg]) + 1); + strcpy(g_sJavaVMInitArgs.options[iCurrArg - iSkipArgCnt].optionString, + prgcVmArgs[iCurrArg]); + } + } + g_sJavaVMInitArgs.nOptions = iArgCnt - iSkipArgCnt; + /* Free the malloc'd memory, we dont want to leak */ + free(prgcVmArgs); + } +} + +JNIEnv* createVm() +{ + int iRetVal; + CreateJavaVM_t *pfnCreateJavaVM; + char rgcLibPth[_MAX_PATH + 18]; + // sprintf(rgcLibPth, "%s\\bin\\client\\jvm.dll", g_rgcCurrJrePth); // TODO - could be client or server + sprintf(rgcLibPth, "%s\\bin\\client\\jvm.dll", g_rgcCurrJrePth); + + /* Get a handle to the jvm dll */ + if ((g_hInstance = LoadLibrary(rgcLibPth)) == NULL) + { + return NULL; + } + + /* Get the CreateJavaVM() function */ + pfnCreateJavaVM = (CreateJavaVM_t *)GetProcAddress(g_hInstance, "JNI_CreateJavaVM"); + + if (pfnCreateJavaVM == NULL) + { + return NULL; + } + + g_sJavaVMInitArgs.version = JNI_VERSION_1_2; + g_sJavaVMInitArgs.ignoreUnrecognized = JNI_TRUE; + /* Start the VM */ + iRetVal = pfnCreateJavaVM(&g_pJavaVM, (void **)&g_pJNIEnv, &g_sJavaVMInitArgs); + + if (iRetVal != 0) + { + return NULL; + } + + return g_pJNIEnv; +} + +int invokeMainClass(JNIEnv* psJNIEnv) +{ + jclass jcMnCls; + jmethodID jmMnMthd; + jobjectArray joAppArgs; + jstring jsAppArg; + jthrowable jtExcptn; + char *pcCurrArg; + int iArgCnt= 0, iOption = -1; + char rgcMnClsCpy[MAX_ARGS] = {0}; + + /* Ensure Java JNI Env is set up */ + if(psJNIEnv == NULL) + { + return -1; + } + /* We need a class name */ + if (g_rgcMnCls[0] == '\0') + { + return -1; + } + else + { + /* Replace . with / in fully qualified class name */ + char *pClsNm; + for(pClsNm = g_rgcMnCls; *pClsNm; pClsNm++) + { + if(*pClsNm == '.') + *pClsNm = '/'; + } + } + /* Find the class */ + jcMnCls = (*psJNIEnv)->FindClass(psJNIEnv, g_rgcMnCls); + jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv); + if (jtExcptn != NULL) + { + (*psJNIEnv)->ExceptionDescribe(psJNIEnv); + return -1; + } + if (jcMnCls == NULL) + { + return -1; + } + /* Get the static main method */ + jmMnMthd = (*psJNIEnv)->GetStaticMethodID(psJNIEnv, jcMnCls, "main", "([Ljava/lang/String;)V"); + jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv); + if (jtExcptn != NULL) + { + (*psJNIEnv)->ExceptionDescribe(psJNIEnv); + } + if (jmMnMthd == NULL) + { + return -1; + } + /* Build the String[] array if we need one */ + strncpy(rgcMnClsCpy, g_rgcMnClsArgs, MAX_ARGS); + iArgCnt = getArgCount(rgcMnClsCpy); + joAppArgs = (jobjectArray)(*psJNIEnv)->NewObjectArray(psJNIEnv, iArgCnt, + (*psJNIEnv)->FindClass(psJNIEnv, "java/lang/String"), NULL); + jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv); + if (jtExcptn != NULL) + { + (*psJNIEnv)->ExceptionDescribe(psJNIEnv); + return -1; + } + for (pcCurrArg = strtok(rgcMnClsCpy, g_pcSep); pcCurrArg; pcCurrArg = strtok(NULL, g_pcSep)) + { + iOption++; + jsAppArg = (*psJNIEnv)->NewStringUTF(psJNIEnv, pcCurrArg); + (*psJNIEnv)->SetObjectArrayElement(psJNIEnv, joAppArgs, iOption, jsAppArg); + jtExcptn = (*psJNIEnv)->ExceptionOccurred(psJNIEnv); + if(jtExcptn != NULL) + { + (*psJNIEnv)->ExceptionDescribe(psJNIEnv); + return -1; + } + } + /* Execute the class */ + (*psJNIEnv)->CallStaticVoidMethod(psJNIEnv, jcMnCls, jmMnMthd, joAppArgs); + return 0; +} + +void cleanupVm() +{ + /* Destroy the VM */ + (*g_pJavaVM)->DestroyJavaVM(g_pJavaVM); +} + +BOOL executeVm(DWORD *dwExitCode) +{ + BOOL result = TRUE; + *dwExitCode = -1; + + int iIdx; + /* Use Invocation API */ + if (createVm()) + { + *dwExitCode = invokeMainClass(g_pJNIEnv); + cleanupVm(); + } + else + { + result = FALSE; + } + + /* Free the allocated memory */ + for (iIdx = 0; iIdx < g_sJavaVMInitArgs.nOptions; iIdx++) + { + free(g_sJavaVMInitArgs.options[iIdx].optionString); + } + free(g_sJavaVMInitArgs.options); + + return result; +} + diff --git a/launch4j/head_src/jnihead.h b/launch4j/head_src/jnihead.h new file mode 100644 index 0000000..5d3a2d3 --- /dev/null +++ b/launch4j/head_src/jnihead.h @@ -0,0 +1,41 @@ +/* + Launch4j (http://launch4j.sourceforge.net/) + Cross-platform Java application wrapper for creating Windows native executables. + + Copyright (c) 2007 Ryan Rusaw + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + Except as contained in this notice, the name(s) of the above copyright holders + shall not be used in advertising or otherwise to promote the sale, use or other + dealings in this Software without prior written authorization. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include +#include + +#include "head.h" + +int getArgCount(const char* pcArgStr); +void saveJvmOptions(const char *jrePath, const char *mainClass, const char *pcOpts); +JNIEnv* createVm(); +int invokeMainClass(JNIEnv* psJNIEnv); +void cleanupVm(); +BOOL executeVm(DWORD *dwExitCode); + diff --git a/launch4j/launch4j.jar b/launch4j/launch4j.jar index eadd38a..722e53d 100644 --- a/launch4j/launch4j.jar +++ b/launch4j/launch4j.jar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:32a4828d66bb793547338cba06f7fcae903f2c27e261abffa295752cd0b8e804 -size 187752 +oid sha256:2a69034740a0d8973cd65750cd690226146b217f402489d00111d5f2e7610d17 +size 199603 diff --git a/launch4j/lib/commons-logging.jar b/launch4j/lib/commons-logging.jar index 46de424..13ec090 100644 --- a/launch4j/lib/commons-logging.jar +++ b/launch4j/lib/commons-logging.jar @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e94af49749384c11f5aa50e8d0f5fe679be771295b52030338d32843c980351e -size 38015 +oid sha256:daddea1ea0be0f56978ab3006b8ac92834afeefbd9b7e4e6316fca57df0fa636 +size 61829 diff --git a/launch4j/maven/.classpath b/launch4j/maven/.classpath new file mode 100644 index 0000000..9f62fb5 --- /dev/null +++ b/launch4j/maven/.classpath @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/launch4j/maven/.project b/launch4j/maven/.project new file mode 100644 index 0000000..f64debb --- /dev/null +++ b/launch4j/maven/.project @@ -0,0 +1,23 @@ + + + launch4j + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/launch4j/maven/.settings/org.eclipse.m2e.core.prefs b/launch4j/maven/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..14b697b --- /dev/null +++ b/launch4j/maven/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/launch4j/maven/assembly/assemble-dist.xml b/launch4j/maven/assembly/assemble-dist.xml new file mode 100644 index 0000000..20f2c17 --- /dev/null +++ b/launch4j/maven/assembly/assemble-dist.xml @@ -0,0 +1,14 @@ + + distribution-libs + + dir + + false + + + + false + + + \ No newline at end of file diff --git a/launch4j/maven/assembly/assemble-linux.xml b/launch4j/maven/assembly/assemble-linux.xml new file mode 100644 index 0000000..94d4cf9 --- /dev/null +++ b/launch4j/maven/assembly/assemble-linux.xml @@ -0,0 +1,53 @@ + + + + workdir-linux + + jar + + false + + + bin/bin-linux + ${finalName}-workdir-linux/bin + + + ${finalName}-workdir-linux + + w32api/**/* + w32api_jni/**/* + head/**/* + head_jni_BETA/**/* + + + + diff --git a/launch4j/maven/assembly/assemble-linux64.xml b/launch4j/maven/assembly/assemble-linux64.xml new file mode 100644 index 0000000..d116be7 --- /dev/null +++ b/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/launch4j/maven/assembly/assemble-mac.xml b/launch4j/maven/assembly/assemble-mac.xml new file mode 100644 index 0000000..e813f72 --- /dev/null +++ b/launch4j/maven/assembly/assemble-mac.xml @@ -0,0 +1,53 @@ + + + + workdir-mac + + jar + + false + + + bin/bin-macosx-x86 + ${finalName}-workdir-mac/bin + + + ${finalName}-workdir-mac + + w32api/**/* + w32api_jni/**/* + head/**/* + head_jni_BETA/**/* + + + + diff --git a/launch4j/maven/assembly/assemble-win32.xml b/launch4j/maven/assembly/assemble-win32.xml new file mode 100644 index 0000000..4680f89 --- /dev/null +++ b/launch4j/maven/assembly/assemble-win32.xml @@ -0,0 +1,53 @@ + + + + workdir-win32 + + jar + + false + + + bin/bin-win32 + ${finalName}-workdir-win32/bin + + + ${finalName}-workdir-win32 + + w32api/**/* + w32api_jni/**/* + head/**/* + head_jni_BETA/**/* + + + + diff --git a/launch4j/maven/assembly/src.xml b/launch4j/maven/assembly/src.xml new file mode 100644 index 0000000..c930835 --- /dev/null +++ b/launch4j/maven/assembly/src.xml @@ -0,0 +1,55 @@ + + + + src + + tar.gz + zip + + + + + README* + LICENSE* + NOTICE* + TODO + pom.xml + + + + src + + **/.*.swp + + + + diff --git a/launch4j/maven/maven-readme.txt b/launch4j/maven/maven-readme.txt new file mode 100644 index 0000000..c977ad8 --- /dev/null +++ b/launch4j/maven/maven-readme.txt @@ -0,0 +1,8 @@ +Run once the Ant target switch-to-maven, it will reconfigure the project to use maven. + +*** Creation of Distribution Release *** +Windows: mvn -P dist,win32 clean package + +Linux: mvn -P dist,linux clean package + +MacOsX: mvn -P dist,macosx-x86 clean package diff --git a/launch4j/maven/pom.xml b/launch4j/maven/pom.xml new file mode 100644 index 0000000..bca0543 --- /dev/null +++ b/launch4j/maven/pom.xml @@ -0,0 +1,512 @@ + + 4.0.0 + net.sf.launch4j + launch4j + ${launch4j.version} + Launch4j + Cross-platform Java executable wrapper for creating lightweight Windows native EXEs. Provides advanced JRE search, application startup configuration and better user experience. + http://sourceforge.net/projects/launch4j/ + + + + BSD 3-Clause License + http://opensource.org/licenses/BSD-3-Clause + Launch4j is licensed under the BSD 3-Clause License. + + + MIT License + http://www.opensource.org/licenses/mit-license.php + Launch4j code (head) which is attached to the wrapped jars is licensed under the MIT License. + + + + + + Grzegorz Kowal + http://sourceforge.net/u/grzegok/profile/ + + + + + scm:git:http://git.code.sf.net/p/launch4j/git + scm:git:http://git.code.sf.net/p/launch4j/git + http://sourceforge.net/p/launch4j/git/ci/master/tree/ + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + + + UTF-8 + ${launch4j.version}.0.0 + ${launch4j.version} + + + + + commons-beanutils + commons-beanutils + + + commons-collections + commons-collections + + + 1.7.0 + + + commons-logging + commons-logging + 1.2 + + + net.java.abeille + abeille + 3.0 + + + colt + colt + + + + com.springsource.org.apache.batik.ext.awt + + org.apache.batik + + + + com.springsource.org.apache.batik.util + + org.apache.batik + + + dom4j + dom4j + + + dsol-xml + dsol + + + javahelp + javax.help + + + jfreechart + jfree + + + jcommon + jfree + + + mahout-collections + org.apache.mahout + + + optimization + com.github.rwl + + + + + foxtrot + foxtrot + 2.0 + + + com.jgoodies + jgoodies-common + 1.7.0 + + + com.jgoodies + forms + 1.2.1 + + + com.jgoodies + looks + 2.2.2 + + + com.thoughtworks.xstream + xstream + 1.4.8 + + + org.apache.ant + ant + 1.8.2 + + + + + + src + + + src + + **/*.java + + + + + + maven-compiler-plugin + 3.1 + + 1.6 + 1.6 + + + + com.github.taxone.plugins + classpath-maven-plugin + 1.0.0 + + + set-classpath-property + prepare-package + + setClassPath + + + lib/ + + + + + + org.apache.maven.plugins + maven-jar-plugin + 2.5 + + + default-jar + package + + jar + + + + + net.sf.launch4j.Main + + + . ${taxone.classpath.propertyName} + + + + + + core-jar + package + + jar + + + ${project.build.finalName} + + net/sf/launch4j/form/ + net/sf/launch4j/formimpl + + core + + + + + + maven-assembly-plugin + 2.4.1 + + + assemble-workdir + package + + attached + + + + assembly/assemble-linux.xml + assembly/assemble-linux64.xml + assembly/assemble-win32.xml + assembly/assemble-mac.xml + + + + + assemble-distrib + package + + single + + + lib + ${basedir} + false + + assembly/assemble-dist.xml + + + + + + + maven-resources-plugin + 2.6 + + + copy-resources + package + + copy-resources + + + ${basedir} + + + target + + ${project.build.finalName}.jar + + + + + + + + + maven-clean-plugin + 2.6 + + + + ${basedir} + + ${project.build.finalName}.jar + + + + + + + + + + + full-release + + + + org.apache.maven.plugins + maven-source-plugin + 2.3 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + + sign + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.2 + true + + ossrh + https://oss.sonatype.org/ + + false + + + + + + + + + macosx-x86 + + bin-macosx-x86 + + + + + linux + + bin-linux + + + + + win32 + + bin-win32 + + + + + + com.akathist.maven.plugins.launch4j + launch4j-maven-plugin + 1.6 + + + launch4j + package + + launch4j + + + gui + true + ${project.build.finalName}.jar + launch4j.exe + launch4j + . + false + + + 1.6.0 + + + ${versionNumber} + ${version} + ${versionNumber} + ${version} + Cross-platform Java application wrapper + Copyright (C) 2004, 2017 Grzegorz Kowal + launch4j + http://launch4j.sourceforge.net/ + GUI launcher + launch4j.exe + + + + + + + + + + + dist + + + + + maven-clean-plugin + 2.6 + + + + ${basedir}/bin + + * + + + COPYING + + + + ${basedir} + + launch4j.exe + + + + ${basedir} + + lib/ + + + + + + + + maven-resources-plugin + 2.6 + + + copy-binutils + prepare-package + + copy-resources + + + ${basedir}/bin + + + ${basedir}/bin/${bin.dir} + + + + + + + + + maven-antrun-plugin + 1.7 + + + package + + + + + + + + + run + + + + + + + + + + + + \ No newline at end of file diff --git a/launch4j/sign4j/sign4j.c b/launch4j/sign4j/sign4j.c index 31b3142..4918011 100644 --- a/launch4j/sign4j/sign4j.c +++ b/launch4j/sign4j/sign4j.c @@ -33,8 +33,13 @@ #include #include #include +#ifdef _WIN32 #include #include +#else +#include +#include +#endif #include #include @@ -45,6 +50,14 @@ #define TEST_FILE_NAME "sign4j_temporary.exe" #define SIGN4J_VERSION "3.0" +#ifndef _WIN32 +#define O_BINARY 0 +#define _O_SHORT_LIVED 0 +#define _S_IREAD S_IREAD +#define _S_IWRITE S_IWRITE +#define stricmp strcasecmp +#endif + typedef unsigned char byte; char command[4096]; @@ -127,7 +140,12 @@ int main (int argc, char* argv[]) trg = outf; close (fd); +#ifdef _WIN32 strcpy (command, "\" "); +#else + strcpy (command, ""); +#endif + for (i = j; i < argc; i++) { p = (argv[i] == outf ? trg : argv[i]); @@ -139,9 +157,18 @@ int main (int argc, char* argv[]) strcat (command, "\""); strcat (command, " "); } + +#ifdef _WIN32 strcat (command, "\""); +#endif + if (! vrb) +#ifdef _WIN32 strcat (command, " > NUL"); +#else + strcat (command, " > /dev/null"); +#endif + system (command); if ((td = open (trg, O_RDONLY | O_BINARY)) < 0) @@ -168,7 +195,12 @@ int main (int argc, char* argv[]) printf ("You don't need sign4j to sign this file\n"); } +#ifdef _WIN32 strcpy (command, "\" "); +#else + strcpy (command, ""); +#endif + for (i = j; i < argc; i++) { p = argv[i]; @@ -180,7 +212,11 @@ int main (int argc, char* argv[]) strcat (command, "\""); strcat (command, " "); } + +#ifdef _WIN32 strcat (command, "\""); +#endif + return system (command); } diff --git a/launch4j/src/LICENSE.txt b/launch4j/src/LICENSE.txt new file mode 100644 index 0000000..38af528 --- /dev/null +++ b/launch4j/src/LICENSE.txt @@ -0,0 +1,30 @@ +Launch4j (http://launch4j.sourceforge.net/) +Cross-platform Java application wrapper for creating Windows native executables. + +Copyright (c) 2004, 2017 Grzegorz Kowal +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED +AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/launch4j/src/launch4j.properties b/launch4j/src/launch4j.properties index 71b5332..a14697f 100644 --- a/launch4j/src/launch4j.properties +++ b/launch4j/src/launch4j.properties @@ -1,2 +1,2 @@ -versionNumber=3.7.0.0 -version=3.7 +versionNumber=3.12.0.0 +version=3.12 diff --git a/launch4j/src/net/sf/launch4j/Builder.java b/launch4j/src/net/sf/launch4j/Builder.java index 4b6452f..644b7d6 100644 --- a/launch4j/src/net/sf/launch4j/Builder.java +++ b/launch4j/src/net/sf/launch4j/Builder.java @@ -82,6 +82,10 @@ public class Builder { FileOutputStream os = null; final RcBuilder rcb = new RcBuilder(); try { + if (c.isJniApplication()) { + _log.append("WARNING: Some features are not implemented in JNI headers, see documentation."); + } + rc = rcb.build(c); ro = Util.createTempFile("o"); outfile = ConfigPersister.getInstance().getOutputFile(); @@ -102,8 +106,7 @@ public class Builder { .add("--dynamicbase") .add("--nxcompat") .add("--no-seh") - .add((c.getHeaderType().equals(Config.GUI_HEADER)) - ? "--subsystem windows" : "--subsystem console") + .add(c.isGuiApplication() ? "--subsystem windows" : "--subsystem console") .add("-s") // strip symbols .addFiles(c.getHeaderObjects()) .addAbsFile(ro) diff --git a/launch4j/src/net/sf/launch4j/Main.java b/launch4j/src/net/sf/launch4j/Main.java index 1c1048c..820f4be 100644 --- a/launch4j/src/net/sf/launch4j/Main.java +++ b/launch4j/src/net/sf/launch4j/Main.java @@ -68,6 +68,7 @@ public class Main { } } catch (Exception e) { Log.getConsoleLog().append(e.getMessage()); + System.exit(1); } } @@ -85,7 +86,7 @@ public class Main { " (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/launch4j/src/net/sf/launch4j/RcBuilder.java b/launch4j/src/net/sf/launch4j/RcBuilder.java index ccd942d..45f2339 100644 --- a/launch4j/src/net/sf/launch4j/RcBuilder.java +++ b/launch4j/src/net/sf/launch4j/RcBuilder.java @@ -44,6 +44,7 @@ import java.io.IOException; import java.io.OutputStreamWriter; import java.util.List; +import net.sf.launch4j.config.CharsetID; import net.sf.launch4j.config.Config; import net.sf.launch4j.config.ConfigPersister; import net.sf.launch4j.config.Jre; @@ -111,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(); } @@ -176,13 +177,19 @@ public class RcBuilder { } private void writeResourceFile(File file) throws IOException { + FileOutputStream os = null; + OutputStreamWriter osw = null; BufferedWriter w = null; try { - w = new BufferedWriter(new FileWriter(file)); + os = new FileOutputStream(file); + osw = new OutputStreamWriter(os, "ISO-8859-1"); + w = new BufferedWriter(osw); w.write(_sb.toString()); } finally { Util.close(w); + Util.close(osw); + Util.close(os); } } @@ -225,7 +232,9 @@ public class RcBuilder { "{\n" + " BLOCK \"StringFileInfo\"\n" + " {\n" + - " BLOCK \"040904E4\"\n" + // English + " BLOCK \""); + _sb.append(String.format("%04X%04X", v.getLanguage().getId(), CharsetID.MULTILINGUAL.getId())); + _sb.append("\"\n" + " {\n"); addVerBlockValue("CompanyName", v.getCompanyName()); @@ -233,10 +242,13 @@ public class RcBuilder { addVerBlockValue("FileVersion", v.getTxtFileVersion()); addVerBlockValue("InternalName", v.getInternalName()); addVerBlockValue("LegalCopyright", v.getCopyright()); + addVerBlockValue("LegalTrademarks", v.getTrademarks()); addVerBlockValue("OriginalFilename", v.getOriginalFilename()); addVerBlockValue("ProductName", v.getProductName()); addVerBlockValue("ProductVersion", v.getTxtProductVersion()); - _sb.append(" }\n }\nBLOCK \"VarFileInfo\"\n{\nVALUE \"Translation\", 0x0409, 0x04E4\n}\n}"); + _sb.append(" }\n }\nBLOCK \"VarFileInfo\"\n{\nVALUE \"Translation\", "); + _sb.append(String.format("0x%04X, 0x%04X", v.getLanguage().getId(), CharsetID.MULTILINGUAL.getId())); + _sb.append("\n}\n}"); } private void addJre(Jre jre) { diff --git a/launch4j/src/net/sf/launch4j/config/CharsetID.java b/launch4j/src/net/sf/launch4j/config/CharsetID.java new file mode 100644 index 0000000..40bd8d2 --- /dev/null +++ b/launch4j/src/net/sf/launch4j/config/CharsetID.java @@ -0,0 +1,110 @@ +/* + Launch4j (http://launch4j.sourceforge.net/) + Cross-platform Java application wrapper for creating Windows native executables. + + Copyright (c) 2015 Sebastian Bögl + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package net.sf.launch4j.config; + +import java.util.Arrays; +/** + * @see VERSIONINFO resource + * @see VarFileInfo BLOCK + */ +public enum CharsetID implements Describable { + /** 0x0000 */ + ASCII(0, Messages.getString("Charset.ascii")), + /** 0x04E8 */ + ARABIC(1256, Messages.getString("Language.arabic")), + /** 0x04E3 */ + CYRILLIC(1251, Messages.getString("Charset.cyrillic")), + /** 0x04E5 */ + GREEK(1253, Messages.getString("Language.greek")), + /** 0x04E7 */ + HEBREW(1255, Messages.getString("Language.hebrew")), + /** 0x03A4 */ + SHIFT_JIS(932, Messages.getString("Charset.shift.jis")), + /** 0x03B5 */ + SHIFT_KSC(949, Messages.getString("Charset.shift.ksc")), + /** 0x04E2 */ + LATIN2(1250, Messages.getString("Charset.latin2")), + /** 0x04E4 */ + MULTILINGUAL(1252, Messages.getString("Charset.multilingual")), + /** 0x0B63 */ + BIG5(950, Messages.getString("Charset.big5")), + /** 0x04E6 */ + TURKISH(1254, Messages.getString("Language.turkish")), + /** 0x04B0 */ + UNICODE(1200, Messages.getString("Charset.unicode")), + ; + + private static final CharsetID[] VALUES = CharsetID.values(); + + static { + Arrays.sort(VALUES, new DescribableComparator()); + } + + private final int id; + private final String description; + + CharsetID(int id, String description) { + this.id = id; + this.description = description; + } + + public int getId() { + return id; + } + + @Override + public String toString() { + return description; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public int getIndex() { + for (int i = 0; i < VALUES.length; i++) { + if (VALUES[i] == this) { + return i; + } + } + // should never happen + return -1; + } + + public static CharsetID[] sortedValues() { + return VALUES; + } +} diff --git a/launch4j/src/net/sf/launch4j/config/ClassPath.java b/launch4j/src/net/sf/launch4j/config/ClassPath.java index 3b64079..885d07f 100644 --- a/launch4j/src/net/sf/launch4j/config/ClassPath.java +++ b/launch4j/src/net/sf/launch4j/config/ClassPath.java @@ -53,7 +53,7 @@ public class ClassPath implements IValidatable { Messages.getString("ClassPath.mainClass")); Validator.checkOptStrings(paths, Validator.MAX_PATH, - Validator.MAX_BIG_STR, + Validator.MAX_ARGS, "paths", Messages.getString("ClassPath.path")); } diff --git a/launch4j/src/net/sf/launch4j/config/Config.java b/launch4j/src/net/sf/launch4j/config/Config.java index c322831..a9671c2 100644 --- a/launch4j/src/net/sf/launch4j/config/Config.java +++ b/launch4j/src/net/sf/launch4j/config/Config.java @@ -63,9 +63,13 @@ public class Config implements IValidatable { public static final String GUI_HEADER = "gui"; public static final String CONSOLE_HEADER = "console"; + public static final String JNI_GUI_HEADER_32 = "jniGui32"; + public static final String JNI_CONSOLE_HEADER_32 = "jniConsole32"; private static final String[] HEADER_TYPES = new String[] { GUI_HEADER, - CONSOLE_HEADER }; + CONSOLE_HEADER, + JNI_GUI_HEADER_32, + JNI_CONSOLE_HEADER_32 }; private static final String[] PRIORITY_CLASS_NAMES = new String[] { "normal", "idle", @@ -119,7 +123,7 @@ public class Config implements IValidatable { if (!Validator.isEmpty(chdir)) { Validator.checkRelativeWinPath(chdir, "chdir", Messages.getString("Config.chdir.relative")); - Validator.checkFalse(chdir.toLowerCase().equals("true") + Validator.checkFalse(chdir.toLowerCase().equals("true") || chdir.toLowerCase().equals("false"), "chdir", Messages.getString("Config.chdir.path")); } @@ -135,7 +139,7 @@ public class Config implements IValidatable { "supportUrl", Messages.getString("Config.support.url")); Validator.checkIn(getHeaderType(), HEADER_TYPES, "headerType", Messages.getString("Config.header.type")); - Validator.checkFalse(getHeaderType().equals(CONSOLE_HEADER) && splash != null, + Validator.checkFalse(!isGuiApplication() && splash != null, "headerType", Messages.getString("Config.splash.not.impl.by.console.hdr")); Validator.checkOptStrings(variables, @@ -147,9 +151,31 @@ public class Config implements IValidatable { Messages.getString("Config.variables.err")); Validator.checkIn(getPriority(), PRIORITY_CLASS_NAMES, "priority", Messages.getString("Config.priority")); + checkJniInvariants(); jre.checkInvariants(); } + private void checkJniInvariants() { + // TODO: Remove once JNI is fully implemented. + if (isJniApplication()) { + Validator.checkTrue(".".equals(chdir), "chdir", + "Only '.' is allowed in change directory."); + Validator.checkTrue(Validator.isEmpty(cmdLine), "cmdLine", + "Constant command line arguments not supported."); + Validator.checkFalse(stayAlive, "stayAlive", + "Stay alive option is not used in JNI, this is the default behavior."); + Validator.checkFalse(restartOnCrash, "restartOnCrash", + "Restart on crash not supported."); + Validator.checkIn(getPriority(), new String[] { "normal" }, "priority", + "Process priority is not supported,"); + Validator.checkNotNull(classPath, "classpath", "classpath"); + Validator.checkFalse(jre.getBundledJre64Bit(), "jre.bundledJre64Bit", + "64-bit bundled JRE not supported."); + Validator.checkTrue(Jre.RUNTIME_BITS_32.equals(jre.getRuntimeBits()), "jre.runtimeBits", + "64-bit JRE not supported."); + } + } + public void validate() { checkInvariants(); if (classPath != null) { @@ -189,10 +215,19 @@ public class Config implements IValidatable { public void setErrTitle(String errTitle) { this.errTitle = errTitle; } + + public boolean isGuiApplication() { + return GUI_HEADER.equals(headerType) || JNI_GUI_HEADER_32.equals(headerType); + } + + public boolean isJniApplication() { + return JNI_GUI_HEADER_32.equals(headerType) + || JNI_CONSOLE_HEADER_32.equals(headerType); + } /** launch4j header file. */ public String getHeaderType() { - return headerType.toLowerCase(); + return headerType; } public void setHeaderType(String headerType) { @@ -215,9 +250,7 @@ public class Config implements IValidatable { public List getHeaderObjects() { return isCustomHeaderObjects() ? headerObjects - : getHeaderType().equals(GUI_HEADER) - ? LdDefaults.GUI_HEADER_OBJECTS - : LdDefaults.CONSOLE_HEADER_OBJECTS; + : LdDefaults.getHeaderObjects(getHeaderTypeIndex()); } public void setHeaderObjects(List headerObjects) { @@ -229,7 +262,7 @@ public class Config implements IValidatable { } public List getLibs() { - return isCustomLibs() ? libs : LdDefaults.LIBS; + return isCustomLibs() ? libs : LdDefaults.getLibs(headerType); } public void setLibs(List libs) { diff --git a/launch4j/src/net/sf/launch4j/config/Describable.java b/launch4j/src/net/sf/launch4j/config/Describable.java new file mode 100644 index 0000000..f98a7a5 --- /dev/null +++ b/launch4j/src/net/sf/launch4j/config/Describable.java @@ -0,0 +1,18 @@ +package net.sf.launch4j.config; + +import java.util.Comparator; + +public interface Describable { + + String getDescription(); + + int getIndex(); + + class DescribableComparator implements Comparator { + + @Override + public int compare(Describable o1, Describable o2) { + return o1.getDescription().compareTo(o2.getDescription()); + } + } +} diff --git a/launch4j/src/net/sf/launch4j/config/Jre.java b/launch4j/src/net/sf/launch4j/config/Jre.java index ceb2801..cd91661 100644 --- a/launch4j/src/net/sf/launch4j/config/Jre.java +++ b/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 class Jre implements IValidatable { 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 class Jre implements IValidatable { 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/launch4j/src/net/sf/launch4j/config/JreVersion.java b/launch4j/src/net/sf/launch4j/config/JreVersion.java new file mode 100644 index 0000000..185257e --- /dev/null +++ b/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/launch4j/src/net/sf/launch4j/config/LanguageID.java b/launch4j/src/net/sf/launch4j/config/LanguageID.java new file mode 100644 index 0000000..9648a48 --- /dev/null +++ b/launch4j/src/net/sf/launch4j/config/LanguageID.java @@ -0,0 +1,132 @@ +/* + Launch4j (http://launch4j.sourceforge.net/) + Cross-platform Java application wrapper for creating Windows native executables. + + Copyright (c) 2015 Sebastian Bögl + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software without + specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +package net.sf.launch4j.config; + +import java.util.Arrays; + +/** + * @see VERSIONINFO resource + * @see VarFileInfo BLOCK + */ +public enum LanguageID implements Describable { + ALBANIAN(0x041C, Messages.getString("Language.albanian")), + ARABIC(0x0401, Messages.getString("Language.arabic")), + BAHASA(0x0421, Messages.getString("Language.bahasa")), + DUTCH_BELGIAN(0x0813, Messages.getString("Language.belgian.dutch")), + FRENCH_BELGIAN(0x080C, Messages.getString("Language.belgian.french")), + BULGARIAN(0x0402, Messages.getString("Language.bulgarian")), + FRENCH_CANADIAN(0x0C0C, Messages.getString("Language.canadian.french")), + CASTILIAN_SPANISH(0x040A, Messages.getString("Language.spanish.castilian")), + CATALAN(0x0403, Messages.getString("Language.catalan")), + CROATO_SERBIAN_LATIN(0x041A, Messages.getString("Language.croato.serbian.latin")), + CZECH(0x0405, Messages.getString("Language.czech")), + DANISH(0x0406, Messages.getString("Language.danish")), + DUTCH(0x0413, Messages.getString("Language.dutch")), + ENGLISH_UK(0x0809, Messages.getString("Language.english.uk")), + ENGLISH_US(0x0409, Messages.getString("Language.english.us")), + FINNISH(0x040B, Messages.getString("Language.finnish")), + FRENCH(0x040C, Messages.getString("Language.french")), + GERMAN(0x0407, Messages.getString("Language.german")), + GREEK(0x0408, Messages.getString("Language.greek")), + HEBREW(0x040D, Messages.getString("Language.hebrew")), + HUNGARIAN(0x040E, Messages.getString("Language.hungarian")), + ICELANDIC(0x040F, Messages.getString("Language.icelandic")), + ITALIAN(0x0410, Messages.getString("Language.italian")), + JAPANESE(0x0411, Messages.getString("Language.japanese")), + KOREAN(0x0412, Messages.getString("Language.korean")), + NORWEGIAN_BOKMAL(0x0414, Messages.getString("Language.norwegian.bokmal")), + NORWEGIAN_NYNORSK(0x0814, Messages.getString("Language.norwegian.nynorsk")), + POLISH(0x0415, Messages.getString("Language.polish")), + PORTUGUESE_BRAZIL(0x0416, Messages.getString("Language.portuguese.brazil")), + PORTUGUESE_PORTUGAL(0x0816, Messages.getString("Language.portuguese.portugal")), + RHAETO_ROMANIC(0x0417, Messages.getString("Language.rhaeto.romanic")), + ROMANIAN(0x0418, Messages.getString("Language.romanian")), + RUSSIAN(0x0419, Messages.getString("Language.russian")), + SERBO_CROATIAN_CYRILLIC(0x081A, Messages.getString("Language.serbo.croatian.cyrillic")), + SIMPLIFIED_CHINESE(0x0804, Messages.getString("Language.chinese.simplified")), + SLOVAK(0x041B, Messages.getString("Language.slovak")), + SPANISH_MEXICO(0x080A, Messages.getString("Language.spanish.mexico")), + SWEDISH(0x041D, Messages.getString("Language.swedish")), + FRENCH_SWISS(0x100C, Messages.getString("Language.swiss.french")), + GERMAN_SWISS(0x0807, Messages.getString("Language.swiss.german")), + ITALIAN_SWISS(0x0810, Messages.getString("Language.swiss.italian")), + THAI(0x041E, Messages.getString("Language.thai")), + TRADITIONAL_CHINESE(0x0404, Messages.getString("Language.chinese.traditional")), + TURKISH(0x041F, Messages.getString("Language.turkish")), + URDU(0x0420, Messages.getString("Language.urdu")), + ; + + private static final LanguageID[] VALUES = LanguageID.values(); + + static { + Arrays.sort(VALUES, new DescribableComparator()); + } + + private final int id; + private final String description; + + LanguageID(int id, String description) { + this.id = id; + this.description = description; + } + + public int getId() { + return id; + } + + @Override + public String getDescription() { + return description; + } + + @Override + public String toString() { + return description; + } + + @Override + public int getIndex() { + for (int i = 0; i < VALUES.length; i++) { + if (VALUES[i] == this) { + return i; + } + } + // should never happen + return -1; + } + + public static LanguageID[] sortedValues() { + return VALUES; + } +} diff --git a/launch4j/src/net/sf/launch4j/config/LdDefaults.java b/launch4j/src/net/sf/launch4j/config/LdDefaults.java index 5b4179c..4cb1387 100644 --- a/launch4j/src/net/sf/launch4j/config/LdDefaults.java +++ b/launch4j/src/net/sf/launch4j/config/LdDefaults.java @@ -36,22 +36,36 @@ */ package net.sf.launch4j.config; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; public class LdDefaults { - - public static final List GUI_HEADER_OBJECTS = Arrays.asList(new String[] { + private static final List GUI_OBJECTS = Arrays.asList(new String[] { "w32api/crt2.o", "head/guihead.o", "head/head.o" }); - public static final List CONSOLE_HEADER_OBJECTS = Arrays.asList(new String[] { + private static final List CONSOLE_OBJECTS = Arrays.asList(new String[] { "w32api/crt2.o", "head/consolehead.o", - "head/head.o"}); + "head/head.o" }); + + private static final List JNI_GUI_32_OBJECTS = Arrays.asList(new String[] { + "w32api_jni/crt2.o", + "head_jni_BETA/jniguihead.o", + "head_jni_BETA/head.o", + "head_jni_BETA/jnihead.o" }); - public static final List LIBS = Arrays.asList(new String[] { + private static final List JNI_CONSOLE_32_OBJECTS = Arrays.asList(new String[] { + "w32api_jni/crt2.o", + "head_jni_BETA/jniconsolehead.o", + "head_jni_BETA/head.o", + "head_jni_BETA/jnihead.o" }); + + private static final List> HEADER_OBJECTS; + + private static final List LIBS = Arrays.asList(new String[] { "w32api/libmingw32.a", "w32api/libgcc.a", "w32api/libmsvcrt.a", @@ -59,4 +73,45 @@ public class LdDefaults { "w32api/libuser32.a", "w32api/libadvapi32.a", "w32api/libshell32.a" }); + + private static final List JNI_LIBS = Arrays.asList(new String[] { + "w32api_jni/libmingw32.a", + "w32api_jni/libmingwex.a", + "w32api_jni/libgcc.a", + "w32api_jni/libmsvcrt.a", + "w32api_jni/libmoldname.a", + "w32api_jni/libkernel32.a", + "w32api_jni/libuser32.a", + "w32api_jni/libadvapi32.a", + "w32api_jni/libshell32.a" }); + + static { + HEADER_OBJECTS = new ArrayList>(); + HEADER_OBJECTS.add(GUI_OBJECTS); + HEADER_OBJECTS.add(CONSOLE_OBJECTS); + HEADER_OBJECTS.add(JNI_GUI_32_OBJECTS); + HEADER_OBJECTS.add(JNI_CONSOLE_32_OBJECTS); + } + + public static List getHeaderObjects(int headerTypeIndex) { + if (headerTypeIndex < 0 || headerTypeIndex > 3) { + throw new IllegalArgumentException("headerTypeIndex is out of range: " + headerTypeIndex); + } + + return HEADER_OBJECTS.get(headerTypeIndex); + } + + public static List getLibs(String headerType) { + if (Config.GUI_HEADER.equals(headerType) + || Config.CONSOLE_HEADER.equals(headerType)) { + return LIBS; + } + + if (Config.JNI_GUI_HEADER_32.equals(headerType) + || Config.JNI_CONSOLE_HEADER_32.equals(headerType)) { + return JNI_LIBS; + } + + throw new IllegalArgumentException("Unknown headerType: " + headerType); + } } diff --git a/launch4j/src/net/sf/launch4j/config/VersionInfo.java b/launch4j/src/net/sf/launch4j/config/VersionInfo.java index 9a24abd..da7a2ca 100644 --- a/launch4j/src/net/sf/launch4j/config/VersionInfo.java +++ b/launch4j/src/net/sf/launch4j/config/VersionInfo.java @@ -44,6 +44,7 @@ import net.sf.launch4j.binding.Validator; */ public class VersionInfo implements IValidatable { public static final String VERSION_PATTERN = "(\\d+\\.){3}\\d+"; + public static final int DEFAULT_LANGUAGE_INDEX = LanguageID.ENGLISH_US.getIndex(); private String fileVersion; private String txtFileVersion; @@ -55,6 +56,8 @@ public class VersionInfo implements IValidatable { private String companyName; private String internalName; private String originalFilename; + private String trademarks; + private LanguageID language; public void checkInvariants() { Validator.checkString(fileVersion, 20, VERSION_PATTERN, @@ -77,6 +80,8 @@ public class VersionInfo implements IValidatable { Messages.getString("VersionInfo.company.name")); Validator.checkString(internalName, 50, "versionInfo.internalName", Messages.getString("VersionInfo.internal.name")); + Validator.checkOptString(trademarks, 150, "versionInfo.trademarks", + Messages.getString("VersionInfo.trademarks")); Validator.checkTrue(!internalName.endsWith(".exe"), "versionInfo.internalName", Messages.getString("VersionInfo.internal.name.not.exe")); Validator.checkString(originalFilename, 50, "versionInfo.originalFilename", @@ -165,4 +170,28 @@ public class VersionInfo implements IValidatable { public void setTxtProductVersion(String txtProductVersion) { this.txtProductVersion = txtProductVersion; } + + public String getTrademarks() { + return trademarks; + } + + public void setTrademarks(String trademarks) { + this.trademarks = trademarks; + } + + public LanguageID getLanguage() { + return (language == null) ? LanguageID.sortedValues()[DEFAULT_LANGUAGE_INDEX] : language; + } + + public void setLanguage(LanguageID language) { + this.language = language; + } + + public int getLanguageIndex() { + return (language == null) ? DEFAULT_LANGUAGE_INDEX : language.getIndex(); + } + + public void setLanguageIndex(int index) { + language = LanguageID.sortedValues()[index]; + } } diff --git a/launch4j/src/net/sf/launch4j/config/messages.properties b/launch4j/src/net/sf/launch4j/config/messages.properties index cae66fa..b2eecc4 100644 --- a/launch4j/src/net/sf/launch4j/config/messages.properties +++ b/launch4j/src/net/sf/launch4j/config/messages.properties @@ -63,13 +63,14 @@ VersionInfo.product.version=Product version, should be 'x.x.x.x' VersionInfo.txt.product.version=Free from product version VersionInfo.product.name=Product name VersionInfo.company.name=Company name +VersionInfo.trademarks=Trademarks VersionInfo.internal.name=Internal name VersionInfo.internal.name.not.exe=Internal name shouldn't have the .exe extension. 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. @@ -94,3 +95,57 @@ Msg.launcherErr=Launcher error message SingleInstance.mutexName=Mutex name SingleInstance.windowTitle=Window title + +Charset.ascii=7-bit ASCII +Charset.unicode=Unicode +Charset.multilingual=Multilingual +Charset.shift.jis=Japan (Shift JIS X-0208) +Charset.shift.ksc=Korea (Shift KSC 5601) +Charset.big5=Taiwan (Big5) +Charset.latin2=Latin-2 (Eastern European) +Charset.cyrillic=Cyrillic +Language.arabic=Arabic +Language.bulgarian=Bulgarian +Language.catalan=Catalan +Language.chinese.traditional=Chinese (Traditional) +Language.czech=Czech +Language.danish=Danish +Language.german=German +Language.english.us=English U.S. +Language.greek=Greek +Language.hebrew=Hebrew +Language.polish=Polish +Language.portuguese.brazil=Portuguese (Brazil) +Language.rhaeto.romanic=Rhaeto Romanic +Language.romanian=Romanian +Language.russian=Russian +Language.spanish.castilian=Spanish (Castilian) +Language.finnish=Finnish +Language.french=French +Language.hungarian=Hungarian +Language.icelandic=Icelandic +Language.italian=Italian +Language.japanese=Japanese +Language.korean=Korean +Language.dutch=Dutch +Language.norwegian.bokmal=Norwegian Bokm\u00E5l +Language.croato.serbian.latin=Croato-Serbian (Latin) +Language.slovak=Slovak +Language.albanian=Albanian +Language.swedish=Swedish +Language.thai=Thai +Language.turkish=Turkish +Language.urdu=Urdu +Language.bahasa=Bahasa +Language.chinese.simplified=Chinese (Simplified) +Language.swiss.german=Swiss German +Language.english.uk=English U.K. +Language.spanish.mexico=Spanish (Mexico) +Language.belgian.french=Belgian French +Language.canadian.french=Canadian French +Language.swiss.italian=Swiss Italian +Language.belgian.dutch=Belgian Dutch +Language.norwegian.nynorsk=Norwegian Nynorsk +Language.portuguese.portugal=Portuguese (Portugal) +Language.serbo.croatian.cyrillic=Serbo-Croatian (Cyrillic) +Language.swiss.french=Swiss French diff --git a/launch4j/src/net/sf/launch4j/form/BasicForm.java b/launch4j/src/net/sf/launch4j/form/BasicForm.java index b53458c..72f477e 100644 --- a/launch4j/src/net/sf/launch4j/form/BasicForm.java +++ b/launch4j/src/net/sf/launch4j/form/BasicForm.java @@ -229,7 +229,6 @@ public abstract class BasicForm extends JPanel _errorTitleField.setToolTipText(Messages.getString("errorTitleTip")); jpanel1.add(_errorTitleField,cc.xywh(4,24,7,1)); - _downloadUrlLabel.setIcon(loadImage("images/asterix.gif")); _downloadUrlLabel.setName("downloadUrlLabel"); _downloadUrlLabel.setText(Messages.getString("downloadUrl")); jpanel1.add(_downloadUrlLabel,cc.xy(2,26)); diff --git a/launch4j/src/net/sf/launch4j/form/BasicForm.jfrm b/launch4j/src/net/sf/launch4j/form/BasicForm.jfrm index 0325724..3d8e92c 100644 Binary files a/launch4j/src/net/sf/launch4j/form/BasicForm.jfrm and b/launch4j/src/net/sf/launch4j/form/BasicForm.jfrm differ diff --git a/launch4j/src/net/sf/launch4j/form/HeaderForm.java b/launch4j/src/net/sf/launch4j/form/HeaderForm.java index ef5dac4..9465b24 100644 --- a/launch4j/src/net/sf/launch4j/form/HeaderForm.java +++ b/launch4j/src/net/sf/launch4j/form/HeaderForm.java @@ -4,6 +4,7 @@ import com.jeta.forms.components.separator.TitledSeparator; import com.jgoodies.forms.layout.CellConstraints; import com.jgoodies.forms.layout.FormLayout; import java.awt.BorderLayout; +import java.awt.Color; import java.awt.Container; import java.awt.Dimension; import javax.swing.Box; @@ -27,6 +28,8 @@ public abstract class HeaderForm extends JPanel protected final JCheckBox _headerObjectsCheck = new JCheckBox(); protected final JCheckBox _libsCheck = new JCheckBox(); protected final TitledSeparator _linkerOptionsSeparator = new TitledSeparator(); + protected final JRadioButton _jniGuiHeaderRadio = new JRadioButton(); + protected final JRadioButton _jniConsoleHeaderRadio = new JRadioButton(); /** * Default constructor @@ -106,7 +109,7 @@ public abstract class HeaderForm extends JPanel public JPanel createPanel() { JPanel jpanel1 = new JPanel(); - FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:7DLU:NONE,FILL:DEFAULT:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,FILL:DEFAULT:GROW(0.2),CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:9DLU:NONE"); + FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:DEFAULT:NONE,FILL:7DLU:NONE,FILL:DEFAULT:NONE,FILL:7DLU:NONE,FILL:DEFAULT:NONE,FILL:7DLU:NONE,FILL:DEFAULT:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,FILL:DEFAULT:GROW(0.2),CENTER:3DLU:NONE,FILL:DEFAULT:GROW(1.0),CENTER:9DLU:NONE"); CellConstraints cc = new CellConstraints(); jpanel1.setLayout(formlayout1); @@ -117,12 +120,14 @@ public abstract class HeaderForm extends JPanel _guiHeaderRadio.setActionCommand("GUI"); _guiHeaderRadio.setName("guiHeaderRadio"); _guiHeaderRadio.setText(Messages.getString("gui")); + _guiHeaderRadio.setToolTipText(Messages.getString("guiTooltip")); _headerButtonGroup.add(_guiHeaderRadio); jpanel1.add(_guiHeaderRadio,cc.xy(4,2)); _consoleHeaderRadio.setActionCommand("Console"); _consoleHeaderRadio.setName("consoleHeaderRadio"); _consoleHeaderRadio.setText(Messages.getString("console")); + _consoleHeaderRadio.setToolTipText(Messages.getString("consoleTooltip")); _headerButtonGroup.add(_consoleHeaderRadio); jpanel1.add(_consoleHeaderRadio,cc.xy(6,2)); @@ -131,14 +136,14 @@ public abstract class HeaderForm extends JPanel jscrollpane1.setViewportView(_headerObjectsTextArea); jscrollpane1.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); jscrollpane1.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - jpanel1.add(jscrollpane1,cc.xywh(4,6,4,1)); + jpanel1.add(jscrollpane1,cc.xywh(4,6,8,1)); _libsTextArea.setName("libsTextArea"); JScrollPane jscrollpane2 = new JScrollPane(); jscrollpane2.setViewportView(_libsTextArea); jscrollpane2.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED); jscrollpane2.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); - jpanel1.add(jscrollpane2,cc.xywh(4,8,4,1)); + jpanel1.add(jscrollpane2,cc.xywh(4,8,8,1)); _headerObjectsCheck.setActionCommand("Object files"); _headerObjectsCheck.setName("headerObjectsCheck"); @@ -152,9 +157,25 @@ public abstract class HeaderForm extends JPanel _linkerOptionsSeparator.setName("linkerOptionsSeparator"); _linkerOptionsSeparator.setText(Messages.getString("linkerOptions")); - jpanel1.add(_linkerOptionsSeparator,cc.xywh(2,4,6,1)); + jpanel1.add(_linkerOptionsSeparator,cc.xywh(2,4,10,1)); - addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8 },new int[]{ 1,2,3,4,5,6,7,8,9 }); + _jniGuiHeaderRadio.setActionCommand(Messages.getString("jniGui")); + _jniGuiHeaderRadio.setForeground(new Color(255,102,0)); + _jniGuiHeaderRadio.setName("jniGuiHeaderRadio"); + _jniGuiHeaderRadio.setText(Messages.getString("jniGui")); + _jniGuiHeaderRadio.setToolTipText(Messages.getString("jniGuiTooltip")); + _headerButtonGroup.add(_jniGuiHeaderRadio); + jpanel1.add(_jniGuiHeaderRadio,cc.xy(8,2)); + + _jniConsoleHeaderRadio.setActionCommand(Messages.getString("jniConsole")); + _jniConsoleHeaderRadio.setForeground(new Color(255,102,0)); + _jniConsoleHeaderRadio.setName("jniConsoleHeaderRadio"); + _jniConsoleHeaderRadio.setText(Messages.getString("jniConsole")); + _jniConsoleHeaderRadio.setToolTipText(Messages.getString("jniConsoleTooltip")); + _headerButtonGroup.add(_jniConsoleHeaderRadio); + jpanel1.add(_jniConsoleHeaderRadio,cc.xy(10,2)); + + addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12 },new int[]{ 1,2,3,4,5,6,7,8,9 }); return jpanel1; } diff --git a/launch4j/src/net/sf/launch4j/form/HeaderForm.jfrm b/launch4j/src/net/sf/launch4j/form/HeaderForm.jfrm index a7cbed1..200928f 100644 Binary files a/launch4j/src/net/sf/launch4j/form/HeaderForm.jfrm and b/launch4j/src/net/sf/launch4j/form/HeaderForm.jfrm differ diff --git a/launch4j/src/net/sf/launch4j/form/VersionInfoForm.java b/launch4j/src/net/sf/launch4j/form/VersionInfoForm.java index f1f3c7e..92cfda2 100644 --- a/launch4j/src/net/sf/launch4j/form/VersionInfoForm.java +++ b/launch4j/src/net/sf/launch4j/form/VersionInfoForm.java @@ -9,6 +9,7 @@ import java.awt.Dimension; import javax.swing.Box; import javax.swing.ImageIcon; import javax.swing.JCheckBox; +import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JTextField; @@ -37,6 +38,10 @@ public abstract class VersionInfoForm extends JPanel protected final JTextField _internalNameField = new JTextField(); protected final JLabel _companyNameLabel = new JLabel(); protected final JTextField _companyNameField = new JTextField(); + protected final JLabel _languageLabel = new JLabel(); + protected final JComboBox _languageCombo = new JComboBox(); + protected final JLabel _trademarksLabel = new JLabel(); + protected final JTextField _trademarksField = new JTextField(); /** * Default constructor @@ -116,7 +121,7 @@ public abstract class VersionInfoForm extends JPanel public JPanel createPanel() { JPanel jpanel1 = new JPanel(); - FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:60DLU:NONE,FILL:7DLU:NONE,RIGHT:DEFAULT:NONE,FILL:3DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE"); + FormLayout formlayout1 = new FormLayout("FILL:7DLU:NONE,RIGHT:MAX(65DLU;DEFAULT):NONE,FILL:3DLU:NONE,FILL:60DLU:NONE,FILL:7DLU:NONE,RIGHT:DEFAULT:NONE,FILL:3DLU:NONE,FILL:DEFAULT:GROW(1.0),FILL:7DLU:NONE","CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:3DLU:NONE,CENTER:DEFAULT:NONE,CENTER:9DLU:NONE"); CellConstraints cc = new CellConstraints(); jpanel1.setLayout(formlayout1); @@ -215,7 +220,21 @@ public abstract class VersionInfoForm extends JPanel _companyNameField.setName("companyNameField"); jpanel1.add(_companyNameField,cc.xywh(4,16,5,1)); - addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8,9 },new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21 }); + _languageLabel.setName("languageLabel"); + _languageLabel.setText(Messages.getString("language")); + jpanel1.add(_languageLabel,cc.xy(2,24)); + + _languageCombo.setName("languageCombo"); + jpanel1.add(_languageCombo,cc.xywh(4,24,3,1)); + + _trademarksLabel.setName("trademarksLabel"); + _trademarksLabel.setText(Messages.getString("trademarks")); + jpanel1.add(_trademarksLabel,cc.xy(2,22)); + + _trademarksField.setName("trademarksField"); + jpanel1.add(_trademarksField,cc.xywh(4,22,5,1)); + + addFillComponents(jpanel1,new int[]{ 1,2,3,4,5,6,7,8,9 },new int[]{ 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 }); return jpanel1; } diff --git a/launch4j/src/net/sf/launch4j/form/VersionInfoForm.jfrm b/launch4j/src/net/sf/launch4j/form/VersionInfoForm.jfrm index 32eb136..5176be9 100644 Binary files a/launch4j/src/net/sf/launch4j/form/VersionInfoForm.jfrm and b/launch4j/src/net/sf/launch4j/form/VersionInfoForm.jfrm differ diff --git a/launch4j/src/net/sf/launch4j/form/messages.properties b/launch4j/src/net/sf/launch4j/form/messages.properties index ad4fb5b..b50c32b 100644 --- a/launch4j/src/net/sf/launch4j/form/messages.properties +++ b/launch4j/src/net/sf/launch4j/form/messages.properties @@ -71,7 +71,13 @@ importClassPath=Import attributes from a jar's manifest. headerType=Header type: gui=GUI +guiTooltip=Stable version of the GUI header which uses the javaw.exe launcher. console=Console +consoleTooltip=Stable version of the console header which uses the java.exe launcher. +jniGui=JNI GUI (beta) +jniGuiTooltip=BETA version of the GUI header which launches the Java VM through JNI. +jniConsole=JNI Console (beta) +jniConsoleTooltip=BETA version of the console header which launches the Java VM through JNI. objectFiles=Object files: libs=w32api: linkerOptions=Custom header - linker options @@ -141,6 +147,9 @@ originalFilenameTip=Original name of the file without the path. Allows to determ internalName=Internal name: internalNameTip=Internal name without extension, original filename or module name for example. companyName=Company name: +trademarks=Trademarks: +language=Language: +charset=Charset: addMessages=Add custom messages startupErr=Startup error: diff --git a/launch4j/src/net/sf/launch4j/formimpl/HeaderFormImpl.java b/launch4j/src/net/sf/launch4j/formimpl/HeaderFormImpl.java index d4ca507..1938fd4 100644 --- a/launch4j/src/net/sf/launch4j/formimpl/HeaderFormImpl.java +++ b/launch4j/src/net/sf/launch4j/formimpl/HeaderFormImpl.java @@ -40,8 +40,6 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JRadioButton; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import net.sf.launch4j.binding.Binding; import net.sf.launch4j.binding.Bindings; @@ -58,24 +56,45 @@ public class HeaderFormImpl extends HeaderForm { public HeaderFormImpl(Bindings bindings) { _bindings = bindings; _bindings.add("headerTypeIndex", new JRadioButton[] { _guiHeaderRadio, - _consoleHeaderRadio }) + _consoleHeaderRadio, + _jniGuiHeaderRadio, + _jniConsoleHeaderRadio }) .add("headerObjects", "customHeaderObjects", _headerObjectsCheck, _headerObjectsTextArea) .add("libs", "customLibs", _libsCheck, _libsTextArea); - _guiHeaderRadio.addChangeListener(new HeaderTypeChangeListener()); + _guiHeaderRadio.setActionCommand(Config.GUI_HEADER); + _consoleHeaderRadio.setActionCommand(Config.CONSOLE_HEADER); + _jniGuiHeaderRadio.setActionCommand(Config.JNI_GUI_HEADER_32); + _jniConsoleHeaderRadio.setActionCommand(Config.JNI_CONSOLE_HEADER_32); + + ActionListener headerTypeActionListener = new HeaderTypeActionListener(); + _guiHeaderRadio.addActionListener(headerTypeActionListener); + _consoleHeaderRadio.addActionListener(headerTypeActionListener); + _jniGuiHeaderRadio.addActionListener(headerTypeActionListener); + _jniConsoleHeaderRadio.addActionListener(headerTypeActionListener); + _headerObjectsCheck.addActionListener(new HeaderObjectsActionListener()); _libsCheck.addActionListener(new LibsActionListener()); } + + private void updateLibs() { + if (!_libsCheck.isSelected()) { + ConfigPersister.getInstance().getConfig().setLibs(null); + Binding b = _bindings.getBinding("libs"); + b.put(ConfigPersister.getInstance().getConfig()); + } + } - private class HeaderTypeChangeListener implements ChangeListener { - public void stateChanged(ChangeEvent e) { + private class HeaderTypeActionListener implements ActionListener { + public void actionPerformed(ActionEvent e) { Config c = ConfigPersister.getInstance().getConfig(); - c.setHeaderType(_guiHeaderRadio.isSelected() ? Config.GUI_HEADER - : Config.CONSOLE_HEADER); + c.setHeaderType(e.getActionCommand()); + if (!_headerObjectsCheck.isSelected()) { Binding b = _bindings.getBinding("headerObjects"); b.put(c); + updateLibs(); } } } @@ -92,11 +111,7 @@ public class HeaderFormImpl extends HeaderForm { private class LibsActionListener implements ActionListener { public void actionPerformed(ActionEvent e) { - if (!_libsCheck.isSelected()) { - ConfigPersister.getInstance().getConfig().setLibs(null); - Binding b = _bindings.getBinding("libs"); - b.put(ConfigPersister.getInstance().getConfig()); - } + updateLibs(); } } } diff --git a/launch4j/src/net/sf/launch4j/formimpl/MainFrame.java b/launch4j/src/net/sf/launch4j/formimpl/MainFrame.java index a25dc7e..2799bdb 100644 --- a/launch4j/src/net/sf/launch4j/formimpl/MainFrame.java +++ b/launch4j/src/net/sf/launch4j/formimpl/MainFrame.java @@ -69,7 +69,6 @@ import net.sf.launch4j.Util; import net.sf.launch4j.binding.Binding; import net.sf.launch4j.binding.BindingException; import net.sf.launch4j.binding.InvariantViolationException; -import net.sf.launch4j.config.Config; import net.sf.launch4j.config.ConfigPersister; import net.sf.launch4j.config.ConfigPersisterException; @@ -226,7 +225,7 @@ public class MainFrame extends JFrame { } private void showConfigName(File config) { - setTitle(Main.getName() + " - " + (config != null ? config.getName() + setTitle(Main.getName() + " - " + (config != null ? config.getName() : Messages.getString("MainFrame.untitled"))); } @@ -309,8 +308,8 @@ public class MainFrame extends JFrame { ConfigPersister.getInstance().getConfig().checkInvariants(); Builder b = new Builder(log); _outfile = b.build(); - setRunEnabled(ConfigPersister.getInstance().getConfig() - .getHeaderType() == Config.GUI_HEADER // TODO fix console app test + setRunEnabled(ConfigPersister.getInstance().getConfig().isGuiApplication() + // TODO fix console app test && (Util.WINDOWS_OS || !ConfigPersister.getInstance() .getConfig().isDontWrapJar())); } catch (InvariantViolationException ex) { diff --git a/launch4j/src/net/sf/launch4j/formimpl/VersionInfoFormImpl.java b/launch4j/src/net/sf/launch4j/formimpl/VersionInfoFormImpl.java index 275289e..8e0e5f3 100644 --- a/launch4j/src/net/sf/launch4j/formimpl/VersionInfoFormImpl.java +++ b/launch4j/src/net/sf/launch4j/formimpl/VersionInfoFormImpl.java @@ -36,9 +36,11 @@ */ package net.sf.launch4j.formimpl; +import javax.swing.DefaultComboBoxModel; import javax.swing.JFileChooser; import net.sf.launch4j.binding.Bindings; +import net.sf.launch4j.config.LanguageID; import net.sf.launch4j.config.VersionInfo; import net.sf.launch4j.form.VersionInfoForm; @@ -48,6 +50,7 @@ import net.sf.launch4j.form.VersionInfoForm; public class VersionInfoFormImpl extends VersionInfoForm { public VersionInfoFormImpl(Bindings bindings, JFileChooser fc) { + _languageCombo.setModel(new DefaultComboBoxModel(LanguageID.sortedValues())); bindings.addOptComponent("versionInfo", VersionInfo.class, _versionInfoCheck) .add("versionInfo.fileVersion", _fileVersionField) .add("versionInfo.productVersion", _productVersionField) @@ -58,6 +61,9 @@ public class VersionInfoFormImpl extends VersionInfoForm { .add("versionInfo.txtFileVersion", _txtFileVersionField) .add("versionInfo.txtProductVersion", _txtProductVersionField) .add("versionInfo.companyName", _companyNameField) - .add("versionInfo.copyright", _copyrightField); + .add("versionInfo.copyright", _copyrightField) + .add("versionInfo.trademarks", _trademarksField) + .add("versionInfo.languageIndex", _languageCombo, VersionInfo.DEFAULT_LANGUAGE_INDEX) + ; } } diff --git a/launch4j/src/net/sf/launch4j/messages.properties b/launch4j/src/net/sf/launch4j/messages.properties index 9895ca3..db2f9cc 100644 --- a/launch4j/src/net/sf/launch4j/messages.properties +++ b/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/launch4j/w32api_jni/MinGW.LICENSE.txt b/launch4j/w32api_jni/MinGW.LICENSE.txt new file mode 100644 index 0000000..aea85bd --- /dev/null +++ b/launch4j/w32api_jni/MinGW.LICENSE.txt @@ -0,0 +1,25 @@ +MinGW - Licensing Terms + +Various pieces distributed with MinGW come with its own copyright and license: + +Basic MinGW runtime + MinGW base runtime package is uncopyrighted and placed in the public domain. + This basically means that you can do what you want with the code. + +w32api + You are free to use, modify and copy this package. + No restrictions are imposed on programs or object files compiled with this library. + You may not restrict the the usage of this library. + You may distribute this library as part of another package or as a modified package + if and only if you do not restrict the usage of the portions consisting + of this (optionally modified) library. + If distributed as a modified package then this file must be included. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty + of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +MinGW profiling code + MinGW profiling code is distributed under the GNU General Public License. + +The development tools such as GCC, GDB, GNU Make, etc all covered by GNU General Public License. diff --git a/launch4j/w32api_jni/crt2.o b/launch4j/w32api_jni/crt2.o new file mode 100644 index 0000000..4f5f3be Binary files /dev/null and b/launch4j/w32api_jni/crt2.o differ diff --git a/launch4j/w32api_jni/libadvapi32.a b/launch4j/w32api_jni/libadvapi32.a new file mode 100644 index 0000000..21a8d7b Binary files /dev/null and b/launch4j/w32api_jni/libadvapi32.a differ diff --git a/launch4j/w32api_jni/libgcc.a b/launch4j/w32api_jni/libgcc.a new file mode 100644 index 0000000..f98edb8 Binary files /dev/null and b/launch4j/w32api_jni/libgcc.a differ diff --git a/launch4j/w32api_jni/libkernel32.a b/launch4j/w32api_jni/libkernel32.a new file mode 100644 index 0000000..03ee7cd Binary files /dev/null and b/launch4j/w32api_jni/libkernel32.a differ diff --git a/launch4j/w32api_jni/libmingw32.a b/launch4j/w32api_jni/libmingw32.a new file mode 100644 index 0000000..d849b85 Binary files /dev/null and b/launch4j/w32api_jni/libmingw32.a differ diff --git a/launch4j/w32api_jni/libmingwex.a b/launch4j/w32api_jni/libmingwex.a new file mode 100644 index 0000000..f742492 Binary files /dev/null and b/launch4j/w32api_jni/libmingwex.a differ diff --git a/launch4j/w32api_jni/libmoldname.a b/launch4j/w32api_jni/libmoldname.a new file mode 100644 index 0000000..21897da Binary files /dev/null and b/launch4j/w32api_jni/libmoldname.a differ diff --git a/launch4j/w32api_jni/libmsvcrt.a b/launch4j/w32api_jni/libmsvcrt.a new file mode 100644 index 0000000..be8ae31 Binary files /dev/null and b/launch4j/w32api_jni/libmsvcrt.a differ diff --git a/launch4j/w32api_jni/libshell32.a b/launch4j/w32api_jni/libshell32.a new file mode 100644 index 0000000..efdd8bc Binary files /dev/null and b/launch4j/w32api_jni/libshell32.a differ diff --git a/launch4j/w32api_jni/libuser32.a b/launch4j/w32api_jni/libuser32.a new file mode 100644 index 0000000..cbddae6 Binary files /dev/null and b/launch4j/w32api_jni/libuser32.a differ diff --git a/launch4j/web/changelog.html b/launch4j/web/changelog.html index c153de8..450a2c0 100644 --- a/launch4j/web/changelog.html +++ b/launch4j/web/changelog.html @@ -11,7 +11,7 @@
- launch4j 3.7 + 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).
  • +
  • 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).
  • +
  • More reactive splash screen response to main window appearance (Federico Fissore).
  • +
  • FR #95 Launch4j should return an exit value (Sebastian Bögl).
  • +
  • FR #94 Add the working directory classifier for OS X (Sebastian Bögl).
  • +
  • FR #39 Launch Java VM through JNI (Ryan Rusaw) - BETA!
  • +
  • FR #69 Configure the language property of generated executables (Sebastian Bögl).
  • +
  • FR #77 Add legal trademarks as an additional field in version info tab (Sebastian Bögl).
  • +
  • Added a simple example how to use the Maven plugin (demo/ExitCodeApp).
  • +
+ +

Changes in version 3.8 (09-05-2015)

+
    +
  • FR #59 Mavenized launch4j (thanks to taxone, Paul Jungwirth, Lukasz Lenart).
  • +
  • Ticket #139 Sign4j compiles and works on Linux (Tim Angus).
  • +
+

Changes in version 3.7 (01-03-2015)

    -
  • Fixed false positive virus warnings.
  • +
  • Fixed false positive virus warnings that appeared in version 3.6.

Changes in version 3.6 (06-01-2015)

@@ -46,8 +83,7 @@
  • FR #86 The 32/64 bit search is fully configurable (64, 64/32, 32/64, 32) - added option 32/64.
  • FR #70 Java search sequence - bundled JRE can be used before or after the min/max version search (bundledJreAsFallback).
  • Fixed: Crash when classpath contained wildcard patterns where the dependency was in the same directory as the launcher.
  • -
  • Fixed Launch4j GUI application closing - the process was still running.
  • -
  • Updated to Dev-Cpp 5.7.1, MinGW 4.8.1 (head_src and w32api files).
  • +
  • Fixed launch4j GUI application closing - the process was still running.
  • Changes in version 3.5 (09-10-2014)

    @@ -62,7 +98,7 @@
  • FR #61 Added a new special variable JREHOMEDIR (Stefan Knoefel).
  • Ticket #130 Removed ant from launch4j classpath to fix problems with other ant versions.
  • Updated JGoodies libraries.
  • -
  • Added logging based on Launch4j environment variable for file association launch testing.
  • +
  • Added logging based on launch4j environment variable for file association launch testing.
  • Changes in version 3.3 (02-04-2014)

    @@ -422,9 +458,9 @@
    diff --git a/launch4j/web/docs.html b/launch4j/web/docs.html index 34c2daf..bd4f6f4 100644 --- a/launch4j/web/docs.html +++ b/launch4j/web/docs.html @@ -11,7 +11,7 @@
    - launch4j 3.7 + launch4j 3.12
    Running launch4j
    @@ -65,14 +61,17 @@ all of the configuration parameters through the Ant task. All files may be absolute paths or relative to the configuration file path.
    -<!-- Bold elements are required -->
    -<!-- %VAR% expands environment/special variables and registry keys -->
    +<!--
    +  Bold elements are required.
    +  Underlined values are the default when the element is not specified.
    +  %VAR% expands environment/special variables and registry keys.
    +-->
     <launch4jConfig>
    -  <headerType>gui|console</headerType>
    +  <headerType>gui|console|jniGui32|jniConsole32</headerType>
       <outfile>file.exe</outfile>
       <jar>file</jar>
       <dontWrapJar>true|false</dontWrapJar>
    -  <errTitle>text</errTitle>
    +  <errTitle>application name</errTitle>
       <downloadUrl>http://java.com/download</downloadUrl>
       <supportUrl>url</supportUrl>
       <cmdLine>text</cmdLine>
    @@ -97,15 +96,15 @@ may be absolute paths or relative to the configuration file path.
         <windowTitle>text</windowTitle>
       </singleInstance> 
       <jre>
    -    <!-- Specify one of the following or both -->
    +    <!-- Specify path or minVersion or both. -->
         <path>bundled JRE path (%VAR%)</path>
         <bundledJre64Bit>true|false</bundledJre64Bit>
         <bundledJreAsFallback>true|false</bundledJreAsFallback>
    -    <minVersion>x.x.x[_xx]</minVersion>
    -    <maxVersion>x.x.x[_xx]</maxVersion>
    +    <minVersion>1.x.x[_xxx]|xxx[.xxx[.xxx]]</minVersion>
    +    <maxVersion>1.x.x[_xxx]|xxx[.xxx[.xxx]]</maxVersion>
         <jdkPreference>jreOnly|preferJre|preferJdk|jdkOnly</jdkPreference>
         <runtimeBits>64|64/32|32/64|32</runtimeBits>
    -    <!-- Heap sizes in MB and % of available memory -->
    +    <!-- Heap sizes in MB and % of available memory. -->
         <initialHeapSize>MB</initialHeapSize>
         <initialHeapPercent>%</initialHeapPercent>
         <maxHeapSize>MB</maxHeapSize>
    @@ -130,13 +129,26 @@ may be absolute paths or relative to the configuration file path.
         <companyName>text</companyName>
         <internalName>filename</internalName>
         <originalFilename>filename.exe</originalFilename>
    +    <trademarks>text</trademarks>
    +    <language>
    +      ALBANIAN|ARABIC|BAHASA|DUTCH_BELGIAN|FRENCH_BELGIAN|BULGARIAN|
    +      FRENCH_CANADIAN|CASTILIAN_SPANISH|CATALAN|CROATO_SERBIAN_LATIN|
    +      CZECH|DANISH|DUTCH|ENGLISH_UK|ENGLISH_US|FINNISH|FRENCH|GERMAN|
    +      GREEK|HEBREW|HUNGARIAN|ICELANDIC|ITALIAN|JAPANESE|KOREAN|
    +      NORWEGIAN_BOKMAL|NORWEGIAN_NYNORSK|POLISH|PORTUGUESE_BRAZIL|
    +      PORTUGUESE_PORTUGAL|RHAETO_ROMANIC|ROMANIAN|RUSSIAN|
    +      SERBO_CROATIAN_CYRILLIC|SIMPLIFIED_CHINESE|SLOVAK|SPANISH_MEXICO|
    +      SWEDISH|FRENCH_SWISS|GERMAN_SWISS|ITALIAN_SWISS|THAI|
    +      TRADITIONAL_CHINESE|TURKISH|URDU
    +    </language>
       </versionInfo>
       <messages>
         <startupErr>text</startupErr>
         <bundledJreErr>text</bundledJreErr>
         <jreVersionErr>text</jreVersionErr>
         <launcherErr>text</launcherErr>
    -    <instanceAlreadyExistsMsg>text (used by console header only)</instanceAlreadyExistsMsg>
    +    <!-- Used by console header only. -->
    +    <instanceAlreadyExistsMsg>text</instanceAlreadyExistsMsg>
       </messages>
     </launch4jConfig>
     
    @@ -170,8 +182,37 @@ may be absolute paths or relative to the configuration file path. no always waits and returns application's exit code. + + jniGui32 (beta) + launch4j + yes + always waits and returns application's exit code. + + + jniConsole32 (beta) + launch4j + no + always waits and returns application's exit code. + +
    + When JNI headers are used the JVM is created directly by the launch4j wrapper executable instead of running java/javaw launchers. + The process name will be the same as the wrapper. The JNI headers are in BETA and some features are not available which is signaled + during wrapper build based on the configuration. + For production use consider the classic gui/console headers. +
    + Missing features: +
      +
    • Only '.' is allowed in change directory (chdir).
    • +
    • Command line arguments cannot be passed to the executable.
    • +
    • Constant command line arguments (cmdLine).
    • +
    • stayAlive should be ignored by JNI headers.
    • +
    • Restart of appplication based on exit code (restartOnCrash).
    • +
    • Process priority - only normal is supported (priority).
    • +
    • Jar manifest is ignored, mainclass and classpath must be defined.
    • +
    • 64-bit JRE are not supported.
    • +
    @@ -280,7 +321,7 @@ may be absolute paths or relative to the configuration file path. use the <minVersion> property, you may also specify the <maxVersion> to prevent it from using higher Java versions. Launch4j will always use the highest version available (in the min/max range of course). - If a Sun's JRE is not available or does not satisfy the search criteria, + If an Oracle's JRE is not available or does not satisfy the search criteria, the search will be repeated on IBM runtimes. You can also combine these properties to change the startup process... @@ -300,6 +341,30 @@ may be absolute paths or relative to the configuration file path.
    +
    +
    +
    <minVersion>, <maxVersion> format - Java < 9
    +
    The traditional version scheme supported by launch4j is 1.x.x[_xxx] and requires at least 3 parts, for example: +
    +1.6.0
    +1.7.0_51
    +1.8.0_121
    +
    +
    +
    +
    +
    +
    +
    <minVersion>, <maxVersion> format - Java >= 9
    +
    The new version format is xxx[.xxx[.xxx]] where only 1 part is required and the update version after the underscore is not allowed. +
    +1.6
    +9
    +10.0.1
    +
    +
    +
    +
    <bundledJre64Bit>
    @@ -442,7 +507,8 @@ may be absolute paths or relative to the configuration file path.
    <versionInfo>
    -
    Optional, version information to be displayed by the Windows Explorer.
    +
    Optional, version information + to be displayed by the Windows Explorer.
    @@ -487,6 +553,14 @@ may be absolute paths or relative to the configuration file path. whether a file has been renamed by a user.
    +
    +
    <trademarks>
    +
    Trademarks that apply to the file.
    +
    +
    +
    <language>
    +
    One of the language codes.
    +

    Importing 1.x configuration

    @@ -643,6 +717,7 @@ They are substitued during runtime, so for example the EXEDIR is the directory w

    Settings

    +These settings are only used during building of the launcher or wrapper, not during their execution.
    Alternate bin directory: launch4j.bindir
    @@ -657,9 +732,9 @@ They are substitued during runtime, so for example the EXEDIR is the directory w
    diff --git a/launch4j/web/index.html b/launch4j/web/index.html index 723ee00..ac3a0b9 100644 --- a/launch4j/web/index.html +++ b/launch4j/web/index.html @@ -11,7 +11,7 @@
    - launch4j 3.7 + launch4j 3.12

    Cross-platform Java executable wrapper

    @@ -87,22 +83,22 @@
  • Digital signing of the executable with sign4j.
  • Supports Windows Security Features of the Windows 8 certification kit.
  • GUI and command line interface.
  • -
  • Build integration through an Ant task.
  • +
  • Build integration through an Ant task and a Maven Plugin.
  • Lightweight: 35 KB!
  • It's free and may be used for commercial purposes.
  • Includes a sample application and Ant script that automates the build process from Java sources to native executable.
  • -
  • The wrapped program works on all Windows platforms (98/Me/NT/2K/XP/Vista/7/8), - Launch4j works on NT/2K/XP/Vista/7/8, Linux and Mac OS X. +
  • The wrapped program works on all Windows platforms, + Launch4j works on Windows, Linux and Mac OS X.
  • License

    This program is free software licensed under the - BSD license, the head subproject + BSD 3-Clause License, the head subproject (the code which is attached to the wrapped jars) is licensed under the - MIT license. + MIT License. Launch4j may be used for wrapping closed source, commercial applications.

    Info

    @@ -116,9 +112,9 @@
    diff --git a/launch4j/web/links.html b/launch4j/web/links.html index 552b893..8aa9c4e 100644 --- a/launch4j/web/links.html +++ b/launch4j/web/links.html @@ -11,7 +11,7 @@
    - launch4j 3.7 + launch4j 3.12
    diff --git a/launch4j/web/style.css b/launch4j/web/style.css index f57c086..4ad6bcf 100644 --- a/launch4j/web/style.css +++ b/launch4j/web/style.css @@ -114,6 +114,13 @@ table td { color: #ffffff; } +#leftnav a.button { + display: inline; +} +#leftnav a.button:hover { + background-color: transparent; +} + #content { max-width: 52em; diff --git a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java index 62f0269..4764c82 100644 --- a/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java +++ b/src/uk/co/majenko/audiobookrecorder/AudiobookRecorder.java @@ -799,6 +799,8 @@ public class AudiobookRecorder extends JFrame implements DocumentListener { if (n instanceof Sentence) { Sentence s = (Sentence)n; + s.refreshAllData(); + //selectedSentence = s; s.updateCrossings(); sampleWaveform.setSentence(s); diff --git a/src/uk/co/majenko/audiobookrecorder/BookTreeRenderer.java b/src/uk/co/majenko/audiobookrecorder/BookTreeRenderer.java index 50b50c2..facf0a4 100644 --- a/src/uk/co/majenko/audiobookrecorder/BookTreeRenderer.java +++ b/src/uk/co/majenko/audiobookrecorder/BookTreeRenderer.java @@ -42,6 +42,10 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer { icn.add(Overlays.attention, OverlayIcon.TOP_LEFT); } + if (s.isClipping()) { + ret.setForeground(new Color(0xe0, 0x00, 0x00)); + } + if (s.isLocked()) { ret.setForeground(new Color(0x30, 0xb0, 0xFF)); icn.add(Overlays.locked, OverlayIcon.BOTTOM_LEFT); @@ -125,10 +129,10 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer { ctx.weightx = 0.0d; ctx.gridx = 3; ctx.anchor = GridBagConstraints.LINE_END; - int peak = s.getPeakDB(); + int peak = (int)s.getRMS(); JLabel peakLabel = new JLabelFixedWidth(50, peak + "dB "); peakLabel.setHorizontalAlignment(SwingConstants.RIGHT); - if (peak > 0) { + if ((peak < -23) || (peak > -18)) { peakLabel.setForeground(new Color(0xCC, 0x00, 0x00)); } p.add(peakLabel, ctx); @@ -159,9 +163,22 @@ public class BookTreeRenderer extends DefaultTreeCellRenderer { ctx.anchor = GridBagConstraints.LINE_START; ctx.weightx = 1.0d; p.add(ret, ctx); + + ctx.weightx = 0.0d; ctx.gridx = 1; ctx.anchor = GridBagConstraints.LINE_END; + int peak = (int)c.getRMS(); + JLabel peakLabel = new JLabelFixedWidth(50, peak + "dB "); + peakLabel.setHorizontalAlignment(SwingConstants.RIGHT); + if ((peak < -23) || (peak > -18)) { + peakLabel.setForeground(new Color(0xCC, 0x00, 0x00)); + } + p.add(peakLabel, ctx); + + ctx.weightx = 0.0d; + ctx.gridx = 2; + ctx.anchor = GridBagConstraints.LINE_END; p.add(time, ctx); p.setOpaque(false); return p; diff --git a/src/uk/co/majenko/audiobookrecorder/Chapter.java b/src/uk/co/majenko/audiobookrecorder/Chapter.java index 8944bdb..4399bbb 100644 --- a/src/uk/co/majenko/audiobookrecorder/Chapter.java +++ b/src/uk/co/majenko/audiobookrecorder/Chapter.java @@ -420,4 +420,20 @@ public class Chapter extends BookTreeNode { } } } + + public double getRMS() { + double rms = 0; + int c = 0; + for (Enumeration o = children(); o.hasMoreElements();) { + Object ob = (Object)o.nextElement(); + if (ob instanceof Sentence) { + Sentence s = (Sentence)ob; + rms += s.getRMS(); + c++; + } + } + + return rms / c; + } + } diff --git a/src/uk/co/majenko/audiobookrecorder/Sentence.java b/src/uk/co/majenko/audiobookrecorder/Sentence.java index 081963d..63272b2 100644 --- a/src/uk/co/majenko/audiobookrecorder/Sentence.java +++ b/src/uk/co/majenko/audiobookrecorder/Sentence.java @@ -95,6 +95,8 @@ public class Sentence extends BookTreeNode implements Cacheable { Book parentBook = null; double runtime = -1d; + double rms = -100d; + int clipping = 0; double[][] audioData = null; @@ -226,6 +228,8 @@ public class Sentence extends BookTreeNode implements Cacheable { sampleSize = Utils.s2i(Book.getTextNode(root, "samples")); processed = Utils.s2b(Book.getTextNode(root, "processed")); runtime = Utils.s2d(Book.getTextNode(root, "time", "-1.000")); + rms = Utils.s2d(Book.getTextNode(root, "rms", "-100.000")); + clipping = Utils.s2i(Book.getTextNode(root, "clipping", "0")); peak = Utils.s2d(Book.getTextNode(root, "peak", "-1.000")); isDetected = Utils.s2b(Book.getTextNode(root, "detected")); @@ -944,7 +948,7 @@ public class Sentence extends BookTreeNode implements Cacheable { int gainint = (int)(gain * 100d); gain = g; if (gint != gainint) { - CacheManager.removeFromCache(this); + refreshAllData(); peak = -1; reloadTree(); } @@ -960,7 +964,6 @@ public class Sentence extends BookTreeNode implements Cacheable { if (locked) return gain; double max = getPeakValue(false); double d = 0.708 / max; - if (d > 1d) d = 1d; if (d < low) d = low; if (d > high) d = high; setGain(d); @@ -975,7 +978,6 @@ public class Sentence extends BookTreeNode implements Cacheable { if (locked) return gain; double max = getPeakValue(false); double d = 0.708 / max; - if (d > 1d) d = 1d; setGain(d); peak = -1; getPeak(); @@ -1117,6 +1119,8 @@ public class Sentence extends BookTreeNode implements Cacheable { CacheManager.removeFromCache(Sentence.this); runtime = -1; + rms = -100d; + clipping = 0; sampleSize = -1; loadFile(); Debug.d("Ending size:", sampleSize); @@ -1685,6 +1689,8 @@ public class Sentence extends BookTreeNode implements Cacheable { sentenceNode.appendChild(Book.makeTextNode(doc, "time", getLength())); sentenceNode.appendChild(Book.makeTextNode(doc, "peak", getPeak())); sentenceNode.appendChild(Book.makeTextNode(doc, "detected", beenDetected())); + sentenceNode.appendChild(Book.makeTextNode(doc, "rms", getRMS())); + sentenceNode.appendChild(Book.makeTextNode(doc, "clipping", isClipping() ? 2 : 1)); Element gp = doc.createElement("gainpoints"); if (gainPoints != null) { for (Integer loc : gainPoints.keySet()) { @@ -1821,6 +1827,8 @@ public class Sentence extends BookTreeNode implements Cacheable { public void refreshAllData() { runtime = -1d; + rms = -100d; + clipping = 0; peak = -1d; sampleSize = -1; audioData = null; @@ -1833,6 +1841,8 @@ public class Sentence extends BookTreeNode implements Cacheable { crossEndOffset = -1; updateCrossings(); getPeakDB(); + getRMS(); + isClipping(); reloadTree(); } @@ -1849,12 +1859,12 @@ public class Sentence extends BookTreeNode implements Cacheable { gainPoints = new TreeMap(); } gainPoints.put(loc, g); - CacheManager.removeFromCache(this); + refreshAllData(); } public void removeGainPoint(Integer loc) { gainPoints.remove(loc); - CacheManager.removeFromCache(this); + refreshAllData(); } public void adjustGainPoint(Integer loc, Double adj) { @@ -1866,7 +1876,7 @@ public class Sentence extends BookTreeNode implements Cacheable { if (gp == null) return; gp += adj; gainPoints.put(loc, gp); - CacheManager.removeFromCache(this); + refreshAllData(); } public double[] calculateGains() { @@ -1900,4 +1910,55 @@ public class Sentence extends BookTreeNode implements Cacheable { } return gains; } + + public double getRMS() { + if (rms > -90d) return rms; + double[][] samples = getProcessedAudioData(); + if (samples == null) { + return -100d; + } + + double leftsq = 0d; + double rightsq = 0d; + + int c = 0; + + for (int i = crossStartOffset; i < crossEndOffset; i++) { + leftsq += (double)(samples[LEFT][i] * samples[LEFT][i]); + rightsq += (double)(samples[RIGHT][i] * samples[RIGHT][i]); + c++; + } + double left = Math.sqrt(leftsq / c); + double right = Math.sqrt(rightsq / c); + + double l10 = Math.log10((left + right) / 2d); + rms = 20d * l10; + + return rms; + } + + public boolean isClipping() { + if (clipping > 0) { + if (clipping == 1) return false; + return true; + } + + double[][] samples = getProcessedAudioData(); + if (samples == null) { + return false; + } + + clipping = 1; + for (int i = 0; i < samples[LEFT].length; i++) { + if (samples[LEFT][i] > 0.708) { + clipping = 2; + return true; + } + if (samples[RIGHT][i] > 0.708) { + clipping = 2; + return true; + } + } + return false; + } }