From 1537fb992256fbb0be017003457783f55407b04a Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 4 Aug 2025 14:27:09 +0200 Subject: [PATCH 1/2] Strips leading zeros when preparing version info Closes #448 --- .../Launch4jFileVersionGenerator.java | 30 +++++++++++++++- .../Launch4jFileVersionGeneratorTest.java | 36 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGenerator.java b/src/main/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGenerator.java index b28d3b10..c8246123 100644 --- a/src/main/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGenerator.java +++ b/src/main/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGenerator.java @@ -39,6 +39,7 @@ private Launch4jFileVersionGenerator() { * For shorter versions like "x.x.x" it will append zeros (to the 4th level) at the end like "x.x.x.0". * Every text flag like "-SNAPSHOT" or "-alpha" will be cut off. * Too many nested numbers (more than 4 levels) will be cut off as well: "1.2.3.4.5.6" into "1.2.3.4". + * Leading zeros in version components are stripped to avoid "digit exceeds base" errors in windres. *

* Param should be taken from MavenProject property: * @param projectVersion as ${project.version} @@ -53,7 +54,8 @@ public static String generate(String projectVersion) { } String versionLevels = removeTextFlags(projectVersion); - String limitedVersionLevels = cutOffTooManyNestedLevels(versionLevels); + String normalizedVersionLevels = stripLeadingZeros(versionLevels); + String limitedVersionLevels = cutOffTooManyNestedLevels(normalizedVersionLevels); return appendMissingNestedLevelsByZeros(limitedVersionLevels); } @@ -68,6 +70,32 @@ private static String removeTextFlags(String version) { } } + /** + * Strips leading zeros from each version component to prevent "digit exceeds base" errors in windres. + * For example, "302.08.01" becomes "302.8.1". + * Special case: "0" remains "0" (doesn't become empty string). + * + * @param version version string with components separated by dots + * @return version string with leading zeros stripped from each component + */ + private static String stripLeadingZeros(String version) { + String[] levels = version.split("\\."); + + for (int i = 0; i < levels.length; i++) { + // Parse as integer and convert back to string to remove leading zeros + // This handles the special case where "000" becomes "0" + try { + levels[i] = String.valueOf(Integer.parseInt(levels[i])); + } catch (NumberFormatException e) { + // This should not happen given the regex validation, but keep original if it does + // The existing validation should have caught invalid numbers already + throw new IllegalArgumentException("Invalid number format in version component: " + levels[i], e); + } + } + + return String.join(".", levels); + } + private static String cutOffTooManyNestedLevels(String versionLevels) { String[] levels = versionLevels.split("\\."); diff --git a/src/test/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGeneratorTest.java b/src/test/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGeneratorTest.java index faaa032b..cf60b335 100644 --- a/src/test/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGeneratorTest.java +++ b/src/test/java/com/akathist/maven/plugins/launch4j/generators/Launch4jFileVersionGeneratorTest.java @@ -89,4 +89,40 @@ public void shouldCutOffTooManyNestedDigits(String projectVersion, String expect // then assertEquals(expected, launch4jFileVersion); } + + @Test + @Parameters({ + "302.08, 302.8.0.0", + "1.02.3, 1.2.3.0", + "01.02.03.04, 1.2.3.4", + "10.00.01, 10.0.1.0", + "0.08.09, 0.8.9.0", + "302.08-SNAPSHOT, 302.8.0.0", + "1.02.03.04.05.06, 1.2.3.4", + "000.001.002, 0.1.2.0" + }) + public void shouldStripLeadingZerosFromVersionComponents(String projectVersion, String expected) { + // when + final String launch4jFileVersion = Launch4jFileVersionGenerator.generate(projectVersion); + + // then + assertEquals(expected, launch4jFileVersion); + } + + @Test + @Parameters({ + "0, 0.0.0.0", + "00, 0.0.0.0", + "000, 0.0.0.0", + "0.0, 0.0.0.0", + "00.00, 0.0.0.0", + "000.000, 0.0.0.0" + }) + public void shouldHandleZeroVersionsCorrectly(String projectVersion, String expected) { + // when + final String launch4jFileVersion = Launch4jFileVersionGenerator.generate(projectVersion); + + // then + assertEquals(expected, launch4jFileVersion); + } } \ No newline at end of file From 2bb85a595f5a02dcac8e271e4149d56f46ee3d45 Mon Sep 17 00:00:00 2001 From: Lukasz Lenart Date: Mon, 4 Aug 2025 14:27:22 +0200 Subject: [PATCH 2/2] Adds Claude Code specific settings --- .gitignore | 1 + CLAUDE.md | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 CLAUDE.md diff --git a/.gitignore b/.gitignore index 96674bce..d998d68f 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ target/* .idea .java-version .mvn/wrapper/maven-wrapper.jar +.claude diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..4b3b49a6 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,110 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +This is the Launch4j Maven Plugin, which wraps Java JAR files in Windows executables using the Launch4j utility. The plugin integrates Launch4j functionality into the Maven build process, allowing developers to create Windows executables as part of their Maven builds. + +## Core Architecture + +### Main Components + +- **Launch4jMojo.java** (`src/main/java/com/akathist/maven/plugins/launch4j/Launch4jMojo.java`): The main Maven plugin class that handles the launch4j goal execution +- **Configuration Classes**: POJO classes for plugin configuration (ClassPath, Jre, VersionInfo, etc.) +- **Generator Classes** (`src/main/java/com/akathist/maven/plugins/launch4j/generators/`): Handle generation of copyright and version info +- **ResourceIO** (`src/main/java/com/akathist/maven/plugins/launch4j/tools/ResourceIO.java`): Utility for handling resources + +### Key Plugin Structure + +- Plugin binds to the `package` phase by default +- Supports both GUI and console application types +- Handles dependency resolution in `runtime` and `compile` scopes +- Thread-safe execution with optional parallel execution control +- Can load configuration from external Launch4j XML files via `` parameter + +## Build and Development Commands + +### Standard Maven Commands +```bash +# Build the plugin +mvn clean compile + +# Run tests +mvn test + +# Full build with tests +mvn clean test + +# Package the plugin +mvn clean package + +# Install to local repository +mvn clean install +``` + +### Testing +- Uses JUnit 4.13.2 with JUnitParams and Mockito +- Maven Plugin Testing Harness for integration tests +- Test files located in `src/test/java/` + +### Documentation Generation +```bash +# Generate plugin documentation site +mvn site + +# Generate plugin documentation reports +mvn project-info-reports:dependencies +mvn plugin:report +``` + +## Important Configuration Details + +### Maven Plugin Configuration +- The plugin uses Maven Plugin API 3.9.11 +- Minimum Java version: 1.8 +- Launch4j version: 3.50 +- Supports Maven 3.6.x and above + +### Key Plugin Parameters +- ``: Load configuration from external Launch4j XML file (default: `${project.basedir}/src/main/resources/${project.artifactId}-launch4j.xml`) +- ``: Output executable path (default: `${project.build.directory}/${project.artifactId}.exe`) +- ``: JAR file to wrap (default: `${project.build.directory}/${project.build.finalName}.jar`) +- ``: Skip plugin execution (can also use `-DskipLaunch4j` property) +- ``: Disable automatic VersionInfo defaults + +### ClassPath Configuration +- ``: Include Maven dependencies in classpath (default: true) +- ``: Prefix for JAR paths (useful for lib/ directories) +- `` and ``: Add custom classpath entries + +## Architecture Notes + +### Plugin Execution Flow +1. Validates configuration and parameters +2. Resolves platform-specific Launch4j binaries from Maven repositories +3. Builds configuration object from Maven plugin parameters +4. Optionally loads external Launch4j configuration file +5. Applies default values for VersionInfo if not disabled +6. Executes Launch4j Builder to create Windows executable + +### Platform Support +- Runs on Windows, Linux, macOS, and Solaris +- Downloads platform-specific Launch4j binaries as Maven artifacts +- Linux 64-bit uses `linux64` platform, 32-bit uses `linux32` + +### Version Info Defaults +The plugin automatically provides default values for VersionInfo parameters based on Maven project properties: +- File version from project version +- Product name from project name +- Company/copyright from organization +- Description from project description + +This behavior can be disabled with `true`. + +## Documentation References + +- Main documentation: `src/main/resources/README.adoc` +- Parameter reference: `src/main/resources/MOJO.md` +- Version info details: `src/main/resources/VERSIONINFO.md` +- Launch4j documentation: http://launch4j.sourceforge.net/docs.html \ No newline at end of file