@@ -61,6 +61,10 @@ private PathUtils() {
6161
6262 private static final String SUREFIRE_PATH = "surefire-reports" ;
6363 private static final String FAILSAFE_PATH = "failsafe-reports" ;
64+ private static final List <String > ENDINGS =
65+ OSInfo .getDefault ().getType () == OSInfo .OSType .WINDOWS
66+ ? Arrays .asList ("" , ".cmd" , ".exe" , ".com" , ".bat" )
67+ : Collections .singletonList ("" );
6468
6569 /**
6670 * This enumeration contains methods to help build proxy subclass names and select reports directories.
@@ -251,6 +255,30 @@ public String getNewName() {
251255 }
252256 }
253257
258+ /**
259+ * Search for the specified executable file on the system file path.
260+ * <p>
261+ * <b>NOTE</b>: On Windows, this method automatically checks for files of the specified name/path with
262+ * the standard executable file extensions ({@code .cmd"}, {@code ".exe"}, {@code ".com"},
263+ * and {@code ".bat"}), so these can be omitted for cross-platform compatibility.
264+ *
265+ * @param nameOrPath name/path of executable to find
266+ * @return absolute path of located executable; {@code null} if not found
267+ */
268+ public static String findExecutableOnSystemPath (final String nameOrPath ) {
269+ List <String > paths = getSystemPathList ();
270+ paths .add (0 , "" );
271+ for (String path : paths ) {
272+ for (String ending : ENDINGS ) {
273+ File file = new File (path , nameOrPath + ending );
274+ if (canExecute (file )) {
275+ return file .getAbsolutePath ();
276+ }
277+ }
278+ }
279+ return null ;
280+ }
281+
254282 /**
255283 * Get the system file path as a path-delimited string.
256284 * <p>
@@ -261,10 +289,23 @@ public String getNewName() {
261289 * @return system file path as a path-delimited string
262290 */
263291 public static String getSystemPath () {
292+ return String .join (File .pathSeparator , getSystemPathList ());
293+ }
294+
295+ /**
296+ * Get the system file path as a list of path items.
297+ * <p>
298+ * <b>NOTE</b>: The initial items in the returned path list are derived from {@link System#getenv()}.
299+ * When running on {@code Mac OS X}, additional items are acquired from {@code /etc/paths}
300+ * and the files found in the {@code /etc/paths.d} folder.
301+ *
302+ * @return system file path as a path-delimited string
303+ */
304+ public static List <String > getSystemPathList () {
264305 List <String > pathList = new ArrayList <>();
265306 addSystemPathList (pathList );
266307 addMacintoshPathList (pathList );
267- return String . join ( File . pathSeparator , pathList ) ;
308+ return pathList ;
268309 }
269310
270311 /**
@@ -369,6 +410,10 @@ public static String[] append(String suffix, String... strings) {
369410 return temp ;
370411 }
371412
413+ private static boolean canExecute (File file ) {
414+ return file .exists () && !file .isDirectory () && file .canExecute ();
415+ }
416+
372417 /**
373418 * Classes that implement this interface are called to supply additional elements for the path returned by
374419 * {@link ReportsDirectory#getPathForObject(Object)}. This enables the implementing class to partition artifacts
0 commit comments