@@ -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