Some code refactoring and clean-up.

This commit is contained in:
LoRd_MuldeR 2020-10-04 17:14:21 +02:00
parent 2b17c7d53d
commit be6304d758
3 changed files with 86 additions and 56 deletions

View File

@ -153,25 +153,24 @@ As a workaround for the current situation in Java, Launch5j will (by default) co
The only downside is that additional processing is required in the application code:
```java
public class YourMainClass {
public static void main(final String[] args) {
initCommandlineArgs(args);
/* your application code goes here! */
}
private static void initCommandlineArgs(final String[] argv) {
if (System.getProperty("l5j.pid") == null) {
return; /*nothing to do*/
public class MainClass {
public static void main(final String[] args) {
initCommandlineArgs(args);
/* Your application code goes here! */
}
final String utf8enc = StandardCharsets.UTF_8.name();
for (int i = 0; i < argv.length; ++i) {
try {
argv[i] = URLDecoder.decode(argv[i], utf8enc);
} catch (Exception e) { }
}
}
/* ... */
private static void initCommandlineArgs(final String[] argv) {
if (boolify(System.getProperty("l5j.encargs"))) {
final String enc = StandardCharsets.UTF_8.name();
for (int i = 0; i < argv.length; ++i) {
try {
argv[i] = URLDecoder.decode(argv[i], enc);
} catch (Exception e) { }
}
}
}
/* ... */
}
```
@ -179,6 +178,8 @@ public class YourMainClass {
![Unicode command-line arguments](etc/img/unicode-args.png)
Please refer to the file **`example/example.java`** for the *complete* example code!
## JAR file name
Be aware that the same problem of “mangled” Unicode characters applies when the path of the JAR file is passed to the Java executable. In other words, the Java runtime *fails* to execute any JAR files whose path &ndash; file name or any directory name in the path &ndash; contains any Unicode characters that cannot be represented in the computer's *local* ANSI codepage! Unfortunately, we can **not** encode the path of the JAR file as we do with the other command-line arguments, because the Java executable requires the path of the JAR file to be passed in a non-encoded form.

View File

@ -27,15 +27,27 @@ public class Main {
}
private static void initCommandlineArgs(final String[] argv) {
if (System.getProperty("l5j.pid") == null) {
return; /*nothing to do*/
if (boolify(System.getProperty("l5j.encargs"))) {
final String enc = StandardCharsets.UTF_8.name();
for (int i = 0; i < argv.length; ++i) {
try {
argv[i] = URLDecoder.decode(argv[i], enc);
} catch (Exception e) { }
}
}
final String enc = StandardCharsets.UTF_8.name();
for (int i = 0; i < argv.length; ++i) {
}
private static boolean boolify(final String string) {
if(string != null) {
final String value = string.trim();
if(value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) {
return true;
}
try {
argv[i] = URLDecoder.decode(argv[i], enc);
} catch (Exception e) { }
return (Integer.parseInt(value) > 0);
} catch(Exception e) { }
}
return false;
}
private static String dumpCommandLine(final String[] argv) {

View File

@ -61,6 +61,9 @@ static const DWORD SPLASH_SCREEN_TIMEOUT = 30000U;
#error Unknown target platform!
#endif
// Boolean value
#define BOOLIFY(X) ((X) ? TRUE : FALSE)
/* ======================================================================== */
/* String routines */
/* ======================================================================== */
@ -1081,6 +1084,12 @@ static DWORD load_java_bitness(const HINSTANCE hinstance, const UINT id)
return ((value == 32U) || (value == 64U)) ? value : 0U;
}
static const wchar_t *get_java_full_path(const wchar_t *const jre_base_path, const wchar_t *const jre_relative_path)
{
const wchar_t *const relative_path_ptr = AVAILABLE(jre_relative_path) ? skip_leading_separator(jre_relative_path) : NULL;
return aswprintf(L"%s\\%s", jre_base_path, NOT_EMPTY(relative_path_ptr) ? relative_path_ptr: JRE_RELATIVE_PATH_DEFAULT);
}
/* ======================================================================== */
/* Command-line */
/* ======================================================================== */
@ -1144,9 +1153,8 @@ static wchar_t *encode_commandline_args(const int argc, const LPWSTR *const argv
return result_buffer;
}
static const wchar_t *encode_commandline(const wchar_t *const command_line)
static const wchar_t *encode_commandline_str(const wchar_t *const command_line)
{
#if L5J_ENCODE_ARGS
const wchar_t * encoded = NULL;
if (NOT_EMPTY(command_line))
{
@ -1159,9 +1167,43 @@ static const wchar_t *encode_commandline(const wchar_t *const command_line)
}
}
return encoded;
}
static const wchar_t *build_commandline(const DWORD pid, const wchar_t *const java_runtime_path, const wchar_t *const jar_file_path, const wchar_t *const jvm_extra_args, const wchar_t *const cmd_extra_args, const wchar_t *const cmd_input_args)
{
const wchar_t *command_line;
const wchar_t *const jarfile_short_path = get_short_path(jar_file_path);
const wchar_t *const jarfile_ptr = NOT_EMPTY(jarfile_short_path) ? jarfile_short_path : jar_file_path;
#if L5J_ENCODE_ARGS
const wchar_t *const ext_args_encoded = AVAILABLE(cmd_extra_args) ? encode_commandline_str(cmd_extra_args) : NULL;
const wchar_t *const cmd_args_encoded = NOT_EMPTY(cmd_input_args) ? encode_commandline_str(cmd_input_args) : NULL;
#else
return wcsdup(command_line);
const wchar_t *const ext_args_encoded = AVAILABLE(cmd_extra_args) ? skip_leading_spaces(cmd_extra_args) : NULL;
const wchar_t *const cmd_args_encoded = NOT_EMPTY(cmd_input_args) ? skip_leading_spaces(cmd_input_args) : NULL;
#endif
if (NOT_EMPTY(ext_args_encoded))
{
command_line = AVAILABLE(jvm_extra_args)
? aswprintf(NOT_EMPTY(cmd_args_encoded) ? L"\"%s\" %s -Dl5j.pid=%u -Dl5j.encargs=%u -jar \"%s\" %s %s" : L"\"%s\" %s -Dl5j.pid=%u -Dl5j.encargs=%u -jar \"%s\" %s", java_runtime_path, jvm_extra_args, pid, BOOLIFY(L5J_ENCODE_ARGS), jarfile_ptr, ext_args_encoded, cmd_args_encoded)
: aswprintf(NOT_EMPTY(cmd_args_encoded) ? L"\"%s\" -Dl5j.pid=%u -Dl5j.encargs=%u -jar \"%s\" %s %s" : L"\"%s\" -Dl5j.pid=%u -Dl5j.encargs=%u -jar \"%s\" %s", java_runtime_path, pid, BOOLIFY(L5J_ENCODE_ARGS), jarfile_ptr, ext_args_encoded, cmd_args_encoded);
}
else
{
command_line = AVAILABLE(jvm_extra_args)
? aswprintf(NOT_EMPTY(cmd_args_encoded) ? L"\"%s\" %s -Dl5j.pid=%u -Dl5j.encargs=%u -jar \"%s\" %s" : L"\"%s\" %s -Dl5j.pid=%u -Dl5j.encargs=%u -jar \"%s\"", java_runtime_path, jvm_extra_args, pid, BOOLIFY(L5J_ENCODE_ARGS), jarfile_ptr, cmd_args_encoded)
: aswprintf(NOT_EMPTY(cmd_args_encoded) ? L"\"%s\" -Dl5j.pid=%u -Dl5j.encargs=%u -jar \"%s\" %s" : L"\"%s\" -Dl5j.pid=%u -Dl5j.encargs=%u -jar \"%s\"", java_runtime_path, pid, BOOLIFY(L5J_ENCODE_ARGS), jarfile_ptr, cmd_args_encoded);
}
#if L5J_ENCODE_ARGS
free((void*)ext_args_encoded);
free((void*)cmd_args_encoded);
#endif
free((void*)jarfile_short_path);
return command_line;
}
/* ======================================================================== */
@ -1475,8 +1517,8 @@ static wchar_t *const DEFAULT_HEADING = L"Launch5j";
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE _hPrevInstance, PWSTR pCmdLine, int _nCmdShow)
{
int result = -1;
const wchar_t *app_heading = NULL, *mutex_name = NULL, *executable_path = NULL, *executable_directory = NULL, *jarfile_path = NULL, * jarfile_short_path = NULL,
*java_runtime_path = NULL, *jre_relative_path = NULL, *jvm_extra_args = NULL, *cmd_extra_args = NULL, *cmd_args_encoded = NULL, *ext_args_encoded = NULL, *command_line = NULL;
const wchar_t *app_heading = NULL, *mutex_name = NULL, *executable_path = NULL, *executable_directory = NULL, *jarfile_path = NULL,
*java_runtime_path = NULL, *jre_relative_path = NULL, *jvm_extra_args = NULL, *cmd_extra_args = NULL, *command_line = NULL;
HANDLE mutex_handle = NULL;
DWORD java_required_bitness = 0U;
ULONGLONG java_required_ver_min = 0ULL, java_required_ver_max = 0ULL;
@ -1578,9 +1620,6 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE _hPrevInstance, PWSTR pCmdLin
}
#endif
// Convert JAR file path to short form
jarfile_short_path = get_short_path(jarfile_path);
// Find the Java runtime executable path (possibly from the registry)
#if L5J_DETECT_REGISTRY
java_required_ver_min = load_java_version(hInstance, ID_STR_JAVAMIN, (8ull << 48));
@ -1594,13 +1633,12 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE _hPrevInstance, PWSTR pCmdLin
}
#else
jre_relative_path = load_string(hInstance, ID_STR_JREPATH);
const wchar_t *const jre_relative_path_offset = AVAILABLE(jre_relative_path) ? skip_leading_separator(jre_relative_path) : NULL;
if (!(java_runtime_path = aswprintf(L"%s\\%s", executable_directory, NOT_EMPTY(jre_relative_path_offset) ? jre_relative_path_offset: JRE_RELATIVE_PATH_DEFAULT)))
if (!(java_runtime_path = get_java_full_path(executable_path, jre_relative_path)))
{
show_message(hwnd, MB_ICONERROR | MB_TOPMOST, APP_HEADING, L"The path of the Java runtime could not be determined!");
goto cleanup;
}
if (!file_is_executable(java_runtime_path))
if (!BOOLIFY(file_is_executable(java_runtime_path)))
{
show_message_format(hwnd, MB_ICONERROR | MB_TOPMOST, APP_HEADING, L"The Java runtime could not be found or is invalid:\n\n%s\n\n\nRe-installing the application may fix the problem!", java_runtime_path);
goto cleanup;
@ -1611,26 +1649,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE _hPrevInstance, PWSTR pCmdLin
jvm_extra_args = load_string(hInstance, ID_STR_JVMARGS);
cmd_extra_args = load_string(hInstance, ID_STR_CMDARGS);
// Get user-provided command-line args
cmd_args_encoded = encode_commandline(pCmdLine);
// Build command-line
if (AVAILABLE(cmd_extra_args) && (ext_args_encoded = encode_commandline(cmd_extra_args)))
{
const wchar_t *const jarfile_ptr = NOT_EMPTY(jarfile_short_path) ? jarfile_short_path : jarfile_path;
command_line = AVAILABLE(jvm_extra_args)
? aswprintf(NOT_EMPTY(cmd_args_encoded) ? L"\"%s\" %s -Dl5j.pid=%u -jar \"%s\" %s %s" : L"\"%s\" %s -Dl5j.pid=%u -jar \"%s\" %s", java_runtime_path, jvm_extra_args, pid, jarfile_ptr, ext_args_encoded, cmd_args_encoded)
: aswprintf(NOT_EMPTY(cmd_args_encoded) ? L"\"%s\" -Dl5j.pid=%u -jar \"%s\" %s %s" : L"\"%s\" -Dl5j.pid=%u -jar \"%s\" %s", java_runtime_path, pid, jarfile_ptr, ext_args_encoded, cmd_args_encoded);
}
else
{
const wchar_t *const jarfile_ptr = NOT_EMPTY(jarfile_short_path) ? jarfile_short_path : jarfile_path;
command_line = AVAILABLE(jvm_extra_args)
? aswprintf(NOT_EMPTY(cmd_args_encoded) ? L"\"%s\" %s -Dl5j.pid=%u -jar \"%s\" %s" : L"\"%s\" %s -Dl5j.pid=%u -jar \"%s\"", java_runtime_path, jvm_extra_args, pid, jarfile_ptr, cmd_args_encoded)
: aswprintf(NOT_EMPTY(cmd_args_encoded) ? L"\"%s\" -Dl5j.pid=%u -jar \"%s\" %s" : L"\"%s\" -Dl5j.pid=%u -jar \"%s\"", java_runtime_path, pid, jarfile_ptr, cmd_args_encoded);
}
// Make sure command-line was created
command_line = build_commandline(pid, java_runtime_path, jarfile_path, jvm_extra_args, cmd_extra_args, pCmdLine);
if (!command_line)
{
show_message(hwnd, MB_ICONERROR | MB_TOPMOST, APP_HEADING, L"The Java command-line could not be generated!");
@ -1699,12 +1719,9 @@ cleanup:
free((void*)jvm_extra_args);
free((void*)cmd_extra_args);
free((void*)ext_args_encoded);
free((void*)cmd_args_encoded);
free((void*)command_line);
free((void*)java_runtime_path);
free((void*)jarfile_path);
free((void*)jarfile_short_path);
free((void*)jre_relative_path);
free((void*)executable_directory);
free((void*)executable_path);