20
20
import java .io .IOException ;
21
21
import java .net .MalformedURLException ;
22
22
import java .net .URL ;
23
+ import java .nio .file .Files ;
24
+ import java .nio .file .Path ;
25
+ import java .nio .file .StandardOpenOption ;
23
26
import java .util .ArrayList ;
24
27
import java .util .Arrays ;
25
28
import java .util .Collections ;
26
29
import java .util .List ;
30
+ import java .util .Locale ;
27
31
import java .util .Map ;
28
32
import java .util .Set ;
29
33
import java .util .stream .Collectors ;
41
45
import org .springframework .boot .loader .tools .FileUtils ;
42
46
import org .springframework .util .Assert ;
43
47
import org .springframework .util .ObjectUtils ;
48
+ import org .springframework .util .StringUtils ;
44
49
45
50
/**
46
51
* Base class to run a Spring Boot application.
50
55
* @author David Liu
51
56
* @author Daniel Young
52
57
* @author Dmytro Nosan
58
+ * @author Moritz Halbritter
53
59
* @since 1.3.0
54
60
* @see RunMojo
55
61
* @see StartMojo
@@ -239,6 +245,10 @@ private void run(String startClassName) throws MojoExecutionException, MojoFailu
239
245
JavaProcessExecutor processExecutor = new JavaProcessExecutor (this .session , this .toolchainManager );
240
246
File workingDirectoryToUse = (this .workingDirectory != null ) ? this .workingDirectory
241
247
: this .project .getBasedir ();
248
+ if (getLog ().isDebugEnabled ()) {
249
+ getLog ().debug ("Working directory: " + workingDirectoryToUse );
250
+ getLog ().debug ("Java arguments: " + String .join (" " , args ));
251
+ }
242
252
run (processExecutor , workingDirectoryToUse , args , determineEnvironmentVariables ());
243
253
}
244
254
@@ -351,13 +361,40 @@ private void addClasspath(List<String> args) throws MojoExecutionException {
351
361
getLog ().debug ("Classpath for forked process: " + classpath );
352
362
}
353
363
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
+ }
355
370
}
356
371
catch (Exception ex ) {
357
372
throw new MojoExecutionException ("Could not build classpath" , ex );
358
373
}
359
374
}
360
375
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
+
361
398
protected URL [] getClassPathUrls () throws MojoExecutionException {
362
399
try {
363
400
List <URL > urls = new ArrayList <>();
@@ -372,7 +409,6 @@ protected URL[] getClassPathUrls() throws MojoExecutionException {
372
409
}
373
410
}
374
411
375
- @ SuppressWarnings ("removal" )
376
412
private void addAdditionalClasspathLocations (List <URL > urls ) throws MalformedURLException {
377
413
Assert .state (ObjectUtils .isEmpty (this .directories ) || ObjectUtils .isEmpty (this .additionalClasspathElements ),
378
414
"Either additionalClasspathElements or directories (deprecated) should be set, not both" );
@@ -437,4 +473,32 @@ static String format(String key, String value) {
437
473
438
474
}
439
475
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
+
440
504
}
0 commit comments