mirror of
https://github.com/lightbend/config.git
synced 2025-01-15 23:01:05 +08:00
If include statements from a cycle, throw a nicer error
This commit is contained in:
parent
36f4e2e61a
commit
2dc420ccf0
2
NEWS.md
2
NEWS.md
@ -30,6 +30,8 @@
|
||||
implement ConfigIncluderFile, ConfigIncluderURL, and
|
||||
ConfigIncluderClasspath. You should also use
|
||||
ConfigIncludeContext.parseOptions() if appropriate.
|
||||
- cycles in include statements (self-includes) are now detected
|
||||
and result in a nicer error instead of stack overflow
|
||||
- the serialization format has changed for a Config that has not
|
||||
had resolve() called on it. The library can still deserialize
|
||||
the old format, but old versions of the library will not be
|
||||
|
@ -20,6 +20,7 @@ import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.typesafe.config.ConfigException;
|
||||
@ -43,8 +44,16 @@ public abstract class Parseable implements ConfigParseable {
|
||||
private ConfigParseOptions initialOptions;
|
||||
private ConfigOrigin initialOrigin;
|
||||
|
||||
protected Parseable() {
|
||||
private static final ThreadLocal<LinkedList<Parseable>> parseStack = new ThreadLocal<LinkedList<Parseable>>() {
|
||||
@Override
|
||||
protected LinkedList<Parseable> initialValue() {
|
||||
return new LinkedList<Parseable>();
|
||||
}
|
||||
};
|
||||
|
||||
private static final int MAX_INCLUDE_DEPTH = 50;
|
||||
|
||||
protected Parseable() {
|
||||
}
|
||||
|
||||
private ConfigParseOptions fixupOptions(ConfigParseOptions baseOptions) {
|
||||
@ -122,7 +131,23 @@ public abstract class Parseable implements ConfigParseable {
|
||||
|
||||
@Override
|
||||
public ConfigObject parse(ConfigParseOptions baseOptions) {
|
||||
return forceParsedToObject(parseValue(baseOptions));
|
||||
|
||||
LinkedList<Parseable> stack = parseStack.get();
|
||||
if (stack.size() >= MAX_INCLUDE_DEPTH) {
|
||||
throw new ConfigException.Parse(initialOrigin, "include statements nested more than "
|
||||
+ MAX_INCLUDE_DEPTH
|
||||
+ " times, you probably have a cycle in your includes. Trace: " + stack);
|
||||
}
|
||||
|
||||
stack.addFirst(this);
|
||||
try {
|
||||
return forceParsedToObject(parseValue(baseOptions));
|
||||
} finally {
|
||||
stack.removeFirst();
|
||||
if (stack.isEmpty()) {
|
||||
parseStack.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final AbstractConfigValue parseValue(ConfigParseOptions baseOptions) {
|
||||
@ -350,6 +375,11 @@ public abstract class Parseable implements ConfigParseable {
|
||||
protected ConfigOrigin createOrigin() {
|
||||
return SimpleConfigOrigin.newSimple("String");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "(" + input + ")";
|
||||
}
|
||||
}
|
||||
|
||||
public static Parseable newString(String input, ConfigParseOptions options) {
|
||||
|
1
config/src/test/resources/cycle.conf
Normal file
1
config/src/test/resources/cycle.conf
Normal file
@ -0,0 +1 @@
|
||||
include "cycle.conf"
|
@ -817,4 +817,13 @@ class PublicApiTest extends TestUtils {
|
||||
assertTrue("cache was dropped when switching loaders", load3 ne load7)
|
||||
assertEquals(load3, load7)
|
||||
}
|
||||
|
||||
@Test
|
||||
def detectIncludeCycle() {
|
||||
val e = intercept[ConfigException.Parse] {
|
||||
ConfigFactory.load("cycle")
|
||||
}
|
||||
|
||||
assertTrue("wrong exception: " + e.getMessage, e.getMessage.contains("include statements nested"))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user