diff --git a/plexus-compiler-its/src/main/it/issues-351/invoker.properties b/plexus-compiler-its/src/main/it/issues-351/invoker.properties
new file mode 100644
index 000000000..b0d469e98
--- /dev/null
+++ b/plexus-compiler-its/src/main/it/issues-351/invoker.properties
@@ -0,0 +1,19 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+invoker.os.family = windows
+invoker.goals = clean compile
diff --git a/plexus-compiler-its/src/main/it/issues-351/pom.xml b/plexus-compiler-its/src/main/it/issues-351/pom.xml
new file mode 100644
index 000000000..70827bbae
--- /dev/null
+++ b/plexus-compiler-its/src/main/it/issues-351/pom.xml
@@ -0,0 +1,89 @@
+
+
+
+
+ 4.0.0
+
+ org.codehaus.plexus.compiler.it
+ issues-351
+ 1.0-SNAPSHOT
+
+ Issue 351: preserve multiline compiler arguments on Windows
+
+
+ UTF-8
+ @project.version@
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ @maven.compiler.version@
+
+ true
+ 11
+
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED
+ -J--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED
+ -J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED
+ -J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED
+ -XDcompilePolicy=simple
+ -Xplugin:ErrorProne
+ -Xep:DeadException:WARN
+
+
+
+ com.google.errorprone
+ error_prone_core
+ 2.24.1
+
+
+
+
+
+ org.codehaus.plexus
+ plexus-compiler-api
+ ${plexus.compiler.version}
+
+
+ org.codehaus.plexus
+ plexus-compiler-manager
+ ${plexus.compiler.version}
+
+
+ org.codehaus.plexus
+ plexus-compiler-javac
+ ${plexus.compiler.version}
+
+
+
+
+
+
diff --git a/plexus-compiler-its/src/main/it/issues-351/src/main/java/foo/Example.java b/plexus-compiler-its/src/main/it/issues-351/src/main/java/foo/Example.java
new file mode 100644
index 000000000..76cc30e42
--- /dev/null
+++ b/plexus-compiler-its/src/main/it/issues-351/src/main/java/foo/Example.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package foo;
+
+public class Example {
+ public void createException() {
+ new RuntimeException();
+ }
+}
diff --git a/plexus-compiler-its/src/main/it/issues-351/verify.groovy b/plexus-compiler-its/src/main/it/issues-351/verify.groovy
new file mode 100644
index 000000000..bbede9184
--- /dev/null
+++ b/plexus-compiler-its/src/main/it/issues-351/verify.groovy
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+assert new File(basedir, 'target/classes/foo/Example.class').exists()
+
+def buildLog = new File(basedir, 'build.log').getText('UTF-8')
+assert buildLog.contains('[DeadException] Exception created but not thrown')
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 9bf8fabe8..8d93e788a 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
@@ -1068,9 +1068,7 @@ private File createFileWithArguments(String[] args, String outputDirectory) thro
writer = new PrintWriter(new FileWriter(tempFile));
for (String arg : args) {
- String argValue = arg.replace(File.separatorChar, '/');
- writer.write("\"" + argValue + "\"");
- writer.println();
+ writer.println(quoteArgument(arg));
}
writer.flush();
@@ -1083,6 +1081,41 @@ private File createFileWithArguments(String[] args, String outputDirectory) thro
}
}
+ /**
+ * Quotes an argument according to javac command-line argument file syntax.
+ */
+ static String quoteArgument(String argument) {
+ StringBuilder quoted = new StringBuilder(argument.length() + 2);
+ quoted.append('"');
+ for (int i = 0; i < argument.length(); i++) {
+ char c = argument.charAt(i);
+ switch (c) {
+ case '\\':
+ quoted.append("\\\\");
+ break;
+ case '"':
+ quoted.append("\\\"");
+ break;
+ case '\n':
+ quoted.append("\\n");
+ break;
+ case '\r':
+ quoted.append("\\r");
+ break;
+ case '\t':
+ quoted.append("\\t");
+ break;
+ case '\f':
+ quoted.append("\\f");
+ break;
+ default:
+ quoted.append(c);
+ break;
+ }
+ }
+ return quoted.append('"').toString();
+ }
+
/**
* Get the path of the javac tool executable to use.
* Either given through explicit configuration or via {@link #getJavacExecutable()}.
diff --git a/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/JavacCompilerTest.java b/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/JavacCompilerTest.java
index 82a311cd9..fec1e4c42 100644
--- a/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/JavacCompilerTest.java
+++ b/plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/JavacCompilerTest.java
@@ -119,4 +119,29 @@ void testExtractMajorAndMinorVersion() {
assertEquals("21", JavacCompiler.extractMajorAndMinorVersion("javac 21"));
assertEquals("1.8", JavacCompiler.extractMajorAndMinorVersion("javac 1.8.0_432"));
}
+
+ @ParameterizedTest(name = "{0}")
+ @MethodSource("quoteArgumentArguments")
+ void quoteArgument(String description, String argument, String expected) {
+ assertEquals(expected, JavacCompiler.quoteArgument(argument));
+ }
+
+ private static Stream quoteArgumentArguments() {
+ return Stream.of(
+ Arguments.of("empty", "", "\"\""),
+ Arguments.of("plain", "-Xlint", "\"-Xlint\""),
+ Arguments.of("spaces", "two words", "\"two words\""),
+ Arguments.of("double quote", "say \"hello\"", "\"say \\\"hello\\\"\""),
+ Arguments.of(
+ "Windows path",
+ "C:\\Program Files\\Java\\bin\\javac.exe",
+ "\"C:\\\\Program Files\\\\Java\\\\bin\\\\javac.exe\""),
+ Arguments.of("trailing backslash", "C:\\temp\\", "\"C:\\\\temp\\\\\""),
+ Arguments.of("literal backslash-n", "-Dvalue=\\n", "\"-Dvalue=\\\\n\""),
+ Arguments.of(
+ "control whitespace",
+ "line1\nline2\rline3\tline4\fline5",
+ "\"line1\\nline2\\rline3\\tline4\\fline5\""),
+ Arguments.of("backslash and newline", "line1\\\nline2", "\"line1" + "\\\\" + "\\n" + "line2\""));
+ }
}