diff --git a/spring-boot-tools/spring-boot-loader/README.md b/spring-boot-tools/spring-boot-loader/README.md
index b0ae8d3533d..b85e23177aa 100644
--- a/spring-boot-tools/spring-boot-loader/README.md
+++ b/spring-boot-tools/spring-boot-loader/README.md
@@ -158,6 +158,39 @@ $ unzip -q myapp.jar
$ java org.springframework.boot.loader.JarLauncher
```
+## PropertiesLauncher Features
+
+`PropertiesLauncher` has a few special features that can be enabled
+with external properties (System properties, environment variables,
+manifest entries or `application.properties`).
+
+| Key | Purpose | Typical value |
+|------------|---------|---------------|
+|loader.path |Classpath (colon-separated) |lib:${HOME}/app/lib|
+|loader.home |Location of additional properties file (defaults to `${user.dir}`) |file:///opt/app|
+|loader.args |Default arguments for the main method (space separated) ||
+|loader.main |Name of main class to launch | com.app.Application |
+|loader.config.name|Name of properties file (default "application") | loader|
+|loader.config.location|Path to properties file (default "application/.properties") | classpath:loader.properties|
+|loader.system|Boolean flag to indicate that all properties should be added to System properties (default false)|true|
+
+Manifest entry keys are formed by capitalizing intial letters of words
+and changing the separator to '-' from '.' (e.g. "Loader-Path"). The
+exception is "loader.main" which is looked up as "Start-Class" in the
+manifest for compatibility with `JarLauncher`).
+
+Environment variables can be capitalized with underscore separators
+instead of periods.
+
+* `loader.home` is the directory location of an additional properties
+ file (overriding the default) as long as `loader.config.location` is
+ not specified
+* `loader.path` can contain directories (scanned recursively for jar
+ and zip files), archive paths, or wildcard patterns (for the default
+ JVM behaviour)
+* Placeholder replacement is done from System and environment
+ variables plus the properties file itself on all values before use.
+
## Restrictions
There are a number of restrictions that you need to consider when working with a Spring
Boot Loader packaged application.
diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java
index 4a91c3849cf..508427732c7 100644
--- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java
+++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java
@@ -79,7 +79,8 @@ public class PropertiesLauncher extends Launcher {
private final Logger logger = Logger.getLogger(Launcher.class.getName());
/**
- * Properties key for main class
+ * Properties key for main class. As a manifest entry can also be specified as
+ * Start-Class.
*/
public static final String MAIN = "loader.main";
@@ -93,10 +94,16 @@ public class PropertiesLauncher extends Launcher {
* Properties key for home directory. This is the location of external configuration
* if not on classpath, and also the base path for any relative paths in the
* {@link #PATH loader path}. Defaults to current working directory (
- * ${user.home}).
+ * ${user.dir}).
*/
public static final String HOME = "loader.home";
+ /**
+ * Properties key for default command line arguments. These arguments (if present) are
+ * prepended to the main method arguments before launching.
+ */
+ public static final String ARGS = "loader.args";
+
/**
* Properties key for name of external configuration file (excluding suffix). Defaults
* to "application". Ignored if {@link #CONFIG_LOCATION loader config location} is
@@ -314,6 +321,19 @@ public class PropertiesLauncher extends Launcher {
return paths;
}
+ protected String[] getArgs(String... args) throws Exception {
+ String loaderArgs = getProperty(ARGS);
+ if (loaderArgs != null) {
+ String[] defaultArgs = loaderArgs.split("\\s+");
+ String[] additionalArgs = args;
+ args = new String[defaultArgs.length + additionalArgs.length];
+ System.arraycopy(defaultArgs, 0, args, 0, defaultArgs.length);
+ System.arraycopy(additionalArgs, 0, args, defaultArgs.length,
+ additionalArgs.length);
+ }
+ return args;
+ }
+
@Override
protected String getMainClass() throws Exception {
String mainClass = getProperty(MAIN, "Start-Class");
@@ -542,8 +562,10 @@ public class PropertiesLauncher extends Launcher {
return path;
}
- public static void main(String[] args) {
- new PropertiesLauncher().launch(args);
+ public static void main(String[] args) throws Exception {
+ PropertiesLauncher launcher = new PropertiesLauncher();
+ args = launcher.getArgs(args);
+ launcher.launch(args);
}
public static String toCamelCase(CharSequence string) {
diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java
index b0b5c2411f3..1e120c75605 100644
--- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java
+++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java
@@ -20,6 +20,7 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLClassLoader;
+import java.util.Arrays;
import java.util.Collections;
import org.junit.After;
@@ -147,6 +148,13 @@ public class PropertiesLauncherTests {
assertEquals("demo.Application", System.getProperty("loader.main"));
}
+ @Test
+ public void testArgsEnhanced() throws Exception {
+ System.setProperty("loader.args", "foo");
+ PropertiesLauncher launcher = new PropertiesLauncher();
+ assertEquals("[foo, bar]", Arrays.asList(launcher.getArgs("bar")).toString());
+ }
+
private void waitFor(String value) throws Exception {
int count = 0;
boolean timeout = false;