Auto create shebang executable

Change-Id: I7105b82656b641910326d7bc38ce615d930ec04d
diff --git a/app/build.gradle b/app/build.gradle
index c50eecb..46e0d2a 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -136,8 +136,33 @@
     }
 }
 
+// Concatenate shebang + shaded jar into an executable launcher
+tasks.register('assembleShebangExecutable') {
+    dependsOn shadowJar
+    inputs.file(rootProject.file("korapxmltool.shebang"))
+    outputs.file(new File(shadowJar.archiveFile.get().asFile.parent, "korapxmltool"))
+
+    doLast {
+        def shebang = rootProject.file("korapxmltool.shebang")
+        if (!shebang.exists()) {
+            throw new GradleException("Missing shebang stub: ${shebang}")
+        }
+
+        def targetJar = shadowJar.archiveFile.get().asFile
+        def targetExec = new File(targetJar.parent, "korapxmltool")
+
+        targetExec.withOutputStream { os ->
+            os << shebang.bytes
+            os << targetJar.bytes
+        }
+        targetExec.setExecutable(true, true)
+        println "Created executable launcher: ${targetExec}"
+    }
+}
+
 tasks.named('build') {
     dependsOn createJarSymlink
+    dependsOn assembleShebangExecutable
 }
 
 
diff --git a/korapxmltool.shebang b/korapxmltool.shebang
new file mode 100644
index 0000000..d0590ee
--- /dev/null
+++ b/korapxmltool.shebang
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+# Shebang header for korapxmltool to auto-enable native access on Java 25+
+# Usage:
+#   cat korapxmltool.shebang app/build/libs/korapxmltool.jar > korapxmltool
+#   chmod +x korapxmltool
+# (Run `zip -A korapxmltool` if your unzip/java complains about prepended bytes.)
+
+set -euo pipefail
+
+# Add native access flag if not already present
+EXTRA_OPTS=()
+if [[ "${JDK_JAVA_OPTIONS:-}" != *"--enable-native-access="* ]]; then
+  EXTRA_OPTS+=(--enable-native-access=ALL-UNNAMED)
+fi
+
+exec java "${EXTRA_OPTS[@]}" -jar "$0" "$@"