2020import java .io .IOException ;
2121import java .net .MalformedURLException ;
2222import java .net .URL ;
23+ import java .nio .file .Files ;
24+ import java .nio .file .Path ;
25+ import java .nio .file .StandardOpenOption ;
2326import java .util .ArrayList ;
2427import java .util .Arrays ;
2528import java .util .Collections ;
2629import java .util .List ;
30+ import java .util .Locale ;
2731import java .util .Map ;
2832import java .util .Set ;
2933import java .util .stream .Collectors ;
4145import org .springframework .boot .loader .tools .FileUtils ;
4246import org .springframework .util .Assert ;
4347import org .springframework .util .ObjectUtils ;
48+ import org .springframework .util .StringUtils ;
4449
4550/**
4651 * Base class to run a Spring Boot application.
5055 * @author David Liu
5156 * @author Daniel Young
5257 * @author Dmytro Nosan
58+ * @author Moritz Halbritter
5359 * @since 1.3.0
5460 * @see RunMojo
5561 * @see StartMojo
@@ -239,6 +245,10 @@ private void run(String startClassName) throws MojoExecutionException, MojoFailu
239245 JavaProcessExecutor processExecutor = new JavaProcessExecutor (this .session , this .toolchainManager );
240246 File workingDirectoryToUse = (this .workingDirectory != null ) ? this .workingDirectory
241247 : this .project .getBasedir ();
248+ if (getLog ().isDebugEnabled ()) {
249+ getLog ().debug ("Working directory: " + workingDirectoryToUse );
250+ getLog ().debug ("Java arguments: " + String .join (" " , args ));
251+ }
242252 run (processExecutor , workingDirectoryToUse , args , determineEnvironmentVariables ());
243253 }
244254
@@ -351,13 +361,40 @@ private void addClasspath(List<String> args) throws MojoExecutionException {
351361 getLog ().debug ("Classpath for forked process: " + classpath );
352362 }
353363 args .add ("-cp" );
354- args .add (classpath .toString ());
364+ if (needsClasspathArgFile ()) {
365+ args .add ("@" + writeClasspathArgFile (classpath .toString ()));
366+ }
367+ else {
368+ args .add (classpath .toString ());
369+ }
355370 }
356371 catch (Exception ex ) {
357372 throw new MojoExecutionException ("Could not build classpath" , ex );
358373 }
359374 }
360375
376+ private boolean needsClasspathArgFile () {
377+ // Windows limits the maximum command length, so we use an argfile there
378+ return runsOnWindows ();
379+ }
380+
381+ private boolean runsOnWindows () {
382+ String os = System .getProperty ("os.name" );
383+ if (!StringUtils .hasLength (os )) {
384+ if (getLog ().isWarnEnabled ()) {
385+ getLog ().warn ("System property os.name is not set" );
386+ }
387+ return false ;
388+ }
389+ return os .toLowerCase (Locale .ROOT ).contains ("win" );
390+ }
391+
392+ private Path writeClasspathArgFile (String classpath ) throws IOException {
393+ ArgFile argFile = ArgFile .create ();
394+ argFile .write (classpath );
395+ return argFile .getPath ();
396+ }
397+
361398 protected URL [] getClassPathUrls () throws MojoExecutionException {
362399 try {
363400 List <URL > urls = new ArrayList <>();
@@ -372,7 +409,6 @@ protected URL[] getClassPathUrls() throws MojoExecutionException {
372409 }
373410 }
374411
375- @ SuppressWarnings ("removal" )
376412 private void addAdditionalClasspathLocations (List <URL > urls ) throws MalformedURLException {
377413 Assert .state (ObjectUtils .isEmpty (this .directories ) || ObjectUtils .isEmpty (this .additionalClasspathElements ),
378414 "Either additionalClasspathElements or directories (deprecated) should be set, not both" );
@@ -437,4 +473,32 @@ static String format(String key, String value) {
437473
438474 }
439475
476+ static class ArgFile {
477+
478+ private final Path path ;
479+
480+ ArgFile (Path path ) {
481+ this .path = path ;
482+ }
483+
484+ void write (String content ) throws IOException {
485+ String escaped = escape (content );
486+ Files .writeString (this .path , "\" " + escaped + "\" " , StandardOpenOption .APPEND );
487+ }
488+
489+ Path getPath () {
490+ return this .path ;
491+ }
492+
493+ private String escape (String content ) {
494+ return content .replace ("\\ " , "\\ \\ " );
495+ }
496+
497+ static ArgFile create () throws IOException {
498+ Path file = Files .createTempFile ("spring-boot-" , ".argfile" );
499+ return new ArgFile (file );
500+ }
501+
502+ }
503+
440504}
0 commit comments