From b8be8f3869eeb527a12ae8622870daa67c0da424 Mon Sep 17 00:00:00 2001 From: Patrik Nordwall Date: Sat, 19 Nov 2011 09:23:01 +0100 Subject: [PATCH] Latest config lib --- .../main/java/com/typesafe/config/Config.java | 6 +- .../com/typesafe/config/ConfigException.java | 3 + .../com/typesafe/config/ConfigFactory.java | 5 +- .../typesafe/config/ConfigIncludeContext.java | 3 + .../com/typesafe/config/ConfigIncluder.java | 3 + .../java/com/typesafe/config/ConfigList.java | 3 + .../com/typesafe/config/ConfigMergeable.java | 48 ++------ .../com/typesafe/config/ConfigObject.java | 6 +- .../com/typesafe/config/ConfigOrigin.java | 3 + .../typesafe/config/ConfigParseOptions.java | 3 + .../com/typesafe/config/ConfigParseable.java | 3 + .../typesafe/config/ConfigResolveOptions.java | 3 + .../java/com/typesafe/config/ConfigRoot.java | 6 +- .../com/typesafe/config/ConfigSyntax.java | 3 + .../java/com/typesafe/config/ConfigValue.java | 6 +- .../typesafe/config/ConfigValueFactory.java | 3 + .../com/typesafe/config/ConfigValueType.java | 3 + .../config/impl/AbstractConfigObject.java | 108 ++++++++++-------- .../config/impl/AbstractConfigValue.java | 62 ++++++++-- .../typesafe/config/impl/ConfigBoolean.java | 3 + .../config/impl/ConfigDelayedMerge.java | 84 +++++++++----- .../config/impl/ConfigDelayedMergeObject.java | 70 +++++++----- .../typesafe/config/impl/ConfigDouble.java | 3 + .../com/typesafe/config/impl/ConfigImpl.java | 34 +----- .../com/typesafe/config/impl/ConfigInt.java | 3 + .../com/typesafe/config/impl/ConfigLong.java | 3 + .../com/typesafe/config/impl/ConfigNull.java | 3 + .../typesafe/config/impl/ConfigNumber.java | 16 +++ .../typesafe/config/impl/ConfigString.java | 3 + .../config/impl/ConfigSubstitution.java | 67 +++++++---- .../com/typesafe/config/impl/ConfigUtil.java | 3 + .../config/impl/DefaultTransformer.java | 3 + .../com/typesafe/config/impl/FromMapMode.java | 3 + .../com/typesafe/config/impl/Parseable.java | 3 + .../java/com/typesafe/config/impl/Parser.java | 3 + .../java/com/typesafe/config/impl/Path.java | 3 + .../com/typesafe/config/impl/PathBuilder.java | 3 + .../config/impl/PropertiesParser.java | 8 +- .../typesafe/config/impl/ResolveStatus.java | 3 + .../com/typesafe/config/impl/RootConfig.java | 15 +-- .../typesafe/config/impl/SimpleConfig.java | 34 +++--- .../config/impl/SimpleConfigList.java | 3 + .../config/impl/SimpleConfigObject.java | 21 +++- .../config/impl/SimpleConfigOrigin.java | 3 + .../config/impl/SubstitutionResolver.java | 3 + .../java/com/typesafe/config/impl/Token.java | 3 + .../com/typesafe/config/impl/TokenType.java | 3 + .../com/typesafe/config/impl/Tokenizer.java | 3 + .../java/com/typesafe/config/impl/Tokens.java | 3 + .../com/typesafe/config/impl/Unmergeable.java | 3 + 50 files changed, 449 insertions(+), 246 deletions(-) diff --git a/akka-actor/src/main/java/com/typesafe/config/Config.java b/akka-actor/src/main/java/com/typesafe/config/Config.java index 94abf9d9f5..3a820033a8 100644 --- a/akka-actor/src/main/java/com/typesafe/config/Config.java +++ b/akka-actor/src/main/java/com/typesafe/config/Config.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; import java.util.List; @@ -53,9 +56,6 @@ public interface Config extends ConfigMergeable { @Override Config withFallback(ConfigMergeable other); - @Override - Config withFallbacks(ConfigMergeable... others); - @Override ConfigObject toValue(); diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigException.java b/akka-actor/src/main/java/com/typesafe/config/ConfigException.java index 894f6bc13a..7763231108 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigException.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigException.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; /** diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java b/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java index cd82e3fa11..b55c9abdf8 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigFactory.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; import java.io.File; @@ -74,7 +77,7 @@ public final class ConfigFactory { Config referenceFiles = parseResourcesForPath(rootPath + ".reference", options); - return system.withFallbacks(mainFiles, referenceFiles); + return system.withFallback(mainFiles).withFallback(referenceFiles); } public static ConfigRoot emptyRoot(String rootPath) { diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigIncludeContext.java b/akka-actor/src/main/java/com/typesafe/config/ConfigIncludeContext.java index a79fa6edbc..a770250171 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigIncludeContext.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigIncludeContext.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigIncluder.java b/akka-actor/src/main/java/com/typesafe/config/ConfigIncluder.java index 5f100a5292..364b8c5e30 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigIncluder.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigIncluder.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; /** diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigList.java b/akka-actor/src/main/java/com/typesafe/config/ConfigList.java index 5efe7014fe..0688c29abe 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigList.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigList.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; import java.util.List; diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigMergeable.java b/akka-actor/src/main/java/com/typesafe/config/ConfigMergeable.java index c1b0b6fc32..deec42bec1 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigMergeable.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigMergeable.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; /** @@ -18,35 +21,16 @@ public interface ConfigMergeable { * Config instances do anything in this method (they need to merge the * fallback keys into themselves). All other values just return the original * value, since they automatically override any fallback. - * + * * The semantics of merging are described in * https://github.com/havocp/config/blob/master/HOCON.md - * - * Prefer withFallbacks(), listing all your fallbacks at once, - * over this method. - * - * When using this method, there is an easy way to write a wrong - * loop. Even if you don't loop, it's easy to do the equivalent wrong - * thing. - * - * - * // WRONG - * for (ConfigMergeable fallback : fallbacks) { - * // DO NOT DO THIS - * result = result.withFallback(fallback); - * } - * - * - * This is wrong because when result is an object and - * fallback is a non-object, - * result.withFallback(fallback) returns an object. Then if - * there are more objects, they are merged into that object. But the correct - * semantics are that a non-object will block merging any more objects later - * in the list. To get it right, you need to iterate backward. Simplest - * solution: prefer withFallbacks() which is harder to get - * wrong, and merge all your fallbacks in one call to - * withFallbacks(). - * + * + * Note that objects do not merge "across" non-objects; if you do + * object.withFallback(nonObject).withFallback(otherObject), + * then otherObject will simply be ignored. This is an + * intentional part of how merging works. Both non-objects, and any object + * which has fallen back to a non-object, block subsequent fallbacks. + * * @param other * an object whose keys should be used if the keys are not * present in this one @@ -54,14 +38,4 @@ public interface ConfigMergeable { * used) */ ConfigMergeable withFallback(ConfigMergeable other); - - /** - * Convenience method just calls withFallback() on each of the values; - * earlier values in the list win over later ones. The semantics of merging - * are described in https://github.com/havocp/config/blob/master/HOCON.md - * - * @param fallbacks - * @return a version of the object with the requested fallbacks merged in - */ - ConfigMergeable withFallbacks(ConfigMergeable... others); } diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigObject.java b/akka-actor/src/main/java/com/typesafe/config/ConfigObject.java index 1763358496..c559f9e4ee 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigObject.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigObject.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; import java.util.Map; @@ -58,9 +61,6 @@ public interface ConfigObject extends ConfigValue, Map { @Override ConfigObject withFallback(ConfigMergeable other); - @Override - ConfigObject withFallbacks(ConfigMergeable... others); - /** * Gets a ConfigValue at the given key, or returns null if there is no * value. The returned ConfigValue may have ConfigValueType.NULL or any diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigOrigin.java b/akka-actor/src/main/java/com/typesafe/config/ConfigOrigin.java index 3935888060..73240736e5 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigOrigin.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigOrigin.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; /** diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigParseOptions.java b/akka-actor/src/main/java/com/typesafe/config/ConfigParseOptions.java index 8b26fc45dd..ac0c8f3974 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigParseOptions.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigParseOptions.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigParseable.java b/akka-actor/src/main/java/com/typesafe/config/ConfigParseable.java index 9845d2acde..4c19b5451a 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigParseable.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigParseable.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; import java.net.URL; diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigResolveOptions.java b/akka-actor/src/main/java/com/typesafe/config/ConfigResolveOptions.java index 91e3320cd1..6f572a84e8 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigResolveOptions.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigResolveOptions.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; public final class ConfigResolveOptions { diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigRoot.java b/akka-actor/src/main/java/com/typesafe/config/ConfigRoot.java index 7554280688..d8f25e89d6 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigRoot.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigRoot.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; /** @@ -21,9 +24,6 @@ public interface ConfigRoot extends Config { @Override ConfigRoot withFallback(ConfigMergeable fallback); - @Override - ConfigRoot withFallbacks(ConfigMergeable... fallbacks); - /** * Gets the global app name that this root represents. * diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigSyntax.java b/akka-actor/src/main/java/com/typesafe/config/ConfigSyntax.java index c1c68d0783..4f43fe7365 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigSyntax.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigSyntax.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; public enum ConfigSyntax { diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigValue.java b/akka-actor/src/main/java/com/typesafe/config/ConfigValue.java index 006b89a9de..8b50f7b205 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigValue.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigValue.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; /** @@ -29,7 +32,4 @@ public interface ConfigValue extends ConfigMergeable { @Override ConfigValue withFallback(ConfigMergeable other); - - @Override - ConfigValue withFallbacks(ConfigMergeable... fallbacks); } diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigValueFactory.java b/akka-actor/src/main/java/com/typesafe/config/ConfigValueFactory.java index 05ffefa152..fd63a6ffe5 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigValueFactory.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigValueFactory.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; import java.util.Collection; diff --git a/akka-actor/src/main/java/com/typesafe/config/ConfigValueType.java b/akka-actor/src/main/java/com/typesafe/config/ConfigValueType.java index 1de791698a..0ead8e1965 100644 --- a/akka-actor/src/main/java/com/typesafe/config/ConfigValueType.java +++ b/akka-actor/src/main/java/com/typesafe/config/ConfigValueType.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config; /** diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java b/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java index 6e4ff47c5b..d9d41e3f04 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigObject.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.ArrayList; @@ -99,54 +102,61 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements return ConfigValueType.OBJECT; } - protected abstract AbstractConfigObject newCopy(ResolveStatus status); + protected abstract AbstractConfigObject newCopy(ResolveStatus status, + boolean ignoresFallbacks); @Override - public AbstractConfigObject withFallbacks(ConfigMergeable... others) { - return (AbstractConfigObject) super.withFallbacks(others); + protected AbstractConfigObject newCopy(boolean ignoresFallbacks) { + return newCopy(resolveStatus(), ignoresFallbacks); + } + + @Override + protected final AbstractConfigObject mergedWithTheUnmergeable(Unmergeable fallback) { + if (ignoresFallbacks()) + throw new ConfigException.BugOrBroken("should not be reached"); + + List stack = new ArrayList(); + if (this instanceof Unmergeable) { + stack.addAll(((Unmergeable) this).unmergedValues()); + } else { + stack.add(this); + } + stack.addAll(fallback.unmergedValues()); + return new ConfigDelayedMergeObject(mergeOrigins(stack), stack, + ((AbstractConfigValue) fallback).ignoresFallbacks()); + } + + @Override + protected AbstractConfigObject mergedWithObject(AbstractConfigObject fallback) { + if (ignoresFallbacks()) + throw new ConfigException.BugOrBroken("should not be reached"); + + boolean allResolved = true; + Map merged = new HashMap(); + Set allKeys = new HashSet(); + allKeys.addAll(this.keySet()); + allKeys.addAll(fallback.keySet()); + for (String key : allKeys) { + AbstractConfigValue first = this.peek(key); + AbstractConfigValue second = fallback.peek(key); + AbstractConfigValue kept; + if (first == null) + kept = second; + else if (second == null) + kept = first; + else + kept = first.withFallback(second); + merged.put(key, kept); + if (kept.resolveStatus() == ResolveStatus.UNRESOLVED) + allResolved = false; + } + return new SimpleConfigObject(mergeOrigins(this, fallback), merged, + ResolveStatus.fromBoolean(allResolved), fallback.ignoresFallbacks()); } @Override public AbstractConfigObject withFallback(ConfigMergeable mergeable) { - ConfigValue other = mergeable.toValue(); - - if (other instanceof Unmergeable) { - List stack = new ArrayList(); - stack.add(this); - stack.addAll(((Unmergeable) other).unmergedValues()); - return new ConfigDelayedMergeObject(mergeOrigins(stack), stack); - } else if (other instanceof AbstractConfigObject) { - AbstractConfigObject fallback = (AbstractConfigObject) other; - if (fallback.isEmpty()) { - return this; // nothing to do - } else { - boolean allResolved = true; - Map merged = new HashMap(); - Set allKeys = new HashSet(); - allKeys.addAll(this.keySet()); - allKeys.addAll(fallback.keySet()); - for (String key : allKeys) { - AbstractConfigValue first = this.peek(key); - AbstractConfigValue second = fallback.peek(key); - AbstractConfigValue kept; - if (first == null) - kept = second; - else if (second == null) - kept = first; - else - kept = first.withFallback(second); - merged.put(key, kept); - if (kept.resolveStatus() == ResolveStatus.UNRESOLVED) - allResolved = false; - } - return new SimpleConfigObject(mergeOrigins(this, fallback), - merged, ResolveStatus.fromBoolean(allResolved)); - } - } else { - // falling back to a non-object has no effect, we just override - // primitive values. - return this; - } + return (AbstractConfigObject) super.withFallback(mergeable); } static ConfigOrigin mergeOrigins( @@ -166,7 +176,9 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements if (desc.startsWith(prefix)) desc = desc.substring(prefix.length()); - if (v instanceof ConfigObject && ((ConfigObject) v).isEmpty()) { + if (v instanceof AbstractConfigObject + && ((AbstractConfigObject) v).resolveStatus() == ResolveStatus.RESOLVED + && ((ConfigObject) v).isEmpty()) { // don't include empty files or the .empty() // config in the description, since they are // likely to be "implementation details" @@ -206,7 +218,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements } } if (changes == null) { - return newCopy(newResolveStatus); + return newCopy(newResolveStatus, ignoresFallbacks()); } else { Map modified = new HashMap(); for (String k : keySet()) { @@ -216,8 +228,8 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements modified.put(k, peek(k)); } } - return new SimpleConfigObject(origin(), modified, - newResolveStatus); + return new SimpleConfigObject(origin(), modified, newResolveStatus, + ignoresFallbacks()); } } @@ -311,7 +323,8 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements @Override public boolean equals(Object other) { - // note that "origin" is deliberately NOT part of equality + // note that "origin" is deliberately NOT part of equality. + // neither are other "extras" like ignoresFallbacks or resolve status. if (other instanceof ConfigObject) { // optimization to avoid unwrapped() for two ConfigObject, // which is what AbstractConfigValue does. @@ -324,6 +337,7 @@ abstract class AbstractConfigObject extends AbstractConfigValue implements @Override public int hashCode() { // note that "origin" is deliberately NOT part of equality + // neither are other "extras" like ignoresFallbacks or resolve status. return mapHash(this); } diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigValue.java b/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigValue.java index c4e5c3bf51..2125cf723b 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigValue.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/AbstractConfigValue.java @@ -1,5 +1,9 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; +import com.typesafe.config.ConfigException; import com.typesafe.config.ConfigMergeable; import com.typesafe.config.ConfigOrigin; import com.typesafe.config.ConfigResolveOptions; @@ -72,17 +76,61 @@ abstract class AbstractConfigValue implements ConfigValue { return this; } - @Override - public AbstractConfigValue withFallback(ConfigMergeable other) { + protected AbstractConfigValue newCopy(boolean ignoresFallbacks) { return this; } + // this is virtualized rather than a field because only some subclasses + // really need to store the boolean, and they may be able to pack it + // with another boolean to save space. + protected boolean ignoresFallbacks() { + return true; + } + + private ConfigException badMergeException() { + if (ignoresFallbacks()) + throw new ConfigException.BugOrBroken( + "method should not have been called with ignoresFallbacks=true" + + getClass().getSimpleName()); + else + throw new ConfigException.BugOrBroken("should override this in " + + getClass().getSimpleName()); + } + + protected AbstractConfigValue mergedWithTheUnmergeable(Unmergeable fallback) { + throw badMergeException(); + } + + protected AbstractConfigValue mergedWithObject(AbstractConfigObject fallback) { + throw badMergeException(); + } + @Override - public AbstractConfigValue withFallbacks(ConfigMergeable... fallbacks) { - // note: this is a no-op unless the subclass overrides withFallback(). - // But we need to do this because subclass withFallback() may not - // just "return this" - return ConfigImpl.merge(AbstractConfigValue.class, this, fallbacks); + public AbstractConfigValue withFallback(ConfigMergeable mergeable) { + if (ignoresFallbacks()) { + return this; + } else { + ConfigValue other = mergeable.toValue(); + + if (other instanceof Unmergeable) { + return mergedWithTheUnmergeable((Unmergeable) other); + } else if (other instanceof AbstractConfigObject) { + AbstractConfigObject fallback = (AbstractConfigObject) other; + if (fallback.resolveStatus() == ResolveStatus.RESOLVED && fallback.isEmpty()) { + if (fallback.ignoresFallbacks()) + return newCopy(true /* ignoresFallbacks */); + else + return this; + } else { + return mergedWithObject((AbstractConfigObject) other); + } + } else { + // falling back to a non-object doesn't merge anything, and also + // prohibits merging any objects that we fall back to later. + // so we have to switch to ignoresFallbacks mode. + return newCopy(true /* ignoresFallbacks */); + } + } } protected boolean canEqual(Object other) { diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigBoolean.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigBoolean.java index 614a12e683..d45dbd1326 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigBoolean.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigBoolean.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigOrigin; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDelayedMerge.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDelayedMerge.java index 3215958d22..0c20aa5701 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDelayedMerge.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDelayedMerge.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.ArrayList; @@ -5,10 +8,8 @@ import java.util.Collection; import java.util.List; import com.typesafe.config.ConfigException; -import com.typesafe.config.ConfigMergeable; import com.typesafe.config.ConfigOrigin; import com.typesafe.config.ConfigResolveOptions; -import com.typesafe.config.ConfigValue; import com.typesafe.config.ConfigValueType; /** @@ -24,14 +25,26 @@ final class ConfigDelayedMerge extends AbstractConfigValue implements // earlier items in the stack win final private List stack; + final private boolean ignoresFallbacks; - ConfigDelayedMerge(ConfigOrigin origin, List stack) { + ConfigDelayedMerge(ConfigOrigin origin, List stack, + boolean ignoresFallbacks) { super(origin); this.stack = stack; + this.ignoresFallbacks = ignoresFallbacks; if (stack.isEmpty()) throw new ConfigException.BugOrBroken( "creating empty delayed merge value"); + for (AbstractConfigValue v : stack) { + if (v instanceof ConfigDelayedMerge || v instanceof ConfigDelayedMergeObject) + throw new ConfigException.BugOrBroken( + "placed nested DelayedMerge in a ConfigDelayedMerge, should have consolidated stack"); + } + } + + ConfigDelayedMerge(ConfigOrigin origin, List stack) { + this(origin, stack, false /* ignoresFallbacks */); } @Override @@ -57,18 +70,19 @@ final class ConfigDelayedMerge extends AbstractConfigValue implements List stack, SubstitutionResolver resolver, int depth, ConfigResolveOptions options) { // to resolve substitutions, we need to recursively resolve - // the stack of stuff to merge, and then merge the stack. - List toMerge = new ArrayList(); + // the stack of stuff to merge, and merge the stack so + // we won't be a delayed merge anymore. + AbstractConfigValue merged = null; for (AbstractConfigValue v : stack) { AbstractConfigValue resolved = resolver.resolve(v, depth, options); - toMerge.add(resolved); + if (merged == null) + merged = resolved; + else + merged = merged.withFallback(resolved); } - // we shouldn't have a delayed merge object with an empty stack, so - // it should be safe to ignore the toMerge.isEmpty case. - return ConfigImpl.merge(AbstractConfigValue.class, toMerge.get(0), - toMerge.subList(1, toMerge.size())); + return merged; } @Override @@ -82,30 +96,40 @@ final class ConfigDelayedMerge extends AbstractConfigValue implements for (AbstractConfigValue o : stack) { newStack.add(o.relativized(prefix)); } - return new ConfigDelayedMerge(origin(), newStack); + return new ConfigDelayedMerge(origin(), newStack, ignoresFallbacks); } @Override - public AbstractConfigValue withFallback(ConfigMergeable mergeable) { - ConfigValue other = mergeable.toValue(); + protected boolean ignoresFallbacks() { + return ignoresFallbacks; + } - if (other instanceof AbstractConfigObject - || other instanceof Unmergeable) { - // if we turn out to be an object, and the fallback also does, - // then a merge may be required; delay until we resolve. - List newStack = new ArrayList(); - newStack.addAll(stack); - if (other instanceof Unmergeable) - newStack.addAll(((Unmergeable) other).unmergedValues()); - else - newStack.add((AbstractConfigValue) other); - return new ConfigDelayedMerge( - AbstractConfigObject.mergeOrigins(newStack), newStack); - } else { - // if the other is not an object, there won't be anything - // to merge with, so we are it even if we are an object. - return this; - } + @Override + protected final ConfigDelayedMerge mergedWithTheUnmergeable(Unmergeable fallback) { + if (ignoresFallbacks) + throw new ConfigException.BugOrBroken("should not be reached"); + + // if we turn out to be an object, and the fallback also does, + // then a merge may be required; delay until we resolve. + List newStack = new ArrayList(); + newStack.addAll(stack); + newStack.addAll(fallback.unmergedValues()); + return new ConfigDelayedMerge(AbstractConfigObject.mergeOrigins(newStack), newStack, + ((AbstractConfigValue) fallback).ignoresFallbacks()); + } + + @Override + protected final ConfigDelayedMerge mergedWithObject(AbstractConfigObject fallback) { + if (ignoresFallbacks) + throw new ConfigException.BugOrBroken("should not be reached"); + + // if we turn out to be an object, and the fallback also does, + // then a merge may be required; delay until we resolve. + List newStack = new ArrayList(); + newStack.addAll(stack); + newStack.add(fallback); + return new ConfigDelayedMerge(AbstractConfigObject.mergeOrigins(newStack), newStack, + fallback.ignoresFallbacks()); } @Override diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDelayedMergeObject.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDelayedMergeObject.java index 5a05403b9e..6f381afc48 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDelayedMergeObject.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDelayedMergeObject.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.ArrayList; @@ -18,25 +21,40 @@ class ConfigDelayedMergeObject extends AbstractConfigObject implements Unmergeable { final private List stack; + final private boolean ignoresFallbacks; ConfigDelayedMergeObject(ConfigOrigin origin, List stack) { + this(origin, stack, false /* ignoresFallbacks */); + } + + ConfigDelayedMergeObject(ConfigOrigin origin, List stack, + boolean ignoresFallbacks) { super(origin); this.stack = stack; + this.ignoresFallbacks = ignoresFallbacks; + if (stack.isEmpty()) throw new ConfigException.BugOrBroken( "creating empty delayed merge object"); if (!(stack.get(0) instanceof AbstractConfigObject)) throw new ConfigException.BugOrBroken( "created a delayed merge object not guaranteed to be an object"); + + for (AbstractConfigValue v : stack) { + if (v instanceof ConfigDelayedMerge || v instanceof ConfigDelayedMergeObject) + throw new ConfigException.BugOrBroken( + "placed nested DelayedMerge in a ConfigDelayedMergeObject, should have consolidated stack"); + } } @Override - public ConfigDelayedMergeObject newCopy(ResolveStatus status) { + protected ConfigDelayedMergeObject newCopy(ResolveStatus status, + boolean ignoresFallbacks) { if (status != resolveStatus()) throw new ConfigException.BugOrBroken( "attempt to create resolved ConfigDelayedMergeObject"); - return new ConfigDelayedMergeObject(origin(), stack); + return new ConfigDelayedMergeObject(origin(), stack, ignoresFallbacks); } @Override @@ -64,36 +82,32 @@ class ConfigDelayedMergeObject extends AbstractConfigObject implements for (AbstractConfigValue o : stack) { newStack.add(o.relativized(prefix)); } - return new ConfigDelayedMergeObject(origin(), newStack); + return new ConfigDelayedMergeObject(origin(), newStack, + ignoresFallbacks); + } + + @Override + protected boolean ignoresFallbacks() { + return ignoresFallbacks; + } + + @Override + protected ConfigDelayedMergeObject mergedWithObject(AbstractConfigObject fallback) { + if (ignoresFallbacks) + throw new ConfigException.BugOrBroken("should not be reached"); + + // since we are an object, and the fallback is, we'll need to + // merge the fallback once we resolve. + List newStack = new ArrayList(); + newStack.addAll(stack); + newStack.add(fallback); + return new ConfigDelayedMergeObject(AbstractConfigObject.mergeOrigins(newStack), newStack, + fallback.ignoresFallbacks()); } @Override public ConfigDelayedMergeObject withFallback(ConfigMergeable mergeable) { - ConfigValue other = mergeable.toValue(); - - if (other instanceof AbstractConfigObject - || other instanceof Unmergeable) { - // since we are an object, and the fallback could be, - // then a merge may be required; delay until we resolve. - List newStack = new ArrayList(); - newStack.addAll(stack); - if (other instanceof Unmergeable) - newStack.addAll(((Unmergeable) other).unmergedValues()); - else - newStack.add((AbstractConfigValue) other); - return new ConfigDelayedMergeObject( - AbstractConfigObject.mergeOrigins(newStack), - newStack); - } else { - // if the other is not an object, there won't be anything - // to merge with. - return this; - } - } - - @Override - public ConfigDelayedMergeObject withFallbacks(ConfigMergeable... others) { - return (ConfigDelayedMergeObject) super.withFallbacks(others); + return (ConfigDelayedMergeObject) super.withFallback(mergeable); } @Override diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDouble.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDouble.java index 483cf9cd79..3317974453 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDouble.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigDouble.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigOrigin; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigImpl.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigImpl.java index 9f45cb37cd..8c2bd01ec1 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigImpl.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigImpl.java @@ -1,20 +1,20 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.io.File; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; -import java.util.ListIterator; import java.util.Map; import com.typesafe.config.Config; import com.typesafe.config.ConfigException; import com.typesafe.config.ConfigIncludeContext; import com.typesafe.config.ConfigIncluder; -import com.typesafe.config.ConfigMergeable; import com.typesafe.config.ConfigObject; import com.typesafe.config.ConfigOrigin; import com.typesafe.config.ConfigParseOptions; @@ -26,32 +26,6 @@ import com.typesafe.config.ConfigValue; /** This is public but is only supposed to be used by the "config" package */ public class ConfigImpl { - static T merge(Class klass, T first, - ConfigMergeable... others) { - List stack = Arrays.asList(others); - return merge(klass, first, stack); - } - - static T merge(Class klass, T first, - List stack) { - if (stack.isEmpty()) { - return first; - } else { - // to be consistent with the semantics of duplicate keys - // in the same file, we have to go backward like this. - // importantly, a primitive value always permanently - // hides a previous object value. - ListIterator i = stack - .listIterator(stack.size()); - ConfigMergeable merged = i.previous(); - while (i.hasPrevious()) { - merged = i.previous().withFallback(merged); - } - merged = first.withFallback(merged); - return klass.cast(merged); - } - } - private interface NameSource { ConfigParseable nameToParseable(String name); } @@ -425,7 +399,7 @@ public class ConfigImpl { new SimpleConfigOrigin("env var " + key), entry.getValue())); } return new SimpleConfigObject(new SimpleConfigOrigin("env variables"), - m, ResolveStatus.RESOLVED); + m, ResolveStatus.RESOLVED, false /* ignoresFallbacks */); } /** For use ONLY by library internals, DO NOT TOUCH not guaranteed ABI */ diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigInt.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigInt.java index 192abbde03..4ce4a58545 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigInt.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigInt.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigOrigin; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigLong.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigLong.java index f949f10b87..feb3897bb3 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigLong.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigLong.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigOrigin; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigNull.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigNull.java index 84a7a41568..ea8976e340 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigNull.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigNull.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigOrigin; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigNumber.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigNumber.java index eec0ff5008..3c01d9b950 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigNumber.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigNumber.java @@ -1,5 +1,9 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; +import com.typesafe.config.ConfigException; import com.typesafe.config.ConfigOrigin; abstract class ConfigNumber extends AbstractConfigValue { @@ -14,11 +18,23 @@ abstract class ConfigNumber extends AbstractConfigValue { this.originalText = originalText; } + @Override + public abstract Number unwrapped(); + @Override String transformToString() { return originalText; } + int intValueRangeChecked(String path) { + long l = longValue(); + if (l < Integer.MIN_VALUE || l > Integer.MAX_VALUE) { + throw new ConfigException.WrongType(origin(), path, "32-bit integer", + "out-of-range value " + l); + } + return (int) l; + } + protected abstract long longValue(); protected abstract double doubleValue(); diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigString.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigString.java index 522d5bf5a7..e054b6c91f 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigString.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigString.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigOrigin; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigSubstitution.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigSubstitution.java index ae894e03a1..2c5531e74f 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigSubstitution.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigSubstitution.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.ArrayList; @@ -6,7 +9,6 @@ import java.util.Collections; import java.util.List; import com.typesafe.config.ConfigException; -import com.typesafe.config.ConfigMergeable; import com.typesafe.config.ConfigOrigin; import com.typesafe.config.ConfigResolveOptions; import com.typesafe.config.ConfigValue; @@ -25,17 +27,19 @@ final class ConfigSubstitution extends AbstractConfigValue implements // than one piece everything is stringified and concatenated final private List pieces; // the length of any prefixes added with relativized() - final int prefixLength; + final private int prefixLength; + final private boolean ignoresFallbacks; ConfigSubstitution(ConfigOrigin origin, List pieces) { - this(origin, pieces, 0); + this(origin, pieces, 0, false); } private ConfigSubstitution(ConfigOrigin origin, List pieces, - int prefixLength) { + int prefixLength, boolean ignoresFallbacks) { super(origin); this.pieces = pieces; this.prefixLength = prefixLength; + this.ignoresFallbacks = ignoresFallbacks; } @Override @@ -52,26 +56,41 @@ final class ConfigSubstitution extends AbstractConfigValue implements } @Override - public AbstractConfigValue withFallback(ConfigMergeable mergeable) { - ConfigValue other = mergeable.toValue(); + protected ConfigSubstitution newCopy(boolean ignoresFallbacks) { + return new ConfigSubstitution(origin(), pieces, prefixLength, ignoresFallbacks); + } - if (other instanceof AbstractConfigObject - || other instanceof Unmergeable) { - // if we turn out to be an object, and the fallback also does, - // then a merge may be required; delay until we resolve. - List newStack = new ArrayList(); - newStack.add(this); - if (other instanceof Unmergeable) - newStack.addAll(((Unmergeable) other).unmergedValues()); - else - newStack.add((AbstractConfigValue) other); - return new ConfigDelayedMerge( - AbstractConfigObject.mergeOrigins(newStack), newStack); - } else { - // if the other is not an object, there won't be anything - // to merge with, so we are it even if we are an object. - return this; - } + @Override + protected boolean ignoresFallbacks() { + return ignoresFallbacks; + } + + @Override + protected AbstractConfigValue mergedWithTheUnmergeable(Unmergeable fallback) { + if (ignoresFallbacks) + throw new ConfigException.BugOrBroken("should not be reached"); + + // if we turn out to be an object, and the fallback also does, + // then a merge may be required; delay until we resolve. + List newStack = new ArrayList(); + newStack.add(this); + newStack.addAll(fallback.unmergedValues()); + return new ConfigDelayedMerge(AbstractConfigObject.mergeOrigins(newStack), newStack, + ((AbstractConfigValue) fallback).ignoresFallbacks()); + } + + @Override + protected AbstractConfigValue mergedWithObject(AbstractConfigObject fallback) { + if (ignoresFallbacks) + throw new ConfigException.BugOrBroken("should not be reached"); + + // if we turn out to be an object, and the fallback also does, + // then a merge may be required; delay until we resolve. + List newStack = new ArrayList(); + newStack.add(this); + newStack.add(fallback); + return new ConfigDelayedMerge(AbstractConfigObject.mergeOrigins(newStack), newStack, + fallback.ignoresFallbacks()); } @Override @@ -198,7 +217,7 @@ final class ConfigSubstitution extends AbstractConfigValue implements } } return new ConfigSubstitution(origin(), newPieces, prefixLength - + prefix.length()); + + prefix.length(), ignoresFallbacks); } @Override diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigUtil.java b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigUtil.java index fff540e1bf..bfd8f05521 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ConfigUtil.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ConfigUtil.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/DefaultTransformer.java b/akka-actor/src/main/java/com/typesafe/config/impl/DefaultTransformer.java index 62913a1c3b..4391814acb 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/DefaultTransformer.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/DefaultTransformer.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigValueType; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/FromMapMode.java b/akka-actor/src/main/java/com/typesafe/config/impl/FromMapMode.java index 0a646b2e90..ce6c3e3f0a 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/FromMapMode.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/FromMapMode.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; enum FromMapMode { diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/Parseable.java b/akka-actor/src/main/java/com/typesafe/config/impl/Parseable.java index f97bb8f5f0..eef9e75b2a 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/Parseable.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/Parseable.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.io.BufferedReader; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/Parser.java b/akka-actor/src/main/java/com/typesafe/config/impl/Parser.java index b0c68b10ac..d168e8d57a 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/Parser.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/Parser.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.io.StringReader; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/Path.java b/akka-actor/src/main/java/com/typesafe/config/impl/Path.java index cf6d959f32..b0434f0f14 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/Path.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/Path.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.Iterator; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/PathBuilder.java b/akka-actor/src/main/java/com/typesafe/config/impl/PathBuilder.java index 3f3643e8ad..f46e78201e 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/PathBuilder.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/PathBuilder.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.Stack; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/PropertiesParser.java b/akka-actor/src/main/java/com/typesafe/config/impl/PropertiesParser.java index c73293d9c4..bd822e65e9 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/PropertiesParser.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/PropertiesParser.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.io.IOException; @@ -177,11 +180,12 @@ final class PropertiesParser { .get(parentPath) : root; AbstractConfigObject o = new SimpleConfigObject(origin, scope, - ResolveStatus.RESOLVED); + ResolveStatus.RESOLVED, false /* ignoresFallbacks */); parent.put(scopePath.last(), o); } // return root config object - return new SimpleConfigObject(origin, root, ResolveStatus.RESOLVED); + return new SimpleConfigObject(origin, root, ResolveStatus.RESOLVED, + false /* ignoresFallbacks */); } } diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/ResolveStatus.java b/akka-actor/src/main/java/com/typesafe/config/impl/ResolveStatus.java index 3b6a7535f6..3f73eb5221 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/ResolveStatus.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/ResolveStatus.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.Collection; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/RootConfig.java b/akka-actor/src/main/java/com/typesafe/config/impl/RootConfig.java index d8f042b961..723b9fad89 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/RootConfig.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/RootConfig.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigMergeable; @@ -32,20 +35,14 @@ final class RootConfig extends SimpleConfig implements ConfigRoot { // if the object is already resolved then we should end up returning // "this" here, since asRoot() should return this if the path // is unchanged. - SimpleConfig resolved = resolvedObject(options).toConfig(); - return resolved.asRoot(rootPath); + AbstractConfigObject resolved = resolvedObject(options); + return newRootIfObjectChanged(this, resolved); } @Override public RootConfig withFallback(ConfigMergeable value) { // this can return "this" if the withFallback does nothing - return super.withFallback(value).asRoot(rootPath); - } - - @Override - public RootConfig withFallbacks(ConfigMergeable... values) { - // this can return "this" if the withFallbacks does nothing - return super.withFallbacks(values).asRoot(rootPath); + return newRootIfObjectChanged(this, super.withFallback(value).toObject()); } Path rootPathObject() { diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfig.java b/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfig.java index 02d6351d63..d64ce4625a 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfig.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfig.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.ArrayList; @@ -56,6 +59,13 @@ class SimpleConfig implements Config { return new RootConfig(underlying, newRootPath); } + static protected RootConfig newRootIfObjectChanged(RootConfig self, AbstractConfigObject underlying) { + if (underlying == self.object) + return self; + else + return new RootConfig(underlying, self.rootPathObject()); + } + protected AbstractConfigObject resolvedObject(ConfigResolveOptions options) { AbstractConfigValue resolved = SubstitutionResolver.resolve(object, object, options); @@ -129,15 +139,20 @@ class SimpleConfig implements Config { return (Boolean) v.unwrapped(); } + private ConfigNumber getConfigNumber(String path) { + ConfigValue v = find(path, ConfigValueType.NUMBER, path); + return (ConfigNumber) v; + } + @Override public Number getNumber(String path) { - ConfigValue v = find(path, ConfigValueType.NUMBER, path); - return (Number) v.unwrapped(); + return getConfigNumber(path).unwrapped(); } @Override public int getInt(String path) { - return getNumber(path).intValue(); + ConfigNumber n = getConfigNumber(path); + return n.intValueRangeChecked(path); } @Override @@ -245,9 +260,9 @@ class SimpleConfig implements Config { @Override public List getIntList(String path) { List l = new ArrayList(); - List numbers = getNumberList(path); - for (Number n : numbers) { - l.add(n.intValue()); + List numbers = getHomogeneousWrappedList(path, ConfigValueType.NUMBER); + for (AbstractConfigValue v : numbers) { + l.add(((ConfigNumber) v).intValueRangeChecked(path)); } return l; } @@ -385,13 +400,6 @@ class SimpleConfig implements Config { return object.withFallback(other).toConfig(); } - @Override - public SimpleConfig withFallbacks(ConfigMergeable... others) { - // this can return "this" if the withFallbacks doesn't need a new - // ConfigObject - return object.withFallbacks(others).toConfig(); - } - @Override public final boolean equals(Object other) { if (other instanceof SimpleConfig) { diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigList.java b/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigList.java index aa341eb500..9e610858c9 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigList.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigList.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.ArrayList; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java b/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java index b1b5140943..88b2b9090f 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigObject.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.AbstractMap; @@ -17,21 +20,23 @@ final class SimpleConfigObject extends AbstractConfigObject { // this map should never be modified - assume immutable final private Map value; final private boolean resolved; + final private boolean ignoresFallbacks; SimpleConfigObject(ConfigOrigin origin, - Map value, ResolveStatus status) { + Map value, ResolveStatus status, + boolean ignoresFallbacks) { super(origin); if (value == null) throw new ConfigException.BugOrBroken( "creating config object with null map"); this.value = value; this.resolved = status == ResolveStatus.RESOLVED; + this.ignoresFallbacks = ignoresFallbacks; } SimpleConfigObject(ConfigOrigin origin, Map value) { - this(origin, value, ResolveStatus.fromValues(value - .values())); + this(origin, value, ResolveStatus.fromValues(value.values()), false /* ignoresFallbacks */); } @Override @@ -40,9 +45,8 @@ final class SimpleConfigObject extends AbstractConfigObject { } @Override - public SimpleConfigObject newCopy(ResolveStatus newStatus) { - return new SimpleConfigObject(origin(), value, - newStatus); + protected SimpleConfigObject newCopy(ResolveStatus newStatus, boolean newIgnoresFallbacks) { + return new SimpleConfigObject(origin(), value, newStatus, newIgnoresFallbacks); } @Override @@ -50,6 +54,11 @@ final class SimpleConfigObject extends AbstractConfigObject { return ResolveStatus.fromBoolean(resolved); } + @Override + protected boolean ignoresFallbacks() { + return ignoresFallbacks; + } + @Override public Map unwrapped() { Map m = new HashMap(); diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java b/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java index ed23e69863..6e37756638 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/SimpleConfigOrigin.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import com.typesafe.config.ConfigOrigin; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/SubstitutionResolver.java b/akka-actor/src/main/java/com/typesafe/config/impl/SubstitutionResolver.java index 1ec58ce6ea..7f77570d02 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/SubstitutionResolver.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/SubstitutionResolver.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.IdentityHashMap; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/Token.java b/akka-actor/src/main/java/com/typesafe/config/impl/Token.java index 1c863c870a..7c888c748e 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/Token.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/Token.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; class Token { diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/TokenType.java b/akka-actor/src/main/java/com/typesafe/config/impl/TokenType.java index 72700dbaa4..19b6a106a9 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/TokenType.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/TokenType.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; enum TokenType { diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/Tokenizer.java b/akka-actor/src/main/java/com/typesafe/config/impl/Tokenizer.java index 1298f3c1bd..147917bf40 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/Tokenizer.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/Tokenizer.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.io.IOException; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/Tokens.java b/akka-actor/src/main/java/com/typesafe/config/impl/Tokens.java index 8d66bcb575..9ec73a819c 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/Tokens.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/Tokens.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.List; diff --git a/akka-actor/src/main/java/com/typesafe/config/impl/Unmergeable.java b/akka-actor/src/main/java/com/typesafe/config/impl/Unmergeable.java index 82dc203eef..e0d114e78d 100644 --- a/akka-actor/src/main/java/com/typesafe/config/impl/Unmergeable.java +++ b/akka-actor/src/main/java/com/typesafe/config/impl/Unmergeable.java @@ -1,3 +1,6 @@ +/** + * Copyright (C) 2011 Typesafe Inc. + */ package com.typesafe.config.impl; import java.util.Collection;