Commit b36c8a7c authored by Andy Wilkinson's avatar Andy Wilkinson

Polish "Tighten up PropertiesLauncher's contract"

See gh-8346
Closes gh-7221
parent e4c807b8
...@@ -214,7 +214,10 @@ NOTE: `PropertiesLauncher` supports loading properties from ...@@ -214,7 +214,10 @@ NOTE: `PropertiesLauncher` supports loading properties from
just like a regular `-classpath` on the `javac` command line. just like a regular `-classpath` on the `javac` command line.
|`loader.home` |`loader.home`
|Used to resolve relative paths in `loader.path`. E.g. `loader.path=lib` then `${loader.home}/lib` is a classpath location (along with all jar files in that directory). Also used to locate a `loader.properties file`. Example `file:///opt/app` (defaults to `${user.dir}`). |Used to resolve relative paths in `loader.path`. E.g. `loader.path=lib` then
`${loader.home}/lib` is a classpath location (along with all jar files in that
directory). Also used to locate a `loader.properties file`. Example `file:///opt/app`
(defaults to `${user.dir}`).
|`loader.args` |`loader.args`
|Default arguments for the main method (space separated) |Default arguments for the main method (space separated)
...@@ -271,21 +274,24 @@ TIP: Build plugins automatically move the `Main-Class` attribute to `Start-Class ...@@ -271,21 +274,24 @@ TIP: Build plugins automatically move the `Main-Class` attribute to `Start-Class
the fat jar is built. If you are using that, specify the name of the class to launch using the fat jar is built. If you are using that, specify the name of the class to launch using
the `Main-Class` attribute and leave out `Start-Class`. the `Main-Class` attribute and leave out `Start-Class`.
* `loader.properties` are searched for in `loader.home` then in the root of the classpath, * `loader.properties` are searched for in `loader.home` then in the root of the
then in `classpath:/BOOT-INF/classes`. The first location that exists is used. classpath, then in `classpath:/BOOT-INF/classes`. The first location that exists is
* `loader.home` is only the directory location of an additional properties file (overriding used.
the default) as long as `loader.config.location` is not specified. * `loader.home` is only 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), * `loader.path` can contain directories (scanned recursively for jar and zip files),
archive paths, or wildcard patterns (for the default JVM behavior). archive paths, or wildcard patterns (for the default JVM behavior).
* `loader.path` (if empty) defaults to `BOOT-INF/lib` (meaning a local directory or a * `loader.path` (if empty) defaults to `BOOT-INF/lib` (meaning a local directory or a
nested one if running from an archive). Because of this `PropertiesLauncher` behaves the nested one if running from an archive). Because of this `PropertiesLauncher` behaves the
same as `JarLauncher` when no additional configuration is provided. same as `JarLauncher` when no additional configuration is provided.
* `loader.path` can not be used to configure the location of `loader.properties` (the classpath * `loader.path` can not be used to configure the location of `loader.properties` (the
used to search for the latter is the JVM classpath when `PropertiesLauncher` is launched). classpath used to search for the latter is the JVM classpath when `PropertiesLauncher`
is launched).
* Placeholder replacement is done from System and environment variables plus the * Placeholder replacement is done from System and environment variables plus the
properties file itself on all values before use. properties file itself on all values before use.
* The search order for properties (where it makes sense to look in more than one place) * The search order for properties (where it makes sense to look in more than one place)
is env vars, system properties, `loader.properties`, exploded archive manifest, archive manifest. is env vars, system properties, `loader.properties`, exploded archive manifest, archive
manifest.
......
...@@ -167,7 +167,7 @@ public class PropertiesLauncher extends Launcher { ...@@ -167,7 +167,7 @@ public class PropertiesLauncher extends Launcher {
for (String config : configs) { for (String config : configs) {
InputStream resource = getResource(config); InputStream resource = getResource(config);
if (resource != null) { if (resource != null) {
log("Found: " + config); debug("Found: " + config);
try { try {
this.properties.load(resource); this.properties.load(resource);
} }
...@@ -177,7 +177,7 @@ public class PropertiesLauncher extends Launcher { ...@@ -177,7 +177,7 @@ public class PropertiesLauncher extends Launcher {
for (Object key : Collections.list(this.properties.propertyNames())) { for (Object key : Collections.list(this.properties.propertyNames())) {
if (config.endsWith("application.properties") if (config.endsWith("application.properties")
&& ((String) key).startsWith("loader.")) { && ((String) key).startsWith("loader.")) {
warn("WARNING: use of application.properties for PropertiesLauncher is deprecated"); warn("Use of application.properties for PropertiesLauncher is deprecated");
} }
String text = this.properties.getProperty((String) key); String text = this.properties.getProperty((String) key);
String value = SystemPropertyUtils String value = SystemPropertyUtils
...@@ -187,7 +187,7 @@ public class PropertiesLauncher extends Launcher { ...@@ -187,7 +187,7 @@ public class PropertiesLauncher extends Launcher {
} }
} }
if ("true".equals(getProperty(SET_SYSTEM_PROPERTIES))) { if ("true".equals(getProperty(SET_SYSTEM_PROPERTIES))) {
log("Adding resolved properties to System properties"); debug("Adding resolved properties to System properties");
for (Object key : Collections.list(this.properties.propertyNames())) { for (Object key : Collections.list(this.properties.propertyNames())) {
String value = this.properties.getProperty((String) key); String value = this.properties.getProperty((String) key);
System.setProperty((String) key, value); System.setProperty((String) key, value);
...@@ -197,7 +197,7 @@ public class PropertiesLauncher extends Launcher { ...@@ -197,7 +197,7 @@ public class PropertiesLauncher extends Launcher {
return; return;
} }
else { else {
log("Not found: " + config); debug("Not found: " + config);
} }
} }
} }
...@@ -232,13 +232,13 @@ public class PropertiesLauncher extends Launcher { ...@@ -232,13 +232,13 @@ public class PropertiesLauncher extends Launcher {
config = config.substring(1); config = config.substring(1);
} }
config = "/" + config; config = "/" + config;
log("Trying classpath: " + config); debug("Trying classpath: " + config);
return getClass().getResourceAsStream(config); return getClass().getResourceAsStream(config);
} }
private InputStream getFileResource(String config) throws Exception { private InputStream getFileResource(String config) throws Exception {
File file = new File(config); File file = new File(config);
log("Trying file: " + config); debug("Trying file: " + config);
if (file.canRead()) { if (file.canRead()) {
return new FileInputStream(file); return new FileInputStream(file);
} }
...@@ -294,7 +294,7 @@ public class PropertiesLauncher extends Launcher { ...@@ -294,7 +294,7 @@ public class PropertiesLauncher extends Launcher {
if (path != null) { if (path != null) {
this.paths = parsePathsProperty(path); this.paths = parsePathsProperty(path);
} }
log("Nested archive paths: " + this.paths); debug("Nested archive paths: " + this.paths);
} }
private List<String> parsePathsProperty(String commaSeparatedPaths) { private List<String> parsePathsProperty(String commaSeparatedPaths) {
...@@ -342,7 +342,7 @@ public class PropertiesLauncher extends Launcher { ...@@ -342,7 +342,7 @@ public class PropertiesLauncher extends Launcher {
String customLoaderClassName = getProperty("loader.classLoader"); String customLoaderClassName = getProperty("loader.classLoader");
if (customLoaderClassName != null) { if (customLoaderClassName != null) {
loader = wrapWithCustomClassLoader(loader, customLoaderClassName); loader = wrapWithCustomClassLoader(loader, customLoaderClassName);
log("Using custom class loader: " + customLoaderClassName); debug("Using custom class loader: " + customLoaderClassName);
} }
return loader; return loader;
} }
...@@ -392,13 +392,13 @@ public class PropertiesLauncher extends Launcher { ...@@ -392,13 +392,13 @@ public class PropertiesLauncher extends Launcher {
if (property != null) { if (property != null) {
String value = SystemPropertyUtils.resolvePlaceholders(this.properties, String value = SystemPropertyUtils.resolvePlaceholders(this.properties,
property); property);
log("Property '" + propertyKey + "' from environment: " + value); debug("Property '" + propertyKey + "' from environment: " + value);
return value; return value;
} }
if (this.properties.containsKey(propertyKey)) { if (this.properties.containsKey(propertyKey)) {
String value = SystemPropertyUtils.resolvePlaceholders(this.properties, String value = SystemPropertyUtils.resolvePlaceholders(this.properties,
this.properties.getProperty(propertyKey)); this.properties.getProperty(propertyKey));
log("Property '" + propertyKey + "' from properties: " + value); debug("Property '" + propertyKey + "' from properties: " + value);
return value; return value;
} }
try { try {
...@@ -408,7 +408,7 @@ public class PropertiesLauncher extends Launcher { ...@@ -408,7 +408,7 @@ public class PropertiesLauncher extends Launcher {
if (manifest != null) { if (manifest != null) {
String value = manifest.getMainAttributes().getValue(manifestKey); String value = manifest.getMainAttributes().getValue(manifestKey);
if (value != null) { if (value != null) {
log("Property '" + manifestKey debug("Property '" + manifestKey
+ "' from home directory manifest: " + value); + "' from home directory manifest: " + value);
return SystemPropertyUtils.resolvePlaceholders(this.properties, return SystemPropertyUtils.resolvePlaceholders(this.properties,
value); value);
...@@ -424,7 +424,7 @@ public class PropertiesLauncher extends Launcher { ...@@ -424,7 +424,7 @@ public class PropertiesLauncher extends Launcher {
if (manifest != null) { if (manifest != null) {
String value = manifest.getMainAttributes().getValue(manifestKey); String value = manifest.getMainAttributes().getValue(manifestKey);
if (value != null) { if (value != null) {
log("Property '" + manifestKey + "' from archive manifest: " + value); debug("Property '" + manifestKey + "' from archive manifest: " + value);
return SystemPropertyUtils.resolvePlaceholders(this.properties, value); return SystemPropertyUtils.resolvePlaceholders(this.properties, value);
} }
} }
...@@ -460,19 +460,19 @@ public class PropertiesLauncher extends Launcher { ...@@ -460,19 +460,19 @@ public class PropertiesLauncher extends Launcher {
file = new File(this.home, root); file = new File(this.home, root);
} }
if (file.isDirectory()) { if (file.isDirectory()) {
log("Adding classpath entries from " + file); debug("Adding classpath entries from " + file);
Archive archive = new ExplodedArchive(file, false); Archive archive = new ExplodedArchive(file, false);
lib.add(archive); lib.add(archive);
} }
Archive archive = getArchive(file); Archive archive = getArchive(file);
if (archive != null) { if (archive != null) {
log("Adding classpath entries from archive " + archive.getUrl() + root); debug("Adding classpath entries from archive " + archive.getUrl() + root);
lib.add(archive); lib.add(archive);
} }
List<Archive> nested = getNestedArchive(root); Archive nested = getNestedArchive(root);
if (nested != null) { if (nested != null) {
log("Adding classpath entries from nested " + root); debug("Adding classpath entries from nested " + root);
lib.addAll(nested); lib.add(nested);
} }
return lib; return lib;
} }
...@@ -490,21 +490,19 @@ public class PropertiesLauncher extends Launcher { ...@@ -490,21 +490,19 @@ public class PropertiesLauncher extends Launcher {
return null; return null;
} }
private List<Archive> getNestedArchive(String root) throws Exception { private Archive getNestedArchive(String root) throws Exception {
List<Archive> list = new ArrayList<Archive>();
if (root.startsWith("/") if (root.startsWith("/")
|| this.parent.getUrl().equals(this.home.toURI().toURL())) { || this.parent.getUrl().equals(this.home.toURI().toURL())) {
// If home dir is same as parent archive, no need to add it twice. // If home dir is same as parent archive, no need to add it twice.
return list; return null;
} }
EntryFilter filter = new PrefixMatchingArchiveFilter(root); EntryFilter filter = new PrefixMatchingArchiveFilter(root);
if (this.parent.getNestedArchives(filter).isEmpty()) { if (this.parent.getNestedArchives(filter).isEmpty()) {
return list; return null;
} }
// If there are more archives nested in this subdirectory (root) then create a new // If there are more archives nested in this subdirectory (root) then create a new
// virtual archive for them, and have it added to the classpath // virtual archive for them, and have it added to the classpath
list.add(new FilteredArchive(this.parent, filter)); return new FilteredArchive(this.parent, filter);
return list;
} }
private void addNestedEntries(List<Archive> lib) { private void addNestedEntries(List<Archive> lib) {
...@@ -575,15 +573,17 @@ public class PropertiesLauncher extends Launcher { ...@@ -575,15 +573,17 @@ public class PropertiesLauncher extends Launcher {
return Character.toUpperCase(str.charAt(0)) + str.substring(1); return Character.toUpperCase(str.charAt(0)) + str.substring(1);
} }
private void log(String message) { private void debug(String message) {
if (Boolean.getBoolean(DEBUG)) { if (Boolean.getBoolean(DEBUG)) {
// We shouldn't use java.util.logging because of classpath issues so we log(message);
// just sysout log messages when "loader.debug" is true
System.out.println(message);
} }
} }
private void warn(String message) { private void warn(String message) {
log("WARNING: " + message);
}
private void log(String message) {
// We shouldn't use java.util.logging because of classpath issues // We shouldn't use java.util.logging because of classpath issues
System.out.println(message); System.out.println(message);
} }
......
/* /*
* Copyright 2012-2016 the original author or authors. * Copyright 2012-2017 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment