Skip to content

Commit 2b6c9b5

Browse files
committed
codehaus-plexus#420: fix detection of java version when JAVA_TOOL_OPTIONS is set
1 parent bdc011a commit 2b6c9b5

File tree

5 files changed

+98
-2
lines changed

5 files changed

+98
-2
lines changed

Diff for: plexus-compilers/plexus-compiler-javac/src/main/java/org/codehaus/plexus/compiler/javac/JavacCompiler.java

+32-2
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,16 @@ public class JavacCompiler extends AbstractCompiler {
113113
private final Deque<Class<?>> javacClasses = new ConcurrentLinkedDeque<>();
114114

115115
private static final Pattern JAVA_MAJOR_AND_MINOR_VERSION_PATTERN = Pattern.compile("\\d+(\\.\\d+)?");
116+
private static final String JAVAC_PREFIX = "javac";
117+
118+
/**
119+
* List of variable that may produce an output "Picked up %s: %s\n".
120+
* <p>
121+
* There may be more, but for Jenkins withMaven, this is enough.
122+
*
123+
* @see <a href="https://github.com/openjdk/jdk/blob/81e43114eca5199a0d816c02f50ecb6bc370135b/src/hotspot/share/runtime/arguments.cpp#L3074">arguments.cpp</a>
124+
*/
125+
private static final String[] PICKED_ENV_VARS = {"_JAVA_OPTIONS", "JAVA_TOOL_OPTIONS"};
116126

117127
/** Cache of javac version per executable (never invalidated) */
118128
private static final Map<String, String> VERSION_PER_EXECUTABLE = new ConcurrentHashMap<>();
@@ -151,6 +161,7 @@ private String getOutOfProcessJavacVersion(String executable) throws CompilerExc
151161
* up to 21 (https://docs.oracle.com/en/java/javase/21/docs/specs/man/javac.html#standard-options)
152162
*/
153163
cli.addArguments(new String[] {"-version"}); //
164+
154165
CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();
155166
try {
156167
int exitCode = CommandLineUtils.executeCommandLine(cli, out, out);
@@ -161,20 +172,39 @@ private String getOutOfProcessJavacVersion(String executable) throws CompilerExc
161172
} catch (CommandLineException e) {
162173
throw new CompilerException("Error while executing the external compiler " + executable, e);
163174
}
164-
version = extractMajorAndMinorVersion(out.getOutput());
175+
176+
/*
177+
* javac will output the content of JAVA_TOOL_OPTIONS which may (sic) contains javac: we are forced to remove it.
178+
*/
179+
String cleanedOutput = cleanPickedUp(out.getOutput(), CommandLineUtils.getSystemEnvVars());
180+
version = extractMajorAndMinorVersion(cleanedOutput);
165181
VERSION_PER_EXECUTABLE.put(executable, version);
166182
}
167183
return version;
168184
}
169185

170186
static String extractMajorAndMinorVersion(String text) {
187+
int javacIndex = text.indexOf("javac");
171188
Matcher matcher = JAVA_MAJOR_AND_MINOR_VERSION_PATTERN.matcher(text);
172-
if (!matcher.find()) {
189+
int start = javacIndex == -1 ? 0 : javacIndex + JAVAC_PREFIX.length();
190+
if (!matcher.find(start)) {
173191
throw new IllegalArgumentException("Could not extract version from \"" + text + "\"");
174192
}
175193
return matcher.group();
176194
}
177195

196+
static String cleanPickedUp(String text, Properties envvars) {
197+
String ls = "\n";
198+
String ntext = StringUtils.unifyLineSeparators(text, ls);
199+
for (String env : PICKED_ENV_VARS) {
200+
String value = StringUtils.unifyLineSeparators(envvars.getProperty(env), ls);
201+
if (value != null) {
202+
ntext = ntext.replace(String.format("Picked up %s: %s\n", env, value), "");
203+
}
204+
}
205+
return ntext;
206+
}
207+
178208
@Override
179209
public CompilerResult performCompile(CompilerConfiguration config) throws CompilerException {
180210
File destinationDir = new File(config.getOutputLocation());

Diff for: plexus-compilers/plexus-compiler-javac/src/test/java/org/codehaus/plexus/compiler/javac/JavacCompilerTest.java

+51
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,12 @@
22

33
import java.io.BufferedReader;
44
import java.io.IOException;
5+
import java.io.InputStream;
6+
import java.io.InputStreamReader;
57
import java.io.StringReader;
8+
import java.nio.charset.StandardCharsets;
69
import java.util.List;
10+
import java.util.Properties;
711
import java.util.stream.Stream;
812

913
import org.codehaus.plexus.compiler.CompilerMessage;
@@ -13,6 +17,7 @@
1317
import org.junit.jupiter.params.ParameterizedTest;
1418
import org.junit.jupiter.params.provider.Arguments;
1519
import org.junit.jupiter.params.provider.MethodSource;
20+
import org.opentest4j.AssertionFailedError;
1621

1722
import static org.hamcrest.CoreMatchers.endsWith;
1823
import static org.hamcrest.CoreMatchers.not;
@@ -125,5 +130,51 @@ void testExtractMajorAndMinorVersion() {
125130
assertEquals("11.0", JavacCompiler.extractMajorAndMinorVersion("javac 11.0.22"));
126131
assertEquals("11.0", JavacCompiler.extractMajorAndMinorVersion("11.0.22"));
127132
assertEquals("21", JavacCompiler.extractMajorAndMinorVersion("javac 21"));
133+
assertEquals("1.8", JavacCompiler.extractMajorAndMinorVersion("1.3.4\njavac 1.8.0_432"));
134+
}
135+
136+
@Test
137+
void testCleanPickedUp() {
138+
assertEquals(
139+
"This text contains CRLF\n",
140+
JavacCompiler.cleanPickedUp("This text contains CRLF\r\n", new Properties()));
141+
142+
// files were generated by using:
143+
// declare -x JAVA_TOOL_OPTIONS=$'-Daaa\n\n-Dxxx'
144+
// declare -x _JAVA_OPTIONS="-Dccc"
145+
// "${JAVA_8_HOME}/bin/javac" -version >
146+
// plexus-compilers/plexus-compiler-javac/src/test/resources/org/codehaus/plexus/compiler/javac/java8_pickedUp.txt 2>&1
147+
// "${JAVA_17_HOME}/bin/javac" -version >
148+
// plexus-compilers/plexus-compiler-javac/src/test/resources/org/codehaus/plexus/compiler/javac/java17_pickedUp.txt 2>&1
149+
// "${JAVA_21_HOME}/bin/javac" -version >
150+
// plexus-compilers/plexus-compiler-javac/src/test/resources/org/codehaus/plexus/compiler/javac/java21_pickedUp.txt 2>&1
151+
Properties envvars = new Properties();
152+
envvars.setProperty("JAVA_TOOL_OPTIONS", "-Daaa\r\n\r\n-Dxxx");
153+
envvars.setProperty("_JAVA_OPTIONS", "-Dccc");
154+
155+
assertEquals(
156+
"javac 1.8.0_432\n", JavacCompiler.cleanPickedUp(readAllLines("java8_pickedUp.txt", "\n"), envvars));
157+
assertEquals(
158+
"javac 17.0.13\n", JavacCompiler.cleanPickedUp(readAllLines("java17_pickedUp.txt", "\r\n"), envvars));
159+
assertEquals("javac 21.0.5\n", JavacCompiler.cleanPickedUp(readAllLines("java21_pickedUp.txt", "\r"), envvars));
160+
}
161+
162+
private String readAllLines(String resource, String ls) {
163+
try (InputStream is = this.getClass().getResourceAsStream(resource)) {
164+
if (is == null) {
165+
throw new AssertionFailedError("No such resource: " + resource + " in class " + this.getClass());
166+
}
167+
try (InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
168+
BufferedReader br = new BufferedReader(isr)) {
169+
StringBuilder sb = new StringBuilder();
170+
for (String line = null; (line = br.readLine()) != null; ) {
171+
sb.append(line).append(ls);
172+
}
173+
return sb.toString();
174+
}
175+
} catch (IOException e) {
176+
throw new AssertionFailedError(
177+
"Could not fetch lines of resource: " + resource + " in class " + this.getClass(), e);
178+
}
128179
}
129180
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Picked up JAVA_TOOL_OPTIONS: -Daaa
2+
3+
-Dxxx
4+
Picked up _JAVA_OPTIONS: -Dccc
5+
javac 17.0.13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Picked up JAVA_TOOL_OPTIONS: -Daaa
2+
3+
-Dxxx
4+
Picked up _JAVA_OPTIONS: -Dccc
5+
javac 21.0.5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Picked up JAVA_TOOL_OPTIONS: -Daaa
2+
3+
-Dxxx
4+
Picked up _JAVA_OPTIONS: -Dccc
5+
javac 1.8.0_432

0 commit comments

Comments
 (0)