mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-07-05 00:56:58 +08:00
Create classpath argfile on windows for run tasks
Closes gh-17766
This commit is contained in:
parent
a65e1018f0
commit
5a77122abe
@ -20,10 +20,14 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardOpenOption;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
@ -41,6 +45,7 @@ import org.apache.maven.toolchain.ToolchainManager;
|
||||
import org.springframework.boot.loader.tools.FileUtils;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Base class to run a Spring Boot application.
|
||||
@ -50,6 +55,7 @@ import org.springframework.util.ObjectUtils;
|
||||
* @author David Liu
|
||||
* @author Daniel Young
|
||||
* @author Dmytro Nosan
|
||||
* @author Moritz Halbritter
|
||||
* @since 1.3.0
|
||||
* @see RunMojo
|
||||
* @see StartMojo
|
||||
@ -239,6 +245,10 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||
JavaProcessExecutor processExecutor = new JavaProcessExecutor(this.session, this.toolchainManager);
|
||||
File workingDirectoryToUse = (this.workingDirectory != null) ? this.workingDirectory
|
||||
: this.project.getBasedir();
|
||||
if (getLog().isDebugEnabled()) {
|
||||
getLog().debug("Working directory: " + workingDirectoryToUse);
|
||||
getLog().debug("Java arguments: " + String.join(" ", args));
|
||||
}
|
||||
run(processExecutor, workingDirectoryToUse, args, determineEnvironmentVariables());
|
||||
}
|
||||
|
||||
@ -351,13 +361,40 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||
getLog().debug("Classpath for forked process: " + classpath);
|
||||
}
|
||||
args.add("-cp");
|
||||
args.add(classpath.toString());
|
||||
if (needsClasspathArgFile()) {
|
||||
args.add("@" + writeClasspathArgFile(classpath.toString()));
|
||||
}
|
||||
else {
|
||||
args.add(classpath.toString());
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new MojoExecutionException("Could not build classpath", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean needsClasspathArgFile() {
|
||||
// Windows limits the maximum command length, so we use an argfile there
|
||||
return runsOnWindows();
|
||||
}
|
||||
|
||||
private boolean runsOnWindows() {
|
||||
String os = System.getProperty("os.name");
|
||||
if (!StringUtils.hasLength(os)) {
|
||||
if (getLog().isWarnEnabled()) {
|
||||
getLog().warn("System property os.name is not set");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return os.toLowerCase(Locale.ROOT).contains("win");
|
||||
}
|
||||
|
||||
private Path writeClasspathArgFile(String classpath) throws IOException {
|
||||
ArgFile argFile = ArgFile.create();
|
||||
argFile.write(classpath);
|
||||
return argFile.getPath();
|
||||
}
|
||||
|
||||
protected URL[] getClassPathUrls() throws MojoExecutionException {
|
||||
try {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
@ -372,7 +409,6 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("removal")
|
||||
private void addAdditionalClasspathLocations(List<URL> urls) throws MalformedURLException {
|
||||
Assert.state(ObjectUtils.isEmpty(this.directories) || ObjectUtils.isEmpty(this.additionalClasspathElements),
|
||||
"Either additionalClasspathElements or directories (deprecated) should be set, not both");
|
||||
@ -437,4 +473,32 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo {
|
||||
|
||||
}
|
||||
|
||||
static class ArgFile {
|
||||
|
||||
private final Path path;
|
||||
|
||||
ArgFile(Path path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
void write(String content) throws IOException {
|
||||
String escaped = escape(content);
|
||||
Files.writeString(this.path, "\"" + escaped + "\"", StandardOpenOption.APPEND);
|
||||
}
|
||||
|
||||
Path getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
private String escape(String content) {
|
||||
return content.replace("\\", "\\\\");
|
||||
}
|
||||
|
||||
static ArgFile create() throws IOException {
|
||||
Path file = Files.createTempFile("spring-boot-", ".argfile");
|
||||
return new ArgFile(file);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.maven;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.maven.AbstractRunMojo.ArgFile;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link AbstractRunMojo}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
*/
|
||||
class AbstractRunMojoTests {
|
||||
|
||||
@Test
|
||||
void argfileEscapesContent() throws IOException {
|
||||
ArgFile file = ArgFile.create();
|
||||
file.write("some \\ content");
|
||||
file.write("And even more content");
|
||||
assertThat(file.getPath()).content(StandardCharsets.UTF_8)
|
||||
.isEqualTo("\"some \\\\ content\"\"And even more content\"");
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user