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;