Permalink
Browse files

Groundwork for the new file() url() classpath() include syntax

This patch doesn't have the parser just the implementation
  • Loading branch information...
1 parent cdd3e12 commit 3b7d99a797471027ac64c5738ddf023e8e2df051 @havocp havocp committed Apr 9, 2012
@@ -34,4 +34,13 @@
* null
*/
ConfigParseable relativeTo(String filename);
+
+ /**
+ * Parse options to use (if you use another method to get a
+ * {@link ConfigParseable} then use {@link ConfigParseable#options()}
+ * instead though).
+ *
+ * @return the parse options
+ */
+ ConfigParseOptions parseOptions();
}
@@ -6,7 +6,9 @@
/**
* Implement this interface and provide an instance to
* {@link ConfigParseOptions#setIncluder ConfigParseOptions.setIncluder()} to
- * customize handling of {@code include} statements in config files.
+ * customize handling of {@code include} statements in config files. You may
+ * also want to implement {@link ConfigIncluderClasspath},
+ * {@link ConfigIncluderFile}, and {@link ConfigIncluderURL}, or not.
*/
public interface ConfigIncluder {
/**
@@ -30,7 +32,14 @@
* Parses another item to be included. The returned object typically would
* not have substitutions resolved. You can throw a ConfigException here to
* abort parsing, or return an empty object, but may not return null.
- *
+ *
+ * This method is used for a "heuristic" include statement that does not
+ * specify file, URL, or classpath resource. If the include statement does
+ * specify, then the same class implementing {@link ConfigIncluder} must
+ * also implement {@link ConfigIncluderClasspath},
+ * {@link ConfigIncluderFile}, or {@link ConfigIncluderURL} as needed, or a
+ * default includer will be used.
+ *
* @param context
* some info about the include context
* @param what
@@ -0,0 +1,25 @@
+/**
+ * Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com>
+ */
+package com.typesafe.config;
+
+/**
+ * Implement this <em>in addition to</em> {@link ConfigIncluder} if you want to
+ * support inclusion of files with the {@code include classpath("resource")}
+ * syntax. If you do not implement this but do implement {@link ConfigIncluder},
+ * attempts to load classpath resources will use the default includer.
+ */
+public interface ConfigIncluderClasspath {
+ /**
+ * Parses another item to be included. The returned object typically would
+ * not have substitutions resolved. You can throw a ConfigException here to
+ * abort parsing, or return an empty object, but may not return null.
+ *
+ * @param context
+ * some info about the include context
+ * @param what
+ * the include statement's argument
+ * @return a non-null ConfigObject
+ */
+ ConfigObject includeResources(ConfigIncludeContext context, String what);
+}
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com>
+ */
+package com.typesafe.config;
+
+import java.io.File;
+
+/**
+ * Implement this <em>in addition to</em> {@link ConfigIncluder} if you want to
+ * support inclusion of files with the {@code include file("filename")} syntax.
+ * If you do not implement this but do implement {@link ConfigIncluder},
+ * attempts to load files will use the default includer.
+ */
+public interface ConfigIncluderFile {
+ /**
+ * Parses another item to be included. The returned object typically would
+ * not have substitutions resolved. You can throw a ConfigException here to
+ * abort parsing, or return an empty object, but may not return null.
+ *
+ * @param context
+ * some info about the include context
+ * @param what
+ * the include statement's argument
+ * @return a non-null ConfigObject
+ */
+ ConfigObject includeFile(ConfigIncludeContext context, File what);
+}
@@ -0,0 +1,27 @@
+/**
+ * Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com>
+ */
+package com.typesafe.config;
+
+import java.net.URL;
+
+/**
+ * Implement this <em>in addition to</em> {@link ConfigIncluder} if you want to
+ * support inclusion of files with the {@code include url("http://example.com")}
+ * syntax. If you do not implement this but do implement {@link ConfigIncluder},
+ * attempts to load URLs will use the default includer.
+ */
+public interface ConfigIncluderURL {
+ /**
+ * Parses another item to be included. The returned object typically would
+ * not have substitutions resolved. You can throw a ConfigException here to
+ * abort parsing, or return an empty object, but may not return null.
+ *
+ * @param context
+ * some info about the include context
+ * @param what
+ * the include statement's argument
+ * @return a non-null ConfigObject
+ */
+ ConfigObject includeURL(ConfigIncludeContext context, URL what);
+}
@@ -123,8 +123,7 @@ public ConfigParseOptions setIncluder(ConfigIncluder includer) {
if (this.includer == includer)
return this;
else
- return new ConfigParseOptions(this.syntax, this.originDescription,
- this.allowMissing,
+ return new ConfigParseOptions(this.syntax, this.originDescription, this.allowMissing,
includer, this.classLoader);
}
@@ -153,7 +152,7 @@ public ConfigIncluder getIncluder() {
/**
* Set the class loader. If set to null,
* <code>Thread.currentThread().getContextClassLoader()</code> will be used.
- *
+ *
* @param loader
* a class loader or {@code null} to use thread context class
* loader
@@ -77,39 +77,51 @@ public static Config computeCachedConfig(ClassLoader loader, String key,
return cache.getOrElseUpdate(loader, key, updater);
}
+
+ static class FileNameSource implements SimpleIncluder.NameSource {
+ @Override
+ public ConfigParseable nameToParseable(String name, ConfigParseOptions parseOptions) {
+ return Parseable.newFile(new File(name), parseOptions);
+ }
+ };
+
+ static class ClasspathNameSource implements SimpleIncluder.NameSource {
+ @Override
+ public ConfigParseable nameToParseable(String name, ConfigParseOptions parseOptions) {
+ return Parseable.newResources(name, parseOptions);
+ }
+ };
+
+ static class ClasspathNameSourceWithClass implements SimpleIncluder.NameSource {
+ final private Class<?> klass;
+
+ public ClasspathNameSourceWithClass(Class<?> klass) {
+ this.klass = klass;
+ }
+
+ @Override
+ public ConfigParseable nameToParseable(String name, ConfigParseOptions parseOptions) {
+ return Parseable.newResources(klass, name, parseOptions);
+ }
+ };
+
/** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */
- public static ConfigObject parseResourcesAnySyntax(final Class<?> klass,
- String resourceBasename, final ConfigParseOptions baseOptions) {
- NameSource source = new NameSource() {
- @Override
- public ConfigParseable nameToParseable(String name) {
- return Parseable.newResources(klass, name, baseOptions);
- }
- };
+ public static ConfigObject parseResourcesAnySyntax(Class<?> klass, String resourceBasename,
+ ConfigParseOptions baseOptions) {
+ NameSource source = new ClasspathNameSourceWithClass(klass);
return SimpleIncluder.fromBasename(source, resourceBasename, baseOptions);
}
/** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */
public static ConfigObject parseResourcesAnySyntax(String resourceBasename,
- final ConfigParseOptions baseOptions) {
- NameSource source = new NameSource() {
- @Override
- public ConfigParseable nameToParseable(String name) {
- return Parseable.newResources(name, baseOptions);
- }
- };
+ ConfigParseOptions baseOptions) {
+ NameSource source = new ClasspathNameSource();
return SimpleIncluder.fromBasename(source, resourceBasename, baseOptions);
}
/** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */
- public static ConfigObject parseFileAnySyntax(final File basename,
- final ConfigParseOptions baseOptions) {
- NameSource source = new NameSource() {
- @Override
- public ConfigParseable nameToParseable(String name) {
- return Parseable.newFile(new File(name), baseOptions);
- }
- };
+ public static ConfigObject parseFileAnySyntax(File basename, ConfigParseOptions baseOptions) {
+ NameSource source = new FileNameSource();
return SimpleIncluder.fromBasename(source, basename.getPath(), baseOptions);
}
@@ -0,0 +1,14 @@
+/**
+ * Copyright (C) 2011-2012 Typesafe Inc. <http://typesafe.com>
+ */
+package com.typesafe.config.impl;
+
+import com.typesafe.config.ConfigIncluder;
+import com.typesafe.config.ConfigIncluderClasspath;
+import com.typesafe.config.ConfigIncluderFile;
+import com.typesafe.config.ConfigIncluderURL;
+
+interface FullIncluder extends ConfigIncluder, ConfigIncluderFile, ConfigIncluderURL,
+ ConfigIncluderClasspath {
+
+}
@@ -57,7 +57,10 @@ private ConfigParseOptions fixupOptions(ConfigParseOptions baseOptions) {
}
ConfigParseOptions modified = baseOptions.setSyntax(syntax);
+ // make sure the app-provided includer falls back to default
modified = modified.appendIncluder(ConfigImpl.defaultIncluder());
+ // make sure the app-provided includer is complete
+ modified = modified.setIncluder(SimpleIncluder.makeFull(modified.getIncluder()));
return modified;
}
@@ -16,7 +16,6 @@
import com.typesafe.config.ConfigException;
import com.typesafe.config.ConfigIncludeContext;
-import com.typesafe.config.ConfigIncluder;
import com.typesafe.config.ConfigOrigin;
import com.typesafe.config.ConfigParseOptions;
import com.typesafe.config.ConfigSyntax;
@@ -27,8 +26,8 @@
static AbstractConfigValue parse(Iterator<Token> tokens,
ConfigOrigin origin, ConfigParseOptions options,
ConfigIncludeContext includeContext) {
- ParseContext context = new ParseContext(options.getSyntax(), origin,
- tokens, options.getIncluder(), includeContext);
+ ParseContext context = new ParseContext(options.getSyntax(), origin, tokens,
+ SimpleIncluder.makeFull(options.getIncluder()), includeContext);
return context.parse();
}
@@ -80,7 +79,7 @@ public String toString() {
private int lineNumber;
final private Stack<TokenWithComments> buffer;
final private Iterator<Token> tokens;
- final private ConfigIncluder includer;
+ final private FullIncluder includer;
final private ConfigIncludeContext includeContext;
final private ConfigSyntax flavor;
final private ConfigOrigin baseOrigin;
@@ -90,9 +89,8 @@ public String toString() {
// someone may think this is .properties format.
int equalsCount;
- ParseContext(ConfigSyntax flavor, ConfigOrigin origin,
- Iterator<Token> tokens, ConfigIncluder includer,
- ConfigIncludeContext includeContext) {
+ ParseContext(ConfigSyntax flavor, ConfigOrigin origin, Iterator<Token> tokens,
+ FullIncluder includer, ConfigIncludeContext includeContext) {
lineNumber = 1;
buffer = new Stack<TokenWithComments>();
this.tokens = tokens;
@@ -4,6 +4,7 @@
package com.typesafe.config.impl;
import com.typesafe.config.ConfigIncludeContext;
+import com.typesafe.config.ConfigParseOptions;
import com.typesafe.config.ConfigParseable;
class SimpleIncludeContext implements ConfigIncludeContext {
@@ -14,12 +15,11 @@
this.parseable = parseable;
}
- SimpleIncludeContext() {
- this(null);
- }
-
SimpleIncludeContext withParseable(Parseable parseable) {
- return new SimpleIncludeContext(parseable);
+ if (parseable == this.parseable)
+ return this;
+ else
+ return new SimpleIncludeContext(parseable);
}
@Override
@@ -29,4 +29,9 @@ public ConfigParseable relativeTo(String filename) {
else
return null;
}
+
+ @Override
+ public ConfigParseOptions parseOptions() {
+ return SimpleIncluder.clearForInclude(parseable.options());
+ }
}
Oops, something went wrong.

0 comments on commit 3b7d99a

Please sign in to comment.