diff --git a/config/build.sbt b/config/build.sbt index fe5adb6a..a77df75a 100644 --- a/config/build.sbt +++ b/config/build.sbt @@ -4,6 +4,7 @@ import de.johoop.jacoco4sbt.JacocoPlugin.jacoco import com.typesafe.sbt.SbtScalariform import com.typesafe.sbt.SbtScalariform.ScalariformKeys import scalariform.formatter.preferences._ +import com.etsy.sbt.Checkstyle._ SbtScalariform.scalariformSettings @@ -25,6 +26,46 @@ libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % "test" externalResolvers += "Scala Tools Snapshots" at "http://scala-tools.org/repo-snapshots/" +checkstyleSettings + +CheckstyleTasks.checkstyleConfig := baseDirectory.value / "checkstyle-config.xml" + +CheckstyleTasks.checkstyle in Compile := { + val log = streams.value.log + (CheckstyleTasks.checkstyle in Compile).value + val resultFile = (target in Compile).value / "checkstyle-report.xml" + val results = scala.xml.XML.loadFile(resultFile) + val errorFiles = results \\ "checkstyle" \\ "file" + + def errorFromXml(node: scala.xml.NodeSeq): (String, String, String) = { + val line: String = (node \ "@line" text) + val msg: String = (node \ "@message" text) + val source: String = (node \ "@source" text) + (line, msg, source) + } + def errorsFromXml(fileNode: scala.xml.NodeSeq): Seq[(String, String, String, String)] = { + val name: String = (fileNode \ "@name" text) + val errors = (fileNode \\ "error") map { e => errorFromXml(e) } + errors map { case (line, error, source) => (name, line, error, source) } + } + + val errors = errorFiles flatMap { f => errorsFromXml(f) } + + if (errors.nonEmpty) { + for (e <- errors) { + log.error(s"${e._1}:${e._2}: ${e._3} (from ${e._4})") + } + throw new RuntimeException(s"Checkstyle failed with ${errors.size} errors") + } + log.info("No errors from checkstyle") +} + +// add checkstyle as a dependency of doc +doc in Compile := { + (CheckstyleTasks.checkstyle in Compile).value + (doc in Compile).value +} + findbugsSettings findbugsReportType := Some(ReportType.Html) findbugsReportName := Some("findbugs.html") diff --git a/config/checkstyle-config.xml b/config/checkstyle-config.xml new file mode 100644 index 00000000..b5b71d2b --- /dev/null +++ b/config/checkstyle-config.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + diff --git a/config/checkstyle-suppressions.xml b/config/checkstyle-suppressions.xml new file mode 100644 index 00000000..21fb8e51 --- /dev/null +++ b/config/checkstyle-suppressions.xml @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/config/src/main/java/com/typesafe/config/Config.java b/config/src/main/java/com/typesafe/config/Config.java index cd86fcab..4e68148a 100644 --- a/config/src/main/java/com/typesafe/config/Config.java +++ b/config/src/main/java/com/typesafe/config/Config.java @@ -723,24 +723,154 @@ public interface Config extends ConfigMergeable { */ ConfigList getList(String path); + /** + * Gets a list value with boolean elements. Throws if the + * path is unset or null or not a list or contains values not + * convertible to boolean. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of booleans + */ List getBooleanList(String path); + /** + * Gets a list value with number elements. Throws if the + * path is unset or null or not a list or contains values not + * convertible to number. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of numbers + */ List getNumberList(String path); + /** + * Gets a list value with int elements. Throws if the + * path is unset or null or not a list or contains values not + * convertible to int. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of ints + */ List getIntList(String path); + /** + * Gets a list value with long elements. Throws if the + * path is unset or null or not a list or contains values not + * convertible to long. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of longs + */ List getLongList(String path); + /** + * Gets a list value with double elements. Throws if the + * path is unset or null or not a list or contains values not + * convertible to double. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of doubles + */ List getDoubleList(String path); + /** + * Gets a list value with string elements. Throws if the + * path is unset or null or not a list or contains values not + * convertible to string. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of strings + */ List getStringList(String path); + /** + * Gets a list value with object elements. Throws if the + * path is unset or null or not a list or contains values not + * convertible to ConfigObject. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of objects + */ List getObjectList(String path); + /** + * Gets a list value with Config elements. + * Throws if the path is unset or null or not a list or + * contains values not convertible to Config. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of configs + */ List getConfigList(String path); + /** + * Gets a list value with any kind of elements. Throws if the + * path is unset or null or not a list. Each element is + * "unwrapped" (see {@link ConfigValue#unwrapped()}). + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list + */ List getAnyRefList(String path); + /** + * Gets a list value with elements representing a size in + * bytes. Throws if the path is unset or null or not a list + * or contains values not convertible to memory sizes. + * + * @param path + * the path to the list value. + * @return the list at the path + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of memory sizes + */ List getBytesList(String path); /** @@ -751,6 +881,10 @@ public interface Config extends ConfigMergeable { * @param path * a path expression * @return list of memory sizes + * @throws ConfigException.Missing + * if value is absent or null + * @throws ConfigException.WrongType + * if value is not convertible to a list of memory sizes */ List getMemorySizeList(String path); @@ -771,7 +905,7 @@ public interface Config extends ConfigMergeable { /** * Gets a list, converting each value in the list to a duration, using the * same rules as {@link #getDuration(String, TimeUnit)}. - * + * * @since 1.2.0 * @param path * a path expression diff --git a/config/src/main/java/com/typesafe/config/ConfigFactory.java b/config/src/main/java/com/typesafe/config/ConfigFactory.java index 59e14917..eae89afe 100644 --- a/config/src/main/java/com/typesafe/config/ConfigFactory.java +++ b/config/src/main/java/com/typesafe/config/ConfigFactory.java @@ -167,6 +167,16 @@ public final class ConfigFactory { return load(checkedContextClassLoader("load"), config); } + /** + * Like {@link #load(Config)} but allows you to specify + * the class loader for looking up resources. + * + * @param loader + * the class loader to use to find resources + * @param config + * the application's portion of the configuration + * @return resolved configuration with overrides and fallbacks added + */ public static Config load(ClassLoader loader, Config config) { return load(loader, config, ConfigResolveOptions.defaults()); } @@ -269,7 +279,7 @@ public final class ConfigFactory { } /** - * Like {@link #load()} but allows specifying parse options + * Like {@link #load()} but allows specifying parse options. * * @param parseOptions * Options for parsing resources @@ -299,7 +309,7 @@ public final class ConfigFactory { /** * Like {@link #load()} but allows specifying a class loader other than the - * thread's current context class loader, and parse options + * thread's current context class loader and also specify parse options. * * @param loader * class loader for finding resources (overrides any loader in parseOptions) @@ -313,7 +323,7 @@ public final class ConfigFactory { /** * Like {@link #load()} but allows specifying a class loader other than the - * thread's current context class loader, and resolve options + * thread's current context class loader and also specify resolve options. * * @param loader * class loader for finding resources @@ -328,7 +338,7 @@ public final class ConfigFactory { /** * Like {@link #load()} but allows specifying a class loader other than the - * thread's current context class loader, parse options, and resolve options + * thread's current context class loader, parse options, and resolve options. * * @param loader * class loader for finding resources (overrides any loader in parseOptions) @@ -628,22 +638,79 @@ public final class ConfigFactory { return Parseable.newProperties(properties, options).parse().toConfig(); } + /** + * Like {@link parseProperties(Properties, ConfigParseOptions)} but uses default + * parse options. + * @param properties + * a Java Properties object + * @return the parsed configuration + */ public static Config parseProperties(Properties properties) { return parseProperties(properties, ConfigParseOptions.defaults()); } + /** + * Parses a Reader into a Config instance. Does not call + * {@link Config#resolve} or merge the parsed stream with any + * other configuration; this method parses a single stream and + * does nothing else. It does process "include" statements in + * the parsed stream, and may end up doing other IO due to those + * statements. + * + * @param reader + * the reader to parse + * @param options + * parse options to control how the reader is interpreted + * @return the parsed configuration + * @throws ConfigException on IO or parse errors + */ public static Config parseReader(Reader reader, ConfigParseOptions options) { return Parseable.newReader(reader, options).parse().toConfig(); } + /** + * Parses a reader into a Config instance as with + * {@link #parseReader(Reader,ConfigParseOptions)} but always uses the + * default parse options. + * + * @param reader + * the reader to parse + * @return the parsed configuration + * @throws ConfigException on IO or parse errors + */ public static Config parseReader(Reader reader) { return parseReader(reader, ConfigParseOptions.defaults()); } + /** + * Parses a URL into a Config instance. Does not call + * {@link Config#resolve} or merge the parsed stream with any + * other configuration; this method parses a single stream and + * does nothing else. It does process "include" statements in + * the parsed stream, and may end up doing other IO due to those + * statements. + * + * @param url + * the url to parse + * @param options + * parse options to control how the url is interpreted + * @return the parsed configuration + * @throws ConfigException on IO or parse errors + */ public static Config parseURL(URL url, ConfigParseOptions options) { return Parseable.newURL(url, options).parse().toConfig(); } + /** + * Parses a url into a Config instance as with + * {@link #parseURL(URL,ConfigParseOptions)} but always uses the + * default parse options. + * + * @param url + * the url to parse + * @return the parsed configuration + * @throws ConfigException on IO or parse errors + */ public static Config parseURL(URL url) { return parseURL(url, ConfigParseOptions.defaults()); } @@ -766,6 +833,19 @@ public final class ConfigFactory { .toConfig(); } + /** + * Like {@link #parseResources(Class,String,ConfigParseOptions)} but always uses + * default parse options. + * + * @param klass + * klass.getClassLoader() will be used to load + * resources, and non-absolute resource names will have this + * class's package added + * @param resource + * resource to look up, relative to klass's package + * or absolute starting with a "/" + * @return the parsed configuration + */ public static Config parseResources(Class klass, String resource) { return parseResources(klass, resource, ConfigParseOptions.defaults()); } @@ -806,6 +886,19 @@ public final class ConfigFactory { options).toConfig(); } + /** + * Like {@link #parseResourcesAnySyntax(Class,String,ConfigParseOptions)} + * but always uses default parse options. + * + * @param klass + * klass.getClassLoader() will be used to load + * resources, and non-absolute resource names will have this + * class's package added + * @param resourceBasename + * a resource name as in {@link java.lang.Class#getResource}, + * with or without extension + * @return the parsed configuration + */ public static Config parseResourcesAnySyntax(Class klass, String resourceBasename) { return parseResourcesAnySyntax(klass, resourceBasename, ConfigParseOptions.defaults()); } @@ -837,6 +930,16 @@ public final class ConfigFactory { return parseResources(resource, options.setClassLoader(loader)); } + /** + * Like {@link #parseResources(ClassLoader,String,ConfigParseOptions)} but always uses + * default parse options. + * + * @param loader + * will be used to load resources + * @param resource + * resource to look up in the loader + * @return the parsed configuration + */ public static Config parseResources(ClassLoader loader, String resource) { return parseResources(loader, resource, ConfigParseOptions.defaults()); } @@ -870,6 +973,18 @@ public final class ConfigFactory { .toConfig(); } + /** + * Like {@link #parseResourcesAnySyntax(ClassLoader,String,ConfigParseOptions)} but always uses + * default parse options. + * + * @param loader + * will be used to load resources + * @param resourceBasename + * a resource name as in + * {@link java.lang.ClassLoader#getResource}, with or without + * extension + * @return the parsed configuration + */ public static Config parseResourcesAnySyntax(ClassLoader loader, String resourceBasename) { return parseResourcesAnySyntax(loader, resourceBasename, ConfigParseOptions.defaults()); } diff --git a/config/src/main/java/com/typesafe/config/ConfigParseOptions.java b/config/src/main/java/com/typesafe/config/ConfigParseOptions.java index 62084b52..e1c1a770 100644 --- a/config/src/main/java/com/typesafe/config/ConfigParseOptions.java +++ b/config/src/main/java/com/typesafe/config/ConfigParseOptions.java @@ -36,6 +36,12 @@ public final class ConfigParseOptions { this.classLoader = classLoader; } + /** + * Gets an instance of ConfigParseOptions with all fields + * set to the default values. Start with this instance and make any + * changes you need. + * @return the default parse options + */ public static ConfigParseOptions defaults() { return new ConfigParseOptions(null, null, true, null, null); } @@ -56,6 +62,10 @@ public final class ConfigParseOptions { this.includer, this.classLoader); } + /** + * Gets the current syntax option, which may be null for "any". + * @return the current syntax or null + */ public ConfigSyntax getSyntax() { return syntax; } @@ -82,6 +92,10 @@ public final class ConfigParseOptions { this.includer, this.classLoader); } + /** + * Gets the current origin description, which may be null for "automatic". + * @return the current origin description or null + */ public String getOriginDescription() { return originDescription; } @@ -110,12 +124,17 @@ public final class ConfigParseOptions { this.includer, this.classLoader); } + /** + * Gets the current "allow missing" flag. + * @return whether we allow missing files + */ public boolean getAllowMissing() { return allowMissing; } /** - * Set a ConfigIncluder which customizes how includes are handled. + * Set a {@link ConfigIncluder} which customizes how includes are handled. + * null means to use the default includer. * * @param includer the includer to use or null for default * @return new version of the parse options with different includer @@ -128,6 +147,15 @@ public final class ConfigParseOptions { includer, this.classLoader); } + /** + * Prepends a {@link ConfigIncluder} which customizes how + * includes are handled. To prepend your includer, the + * library calls {@link ConfigIncluder#withFallback} on your + * includer to append the existing includer to it. + * + * @param includer the includer to prepend (may not be null) + * @return new version of the parse options with different includer + */ public ConfigParseOptions prependIncluder(ConfigIncluder includer) { if (includer == null) throw new NullPointerException("null includer passed to prependIncluder"); @@ -139,6 +167,14 @@ public final class ConfigParseOptions { return setIncluder(includer); } + /** + * Appends a {@link ConfigIncluder} which customizes how + * includes are handled. To append, the library calls {@link + * ConfigIncluder#withFallback} on the existing includer. + * + * @param includer the includer to append (may not be null) + * @return new version of the parse options with different includer + */ public ConfigParseOptions appendIncluder(ConfigIncluder includer) { if (includer == null) throw new NullPointerException("null includer passed to appendIncluder"); @@ -150,6 +186,10 @@ public final class ConfigParseOptions { return setIncluder(includer); } + /** + * Gets the current includer (will be null for the default includer). + * @return current includer or null + */ public ConfigIncluder getIncluder() { return includer; } diff --git a/project/plugins.sbt b/project/plugins.sbt index 7a8b4f52..b71a6a39 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,6 +4,8 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-pgp" % "0.8.1") addSbtPlugin("com.typesafe.sbt" % "sbt-osgi" % "0.6.0") addSbtPlugin("com.typesafe.sbt" % "sbt-scalariform" % "1.2.1") +addSbtPlugin("com.etsy" % "sbt-checkstyle-plugin" % "0.4.1") + resolvers += "jgit-repo" at "http://download.eclipse.org/jgit/maven" addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.6.2") addSbtPlugin("com.typesafe.sbt" % "sbt-javaversioncheck" % "0.1.0")