diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java index 4cef7b9d36..ebf81c9141 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/RunProcess.java @@ -17,6 +17,7 @@ package org.springframework.boot.loader.tools; import java.io.BufferedReader; +import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.lang.reflect.Method; @@ -41,16 +42,34 @@ public class RunProcess { private static final long JUST_ENDED_LIMIT = 500; + private File workingDirectory; + private final String[] command; private volatile Process process; private volatile long endTime; - public RunProcess(String... command) { + /** + * Creates new {@link RunProcess} instance for the specified command + * and working directory. + * @param workingDirectory the working directory of the child process or {@code null} + * to run in the working directory of the current Java process + * @param command the program to execute and it's arguments + */ + public RunProcess(File workingDirectory, String... command) { + this.workingDirectory = workingDirectory; this.command = command; } + /** + * Creates new {@link RunProcess} instance for the specified command. + * @param command the program to execute and it's arguments + */ + public RunProcess(String... command) { + this(null, command); + } + public int run(boolean waitForProcess, String... args) throws IOException { return run(waitForProcess, Arrays.asList(args)); } @@ -58,6 +77,7 @@ public class RunProcess { protected int run(boolean waitForProcess, Collection args) throws IOException { ProcessBuilder builder = new ProcessBuilder(this.command); + builder.directory(this.workingDirectory); builder.command().addAll(args); builder.redirectErrorStream(true); boolean inheritedIO = inheritIO(builder); diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-disable-fork/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-disable-fork/pom.xml index 1cafbfc789..9f537fe47f 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-disable-fork/pom.xml +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-disable-fork/pom.xml @@ -23,6 +23,7 @@ false -Dfoo=bar + ${project.build.sourceDirectory} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-disable-fork/verify.groovy b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-disable-fork/verify.groovy index cb445e7a2c..baaf7a9a59 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-disable-fork/verify.groovy +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-disable-fork/verify.groovy @@ -3,4 +3,5 @@ import static org.junit.Assert.assertTrue def file = new File(basedir, "build.log") assertTrue file.text.contains("I haz been run") assertTrue file.text.contains("Fork mode disabled, ignoring JVM argument(s) [-Dfoo=bar]") +assertTrue file.text.contains("Fork mode disabled, ignoring working directory configuration") diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/pom.xml new file mode 100644 index 0000000000..9cfd04f3b1 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + org.springframework.boot.maven.it + run-working-directory + 0.0.1.BUILD-SNAPSHOT + + UTF-8 + + + + + @project.groupId@ + @project.artifactId@ + @project.version@ + + + package + + run + + + ${project.build.sourceDirectory} + + + + + + + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/src/main/java/org/test/SampleApplication.java b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/src/main/java/org/test/SampleApplication.java new file mode 100644 index 0000000000..6fff81aaa2 --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/src/main/java/org/test/SampleApplication.java @@ -0,0 +1,26 @@ +/* + * Copyright 2012-2016 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 + * + * http://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.test; + +public class SampleApplication { + + public static void main(String[] args) { + String workingDirectory = System.getProperty("user.dir"); + System.out.println(String.format("I haz been run from %s", workingDirectory)); + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/verify.groovy b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/verify.groovy new file mode 100644 index 0000000000..4f1b8234fc --- /dev/null +++ b/spring-boot-tools/spring-boot-maven-plugin/src/it/run-working-directory/verify.groovy @@ -0,0 +1,6 @@ +import static org.junit.Assert.assertTrue + +def file = new File(basedir, "build.log") +def workDir = new File(basedir, "src/main/java").getAbsolutePath() +assertTrue file.text.contains("I haz been run from ${workDir}") + diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java index 086664afe3..0cf076b589 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java @@ -87,6 +87,15 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { @Parameter(property = "run.noverify") private Boolean noverify; + /** + * Current working directory to use for the application. If not specified, basedir + * will be used NOTE: the use of working directory means that processes will be + * started by forking a new JVM. + * @since 1.5 + */ + @Parameter(property = "run.workingDirectory") + private File workingDirectory; + /** * JVM arguments that should be associated with the forked process used to run the * application. On command line, make sure to wrap multiple values between quotes. @@ -140,8 +149,8 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { /** * Flag to indicate if the run processes should be forked. {@code fork} is - * automatically enabled if an agent or jvmArguments are specified, or if devtools is - * present. + * automatically enabled if an agent, jvmArguments or working directory are + * specified, or if devtools is present. * @since 1.2 */ @Parameter(property = "fork") @@ -185,7 +194,7 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { * @see #logDisabledFork() */ protected boolean enableForkByDefault() { - return hasAgent() || hasJvmArgs(); + return hasAgent() || hasJvmArgs() || hasWorkingDirectorySet(); } private boolean hasAgent() { @@ -196,6 +205,10 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { return (this.jvmArguments != null && this.jvmArguments.length() > 0); } + private boolean hasWorkingDirectorySet() { + return (this.workingDirectory != null); + } + private void findAgent() { try { if (this.agent == null || this.agent.length == 0) { @@ -248,6 +261,9 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { getLog().warn("Fork mode disabled, ignoring JVM argument(s) [" + this.jvmArguments + "]"); } + if (hasWorkingDirectorySet()) { + getLog().warn("Fork mode disabled, ignoring working directory configuration"); + } } private void doRunWithForkedJvm(String startClassName) @@ -258,16 +274,17 @@ public abstract class AbstractRunMojo extends AbstractDependencyFilterMojo { addClasspath(args); args.add(startClassName); addArgs(args); - runWithForkedJvm(args); + runWithForkedJvm(this.workingDirectory, args); } /** * Run with a forked VM, using the specified command line arguments. + * @param workingDirectory the working directory of the forked JVM * @param args the arguments (JVM arguments and application arguments) * @throws MojoExecutionException in case of MOJO execution errors * @throws MojoFailureException in case of MOJO failures */ - protected abstract void runWithForkedJvm(List args) + protected abstract void runWithForkedJvm(File workingDirectory, List args) throws MojoExecutionException, MojoFailureException; /** diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java index 7750556c3d..55843def71 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/RunMojo.java @@ -16,6 +16,7 @@ package org.springframework.boot.maven; +import java.io.File; import java.net.URL; import java.net.URLClassLoader; import java.util.List; @@ -63,9 +64,9 @@ public class RunMojo extends AbstractRunMojo { } @Override - protected void runWithForkedJvm(List args) throws MojoExecutionException { + protected void runWithForkedJvm(File workingDirectory, List args) throws MojoExecutionException { try { - RunProcess runProcess = new RunProcess(new JavaExecutable().toString()); + RunProcess runProcess = new RunProcess(workingDirectory, new JavaExecutable().toString()); Runtime.getRuntime() .addShutdownHook(new Thread(new RunProcessKiller(runProcess))); int exitCode = runProcess.run(true, args.toArray(new String[args.size()])); diff --git a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java index 74fe47655c..595ef0e124 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java +++ b/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/StartMojo.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2015 the original author or authors. + * Copyright 2012-2016 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. @@ -16,6 +16,7 @@ package org.springframework.boot.maven; +import java.io.File; import java.io.IOException; import java.lang.management.ManagementFactory; import java.net.ConnectException; @@ -87,9 +88,9 @@ public class StartMojo extends AbstractRunMojo { private final Object lock = new Object(); @Override - protected void runWithForkedJvm(List args) + protected void runWithForkedJvm(File workingDirectory, List args) throws MojoExecutionException, MojoFailureException { - RunProcess runProcess = runProcess(args); + RunProcess runProcess = runProcess(workingDirectory, args); try { waitForSpringApplication(); } @@ -103,9 +104,11 @@ public class StartMojo extends AbstractRunMojo { } } - private RunProcess runProcess(List args) throws MojoExecutionException { + private RunProcess runProcess(File workingDirectory, List args) + throws MojoExecutionException { try { - RunProcess runProcess = new RunProcess(new JavaExecutable().toString()); + RunProcess runProcess = new RunProcess(workingDirectory, + new JavaExecutable().toString()); runProcess.run(false, args.toArray(new String[args.size()])); return runProcess; }