From 0d39fc9fc8081d975319bee212a36f154b3571c6 Mon Sep 17 00:00:00 2001 From: Sylwester Lachiewicz Date: Mon, 24 Aug 2026 21:57:38 +0200 Subject: [PATCH 1/3] Skip -processor when the annotation processor array is empty JavacCompiler guarded the -processor flag on a null check alone, so a zero-length array produced -processor followed by an empty argument and javac failed to resolve the empty name. EclipseJavaCompiler already guards on length as well; this aligns the two. Fixes #512 --- .../plexus/compiler/javac/JavacCompiler.java | 8 ++--- .../javac/AbstractJavacCompilerTest.java | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java b/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java index e6f7223e7..d3e54e503 100644 --- a/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java +++ b/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java @@ -421,15 +421,15 @@ public static String[] buildCompilerArguments( if (config.getProc() != null) { args.add("-proc:" + config.getProc()); } - if (config.getAnnotationProcessors() != null) { + String[] annotationProcessors = config.getAnnotationProcessors(); + if (annotationProcessors != null && annotationProcessors.length > 0) { args.add("-processor"); - String[] procs = config.getAnnotationProcessors(); StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < procs.length; i++) { + for (int i = 0; i < annotationProcessors.length; i++) { if (i > 0) { buffer.append(","); } - buffer.append(procs[i]); + buffer.append(annotationProcessors[i]); } args.add(buffer.toString()); } diff --git a/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/AbstractJavacCompilerTest.java b/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/AbstractJavacCompilerTest.java index b3d33045f..72e7027a9 100644 --- a/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/AbstractJavacCompilerTest.java +++ b/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/AbstractJavacCompilerTest.java @@ -38,6 +38,9 @@ import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; /** * @author Jason van Zyl @@ -200,6 +203,33 @@ public void internalTest( assertArrayEquals(actualArguments, expectedArguments.toArray(new String[0])); } + @Test + public void testBuildCompilerArgsEmptyAnnotationProcessors() { + CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); + compilerConfiguration.setOutputLocation("/output"); + compilerConfiguration.setAnnotationProcessors(new String[0]); + + String[] actualArguments = JavacCompiler.buildCompilerArguments(compilerConfiguration, new String[0], "17"); + + assertFalse( + Arrays.asList(actualArguments).contains("-processor"), + "an empty processor array must not produce -processor with an empty argument"); + } + + @Test + public void testBuildCompilerArgsAnnotationProcessors() { + CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); + compilerConfiguration.setOutputLocation("/output"); + compilerConfiguration.setAnnotationProcessors(new String[] {"com.example.First", "com.example.Second"}); + + List actualArguments = + Arrays.asList(JavacCompiler.buildCompilerArguments(compilerConfiguration, new String[0], "17")); + + int index = actualArguments.indexOf("-processor"); + assertTrue(index >= 0, "-processor must be present for a non-empty processor array"); + assertEquals("com.example.First,com.example.Second", actualArguments.get(index + 1)); + } + @Test public void testBuildCompilerArgs13() { List expectedArguments = new ArrayList<>(); From 8df867408c2c7a3ec3ed78231c74ce19d2f5af52 Mon Sep 17 00:00:00 2001 From: Sylwester Lachiewicz Date: Mon, 24 Aug 2026 22:14:27 +0200 Subject: [PATCH 2/3] Skip blank annotation processor names in javac and eclipse Both compilers decided whether to pass -processor from the array's length alone, so an array of blank names produced -processor with an empty or comma-only argument. Filtering blanks covers the zero-length case too, and matches how maven-compiler-plugin normalizes the same field caller-side. Fixes #512 --- .../compiler/eclipse/EclipseJavaCompiler.java | 40 ++++++++++++++----- .../plexus/compiler/javac/JavacCompiler.java | 38 +++++++++++++----- .../javac/AbstractJavacCompilerTest.java | 28 +++++++++++++ 3 files changed, 85 insertions(+), 21 deletions(-) diff --git a/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java b/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java index 3c7f4f4c1..aeefba68f 100644 --- a/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java +++ b/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java @@ -173,23 +173,16 @@ public CompilerResult performCompile(CompilerConfiguration config) throws Compil } // now add jdk 1.6 annotation processing related parameters - String[] annotationProcessors = config.getAnnotationProcessors(); + String annotationProcessors = joinAnnotationProcessors(config.getAnnotationProcessors()); List processorPathEntries = config.getProcessorPathEntries(); List processorModulePathEntries = config.getProcessorModulePathEntries(); - if ((annotationProcessors != null && annotationProcessors.length > 0) + if (!annotationProcessors.isEmpty() || (processorPathEntries != null && processorPathEntries.size() > 0) || (processorModulePathEntries != null && processorModulePathEntries.size() > 0)) { - if (annotationProcessors != null && annotationProcessors.length > 0) { + if (!annotationProcessors.isEmpty()) { args.add("-processor"); - StringBuilder sb = new StringBuilder(); - for (String ap : annotationProcessors) { - if (sb.length() > 0) { - sb.append(','); - } - sb.append(ap); - } - args.add(sb.toString()); + args.add(annotationProcessors); } if (processorPathEntries != null && processorPathEntries.size() > 0) { @@ -625,4 +618,29 @@ private String decodeVersion(String versionSpec) { } return versionSpec; } + + /** + * Joins the configured annotation processor names, skipping blank entries. + *

+ * Maven maps an explicitly empty {@code } element to an array of blank + * strings rather than to an empty array, and passing those on produces {@code -processor} with + * an empty processor name. + * + * @param annotationProcessors the configured names, possibly {@code null} + * @return the non-blank names joined by commas, or an empty string if there are none + */ + private static String joinAnnotationProcessors(String[] annotationProcessors) { + StringBuilder buffer = new StringBuilder(); + if (annotationProcessors != null) { + for (String annotationProcessor : annotationProcessors) { + if (annotationProcessor != null && !annotationProcessor.trim().isEmpty()) { + if (buffer.length() > 0) { + buffer.append(','); + } + buffer.append(annotationProcessor); + } + } + } + return buffer.toString(); + } } diff --git a/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java b/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java index d3e54e503..d5a63a7f6 100644 --- a/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java +++ b/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java @@ -371,6 +371,31 @@ public String[] createCommandLine(CompilerConfiguration config) throws CompilerE return buildCompilerArguments(config, getSourceFiles(config), javacVersion); } + /** + * Joins the configured annotation processor names, skipping blank entries. + *

+ * Maven maps an explicitly empty {@code } element to an array of blank + * strings rather than to an empty array, and passing those on produces {@code -processor} with + * an empty processor name, which javac cannot resolve. + * + * @param annotationProcessors the configured names, possibly {@code null} + * @return the non-blank names joined by commas, or an empty string if there are none + */ + private static String joinAnnotationProcessors(String[] annotationProcessors) { + StringBuilder buffer = new StringBuilder(); + if (annotationProcessors != null) { + for (String annotationProcessor : annotationProcessors) { + if (annotationProcessor != null && !annotationProcessor.trim().isEmpty()) { + if (buffer.length() > 0) { + buffer.append(","); + } + buffer.append(annotationProcessor); + } + } + } + return buffer.toString(); + } + public static String[] buildCompilerArguments( CompilerConfiguration config, String[] sourceFiles, String javacVersion) { List args = new ArrayList<>(); @@ -421,17 +446,10 @@ public static String[] buildCompilerArguments( if (config.getProc() != null) { args.add("-proc:" + config.getProc()); } - String[] annotationProcessors = config.getAnnotationProcessors(); - if (annotationProcessors != null && annotationProcessors.length > 0) { + String annotationProcessors = joinAnnotationProcessors(config.getAnnotationProcessors()); + if (!annotationProcessors.isEmpty()) { args.add("-processor"); - StringBuilder buffer = new StringBuilder(); - for (int i = 0; i < annotationProcessors.length; i++) { - if (i > 0) { - buffer.append(","); - } - buffer.append(annotationProcessors[i]); - } - args.add(buffer.toString()); + args.add(annotationProcessors); } if (config.getProcessorPathEntries() != null && !config.getProcessorPathEntries().isEmpty()) { diff --git a/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/AbstractJavacCompilerTest.java b/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/AbstractJavacCompilerTest.java index 72e7027a9..d8e906773 100644 --- a/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/AbstractJavacCompilerTest.java +++ b/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/AbstractJavacCompilerTest.java @@ -216,6 +216,34 @@ public void testBuildCompilerArgsEmptyAnnotationProcessors() { "an empty processor array must not produce -processor with an empty argument"); } + @Test + public void testBuildCompilerArgsBlankAnnotationProcessors() { + CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); + compilerConfiguration.setOutputLocation("/output"); + compilerConfiguration.setAnnotationProcessors(new String[] {"", ""}); + + String[] actualArguments = JavacCompiler.buildCompilerArguments(compilerConfiguration, new String[0], "17"); + + assertFalse( + Arrays.asList(actualArguments).contains("-processor"), + "an array of blank processor names must not produce -processor"); + } + + @Test + public void testBuildCompilerArgsMixedBlankAnnotationProcessors() { + CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); + compilerConfiguration.setOutputLocation("/output"); + compilerConfiguration.setAnnotationProcessors( + new String[] {"", "com.example.First", " ", "com.example.Second"}); + + List actualArguments = + Arrays.asList(JavacCompiler.buildCompilerArguments(compilerConfiguration, new String[0], "17")); + + int index = actualArguments.indexOf("-processor"); + assertTrue(index >= 0, "-processor must be present when at least one name is not blank"); + assertEquals("com.example.First,com.example.Second", actualArguments.get(index + 1)); + } + @Test public void testBuildCompilerArgsAnnotationProcessors() { CompilerConfiguration compilerConfiguration = new CompilerConfiguration(); From f5f1ad26b20c2538d3f0bf7eeb8071a2c33c3be8 Mon Sep 17 00:00:00 2001 From: Sylwester Lachiewicz Date: Mon, 24 Aug 2026 22:16:56 +0200 Subject: [PATCH 3/3] Share one annotation processor normalization helper Both compilers had their own copy of the blank-filtering loop. Two guards that agree today are how these two came to disagree in the first place, so route both through joinAnnotationProcessors on AbstractCompiler. --- .../plexus/compiler/AbstractCompiler.java | 27 +++++++++++++++++++ .../compiler/eclipse/EclipseJavaCompiler.java | 25 ----------------- .../plexus/compiler/javac/JavacCompiler.java | 25 ----------------- 3 files changed, 27 insertions(+), 50 deletions(-) diff --git a/plexus-compiler-api/src/main/java/org/codehaus/plexus/compiler/AbstractCompiler.java b/plexus-compiler-api/src/main/java/org/codehaus/plexus/compiler/AbstractCompiler.java index 0acb4694f..5957950f9 100644 --- a/plexus-compiler-api/src/main/java/org/codehaus/plexus/compiler/AbstractCompiler.java +++ b/plexus-compiler-api/src/main/java/org/codehaus/plexus/compiler/AbstractCompiler.java @@ -295,4 +295,31 @@ private static String getRelativeWorkingDirectory(CompilerConfiguration config) } return to; } + + /** + * Joins the configured annotation processor names, skipping blank entries. + *

+ * Maven maps an explicitly empty {@code } element to an array holding + * blank strings rather than to an empty array. Passing those on yields {@code -processor} with + * an empty processor name, which no compiler can resolve. Callers should omit the option + * entirely when this returns an empty string. + * + * @param annotationProcessors the configured names, possibly {@code null} + * @return the non-blank names joined by commas, or an empty string if none remain + * @since 2.17.1 + */ + protected static String joinAnnotationProcessors(String[] annotationProcessors) { + StringBuilder buffer = new StringBuilder(); + if (annotationProcessors != null) { + for (String annotationProcessor : annotationProcessors) { + if (annotationProcessor != null && !annotationProcessor.trim().isEmpty()) { + if (buffer.length() > 0) { + buffer.append(','); + } + buffer.append(annotationProcessor); + } + } + } + return buffer.toString(); + } } diff --git a/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java b/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java index aeefba68f..bee72a0fc 100644 --- a/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java +++ b/plexus-compilers/plexus-compiler-eclipse/src/main/java/org/codehaus/plexus/compiler/eclipse/EclipseJavaCompiler.java @@ -618,29 +618,4 @@ private String decodeVersion(String versionSpec) { } return versionSpec; } - - /** - * Joins the configured annotation processor names, skipping blank entries. - *

- * Maven maps an explicitly empty {@code } element to an array of blank - * strings rather than to an empty array, and passing those on produces {@code -processor} with - * an empty processor name. - * - * @param annotationProcessors the configured names, possibly {@code null} - * @return the non-blank names joined by commas, or an empty string if there are none - */ - private static String joinAnnotationProcessors(String[] annotationProcessors) { - StringBuilder buffer = new StringBuilder(); - if (annotationProcessors != null) { - for (String annotationProcessor : annotationProcessors) { - if (annotationProcessor != null && !annotationProcessor.trim().isEmpty()) { - if (buffer.length() > 0) { - buffer.append(','); - } - buffer.append(annotationProcessor); - } - } - } - return buffer.toString(); - } } diff --git a/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java b/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java index d5a63a7f6..f1b18d4ae 100644 --- a/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java +++ b/plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java @@ -371,31 +371,6 @@ public String[] createCommandLine(CompilerConfiguration config) throws CompilerE return buildCompilerArguments(config, getSourceFiles(config), javacVersion); } - /** - * Joins the configured annotation processor names, skipping blank entries. - *

- * Maven maps an explicitly empty {@code } element to an array of blank - * strings rather than to an empty array, and passing those on produces {@code -processor} with - * an empty processor name, which javac cannot resolve. - * - * @param annotationProcessors the configured names, possibly {@code null} - * @return the non-blank names joined by commas, or an empty string if there are none - */ - private static String joinAnnotationProcessors(String[] annotationProcessors) { - StringBuilder buffer = new StringBuilder(); - if (annotationProcessors != null) { - for (String annotationProcessor : annotationProcessors) { - if (annotationProcessor != null && !annotationProcessor.trim().isEmpty()) { - if (buffer.length() > 0) { - buffer.append(","); - } - buffer.append(annotationProcessor); - } - } - } - return buffer.toString(); - } - public static String[] buildCompilerArguments( CompilerConfiguration config, String[] sourceFiles, String javacVersion) { List args = new ArrayList<>();