Skip to content

Commit 5b847a0

Browse files
committed
Fix Maven home detection, validation, process handling, and SpotBugs logging issue
1 parent 1a9b0fd commit 5b847a0

File tree

2 files changed

+115
-31
lines changed

2 files changed

+115
-31
lines changed

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/config/Config.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.jenkins.tools.pluginmodernizer.core.config;
22

3+
import edu.umd.cs.findbugs.annotations.Nullable;
34
import io.jenkins.tools.pluginmodernizer.core.model.Plugin;
45
import io.jenkins.tools.pluginmodernizer.core.model.Recipe;
56
import java.net.URL;
@@ -168,11 +169,29 @@ public Path getCachePath() {
168169
}
169170

170171
public Path getMavenHome() {
171-
Path effectiveMavenHome = detectedMavenHome != null ? detectedMavenHome : mavenHome;
172-
if (effectiveMavenHome == null) {
173-
return null;
172+
if (mavenHome != null) {
173+
return mavenHome.toAbsolutePath();
174174
}
175-
return effectiveMavenHome.toAbsolutePath();
175+
176+
if (detectedMavenHome != null) {
177+
return detectedMavenHome.toAbsolutePath();
178+
}
179+
180+
return null;
181+
}
182+
183+
/**
184+
* Maven home explicitly configured via CLI/env (does not include detected value).
185+
*/
186+
public @Nullable Path getConfiguredMavenHome() {
187+
return mavenHome == null ? null : mavenHome.toAbsolutePath();
188+
}
189+
190+
/**
191+
* Maven home detected from PATH and cached for subsequent use.
192+
*/
193+
public @Nullable Path getDetectedMavenHome() {
194+
return detectedMavenHome == null ? null : detectedMavenHome.toAbsolutePath();
176195
}
177196

178197
public void setMavenHome(Path mavenHome) {

plugin-modernizer-core/src/main/java/io/jenkins/tools/pluginmodernizer/core/impl/MavenInvoker.java

Lines changed: 92 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -209,53 +209,118 @@ public void validateMaven() {
209209
@SuppressWarnings("OS_COMMAND_INJECTION")
210210
@Nullable
211211
private Path detectMavenHome() {
212-
try {
213-
String os = System.getProperty("os.name").toLowerCase();
212+
String os = System.getProperty("os.name");
213+
if (os == null) {
214+
os = "";
215+
}
214216

215-
Process process;
216-
if (os.contains("win")) {
217-
process = new ProcessBuilder("where", "mvn").start();
218-
} else {
219-
process = new ProcessBuilder("which", "mvn").start();
220-
}
217+
ProcessBuilder processBuilder;
218+
if (os.toLowerCase().contains("win")) {
219+
processBuilder = new ProcessBuilder("where", "mvn");
220+
} else {
221+
processBuilder = new ProcessBuilder("which", "mvn");
222+
}
223+
processBuilder.redirectErrorStream(true);
224+
225+
String mvnPath = null;
226+
StringBuilder output = new StringBuilder();
227+
Process process = null;
228+
229+
try {
230+
process = processBuilder.start();
221231

222232
try (BufferedReader reader =
223233
new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
224-
String mvnPath = reader.readLine();
225-
process.waitFor();
234+
String line;
235+
while ((line = reader.readLine()) != null) {
236+
if (output.length() > 0) {
237+
output.append('\n');
238+
}
239+
output.append(line);
226240

227-
if (mvnPath == null || mvnPath.isEmpty()) {
228-
return null;
241+
if (mvnPath == null && !line.isBlank()) {
242+
mvnPath = line;
243+
}
229244
}
245+
}
230246

231-
Path mvn = Path.of(mvnPath);
232-
Path binDir = mvn.getParent();
233-
if (binDir == null) {
234-
return null;
235-
}
236-
return binDir.getParent();
247+
int exitCode = process.waitFor();
248+
if (exitCode != 0 || mvnPath == null || mvnPath.isBlank()) {
249+
LOG.debug("Maven not found in PATH (exitCode=" + exitCode + ", output=" + sanitize(output.toString())
250+
+ ")");
251+
return null;
252+
}
253+
254+
Path mvn = Path.of(mvnPath).toRealPath();
255+
Path binDir = mvn.getParent();
256+
if (binDir == null) {
257+
LOG.debug("Failed to detect Maven home from mvn path (no parent): " + sanitize(mvnPath));
258+
return null;
259+
}
260+
261+
Path mavenHome = binDir.getParent();
262+
if (mavenHome == null) {
263+
LOG.debug("Failed to detect Maven home from mvn path (no grandparent): " + sanitize(mvnPath));
264+
return null;
237265
}
266+
return mavenHome;
267+
} catch (InterruptedException e) {
268+
Thread.currentThread().interrupt();
269+
LOG.debug("Interrupted while detecting Maven from PATH", e);
270+
return null;
238271
} catch (Exception e) {
239272
LOG.debug("Failed to detect Maven from PATH", e);
240273
return null;
274+
} finally {
275+
if (process != null) {
276+
process.destroy();
277+
}
241278
}
242279
}
243280

281+
private boolean isValidMavenHome(Path mavenHome) {
282+
if (mavenHome == null || !Files.isDirectory(mavenHome)) {
283+
return false;
284+
}
285+
286+
Path mvnUnix = mavenHome.resolve("bin/mvn");
287+
Path mvnCmd = mavenHome.resolve("bin/mvn.cmd");
288+
Path mvnBat = mavenHome.resolve("bin/mvn.bat");
289+
return mvnUnix.toFile().canExecute()
290+
|| mvnCmd.toFile().exists()
291+
|| mvnBat.toFile().exists();
292+
}
293+
294+
private String sanitize(String input) {
295+
return input == null ? null : input.replaceAll("[\\r\\n]", "");
296+
}
297+
244298
private Path getEffectiveMavenHome() {
245-
Path mavenHome = config.getMavenHome();
246-
if (mavenHome != null) {
247-
return mavenHome;
299+
Path configured = config.getConfiguredMavenHome();
300+
if (configured != null) {
301+
if (isValidMavenHome(configured)) {
302+
return configured;
303+
}
304+
LOG.warn("Configured Maven home is invalid: " + sanitize(configured.toString())
305+
+ ". Falling back to PATH detection.");
306+
}
307+
308+
Path cachedDetected = config.getDetectedMavenHome();
309+
if (cachedDetected != null) {
310+
if (isValidMavenHome(cachedDetected)) {
311+
return cachedDetected;
312+
}
313+
LOG.debug("Cached detected Maven home is invalid: " + sanitize(cachedDetected.toString()));
248314
}
249315

250316
Path detected = detectMavenHome();
251-
if (detected != null) {
252-
LOG.info("Detected Maven home from PATH: {}", detected);
317+
if (detected != null && isValidMavenHome(detected)) {
318+
LOG.info("Detected Maven home from PATH: " + sanitize(detected.toString()));
253319
config.setMavenHome(detected);
254320
return detected;
255321
}
256322

257-
throw new ModernizerException(
258-
"Neither MAVEN_HOME nor M2_HOME environment variables are set and Maven could not be detected from PATH. Or use --maven-home");
323+
throw new ModernizerException("Maven not found. Please set MAVEN_HOME or ensure 'mvn' is available in PATH.");
259324
}
260325

261326
/**
@@ -289,7 +354,7 @@ private InvocationRequest createInvocationRequest(Plugin plugin, String... args)
289354
request.setMavenHome(getEffectiveMavenHome().toFile());
290355
request.setPomFile(plugin.getLocalRepository().resolve("pom.xml").toFile());
291356
request.addArgs(List.of(args));
292-
if (config.isDebug()) {
357+
if (Config.isDebug()) {
293358
request.addArg("-X");
294359
}
295360
return request;
@@ -307,7 +372,7 @@ private void handleInvocationResult(Plugin plugin, InvocationResult result) {
307372
plugin.addError("Maven generic exception occurred", result.getExecutionException());
308373
} else {
309374
String errorMessage;
310-
if (config.isDebug()) {
375+
if (Config.isDebug()) {
311376
errorMessage = "Build failed with code: " + result.getExitCode();
312377
} else {
313378
errorMessage = "Build failed";

0 commit comments

Comments
 (0)