mirror of
https://github.com/lightbend/config.git
synced 2025-03-18 21:30:30 +08:00
Change ConfigBeanFactory to use ConfigMemorySize and java.time.Duration
This commit is contained in:
parent
f1f198595a
commit
69f7b48130
@ -1,8 +1,5 @@
|
||||
package com.typesafe.config;
|
||||
|
||||
import com.typesafe.config.impl.DurationUnit;
|
||||
import com.typesafe.config.impl.MemoryUnit;
|
||||
|
||||
import java.beans.BeanInfo;
|
||||
import java.beans.IntrospectionException;
|
||||
import java.beans.Introspector;
|
||||
@ -12,6 +9,7 @@ import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.time.Duration;
|
||||
|
||||
/**
|
||||
* Factory for automatic creation of config classes populated with values from config.
|
||||
@ -97,15 +95,13 @@ public class ConfigBeanFactory {
|
||||
} else if (parameterClass == Double.class || parameterClass == double.class) {
|
||||
return config.getDouble(configPropName);
|
||||
} else if (parameterClass == Long.class || parameterClass == long.class) {
|
||||
String rawVal = config.getString(configPropName);
|
||||
if (DurationUnit.containsDurationToken(rawVal)) {
|
||||
return config.getDuration(configPropName, TimeUnit.NANOSECONDS);
|
||||
} else if (MemoryUnit.containsMemoryToken(rawVal)) {
|
||||
return config.getBytes(configPropName);
|
||||
}
|
||||
return config.getLong(configPropName);
|
||||
} else if (parameterClass == String.class) {
|
||||
return config.getString(configPropName);
|
||||
} else if (parameterClass == Duration.class) {
|
||||
return config.getDuration(configPropName);
|
||||
} else if (parameterClass == ConfigMemorySize.class) {
|
||||
return config.getMemorySize(configPropName);
|
||||
}
|
||||
|
||||
return config.getAnyRef(configPropName);
|
||||
|
@ -1,58 +0,0 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* https://github.com/typesafehub/config/blob/master/HOCON.md#duration-format
|
||||
*/
|
||||
public enum DurationUnit {
|
||||
|
||||
|
||||
NANOSECONDS(TimeUnit.NANOSECONDS, Arrays.asList("ns", "nano", "nanos", "nanosecond", "nanoseconds")),
|
||||
MICROSECONDS(TimeUnit.MICROSECONDS, Arrays.asList("us", "micro", "micros", "microsecond", "microseconds")),
|
||||
MILLISECONDS(TimeUnit.MILLISECONDS,Arrays.asList("ms", "milli", "millis", "millisecond", "milliseconds")),
|
||||
SECONDS(TimeUnit.SECONDS,Arrays.asList("s", "second", "seconds")),
|
||||
MINUTES(TimeUnit.MINUTES,Arrays.asList("m", "minute", "minutes")),
|
||||
HOURS(TimeUnit.HOURS,Arrays.asList("h", "hour", "hours")),
|
||||
DAYS(TimeUnit.DAYS,Arrays.asList("d", "day", "days"));
|
||||
|
||||
private List<String> aliases;
|
||||
private TimeUnit timeUnit;
|
||||
|
||||
DurationUnit(TimeUnit timeUnit,List<String> aliases) {
|
||||
this.timeUnit = timeUnit;
|
||||
this.aliases = aliases;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds corresponding duration unit by its string representation.
|
||||
* @param rawVal - string duration value ('s','ns' etc.)
|
||||
* @return one of enum values or null if none applicable
|
||||
*/
|
||||
public static final DurationUnit fromString(String rawVal) {
|
||||
for (DurationUnit durationUnit : DurationUnit.values()) {
|
||||
// note that this is deliberately case-sensitive
|
||||
if(durationUnit.aliases.contains(rawVal)) {
|
||||
return durationUnit;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given string contains duration token.
|
||||
* @param rawVal - string like '10s','45nanos' etc.
|
||||
* String is case sensitive, i.e. '10S' is not treated as valid duration string
|
||||
* @return true - if string contains one of enum aliases, false otherwise
|
||||
*/
|
||||
public static boolean containsDurationToken(String rawVal) {
|
||||
String unitStr = rawVal.replaceAll("[^A-Za-z]","");
|
||||
return fromString(unitStr) != null;
|
||||
}
|
||||
|
||||
public TimeUnit getTimeUnit() {
|
||||
return timeUnit;
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
package com.typesafe.config.impl;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* https://github.com/typesafehub/config/blob/master/HOCON.md#size-in-bytes-format
|
||||
*/
|
||||
public enum MemoryUnit {
|
||||
BYTES("", 1024, 0),
|
||||
|
||||
KILOBYTES("kilo", 1000, 1),
|
||||
MEGABYTES("mega", 1000, 2),
|
||||
GIGABYTES("giga", 1000, 3),
|
||||
TERABYTES("tera", 1000, 4),
|
||||
PETABYTES("peta", 1000, 5),
|
||||
EXABYTES("exa", 1000, 6),
|
||||
ZETTABYTES("zetta", 1000, 7),
|
||||
YOTTABYTES("yotta", 1000, 8),
|
||||
|
||||
KIBIBYTES("kibi", 1024, 1),
|
||||
MEBIBYTES("mebi", 1024, 2),
|
||||
GIBIBYTES("gibi", 1024, 3),
|
||||
TEBIBYTES("tebi", 1024, 4),
|
||||
PEBIBYTES("pebi", 1024, 5),
|
||||
EXBIBYTES("exbi", 1024, 6),
|
||||
ZEBIBYTES("zebi", 1024, 7),
|
||||
YOBIBYTES("yobi", 1024, 8);
|
||||
|
||||
final String prefix;
|
||||
final int powerOf;
|
||||
final int power;
|
||||
final BigInteger bytes;
|
||||
|
||||
MemoryUnit(String prefix, int powerOf, int power) {
|
||||
this.prefix = prefix;
|
||||
this.powerOf = powerOf;
|
||||
this.power = power;
|
||||
this.bytes = BigInteger.valueOf(powerOf).pow(power);
|
||||
}
|
||||
|
||||
private static Map<String, MemoryUnit> makeUnitsMap() {
|
||||
Map<String, MemoryUnit> map = new HashMap<String, MemoryUnit>();
|
||||
for (MemoryUnit unit : MemoryUnit.values()) {
|
||||
map.put(unit.prefix + "byte", unit);
|
||||
map.put(unit.prefix + "bytes", unit);
|
||||
if (unit.prefix.length() == 0) {
|
||||
map.put("b", unit);
|
||||
map.put("B", unit);
|
||||
map.put("", unit); // no unit specified means bytes
|
||||
} else {
|
||||
String first = unit.prefix.substring(0, 1);
|
||||
String firstUpper = first.toUpperCase();
|
||||
if (unit.powerOf == 1024) {
|
||||
map.put(first, unit); // 512m
|
||||
map.put(firstUpper, unit); // 512M
|
||||
map.put(firstUpper + "i", unit); // 512Mi
|
||||
map.put(firstUpper + "iB", unit); // 512MiB
|
||||
} else if (unit.powerOf == 1000) {
|
||||
if (unit.power == 1) {
|
||||
map.put(first + "B", unit); // 512kB
|
||||
} else {
|
||||
map.put(firstUpper + "B", unit); // 512MB
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("broken MemoryUnit enum");
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Map<String, MemoryUnit> unitsMap = makeUnitsMap();
|
||||
|
||||
static MemoryUnit parseUnit(String unit) {
|
||||
return unitsMap.get(unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether given string contains memory token.
|
||||
* @param rawVal - string like '10B','45bytes' etc.
|
||||
* String is case sensitive, i.e. '10KILOS' is not treated as valid memory size string
|
||||
* @return true - if string contains memory data, false otherwise
|
||||
*/
|
||||
public static boolean containsMemoryToken(String rawVal) {
|
||||
String unitStr = rawVal.replaceAll("[^A-Za-z]","");
|
||||
for (String unit : unitsMap.keySet()) {
|
||||
if(unit.equals(unitStr)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
@ -547,17 +547,27 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
if (unitString.length() > 2 && !unitString.endsWith("s"))
|
||||
unitString = unitString + "s";
|
||||
|
||||
if(unitString.equals("")) {
|
||||
// note that this is deliberately case-sensitive
|
||||
if (unitString.equals("") || unitString.equals("ms") || unitString.equals("millis")
|
||||
|| unitString.equals("milliseconds")) {
|
||||
units = TimeUnit.MILLISECONDS;
|
||||
} else if (unitString.equals("us") || unitString.equals("micros") || unitString.equals("microseconds")) {
|
||||
units = TimeUnit.MICROSECONDS;
|
||||
} else if (unitString.equals("ns") || unitString.equals("nanos") || unitString.equals("nanoseconds")) {
|
||||
units = TimeUnit.NANOSECONDS;
|
||||
} else if (unitString.equals("d") || unitString.equals("days")) {
|
||||
units = TimeUnit.DAYS;
|
||||
} else if (unitString.equals("h") || unitString.equals("hours")) {
|
||||
units = TimeUnit.HOURS;
|
||||
} else if (unitString.equals("s") || unitString.equals("seconds")) {
|
||||
units = TimeUnit.SECONDS;
|
||||
} else if (unitString.equals("m") || unitString.equals("minutes")) {
|
||||
units = TimeUnit.MINUTES;
|
||||
} else {
|
||||
DurationUnit durationUnit = DurationUnit.fromString(unitString);
|
||||
units = durationUnit != null ? durationUnit.getTimeUnit() : null;
|
||||
if(units == null) {
|
||||
throw new ConfigException.BadValue(originForException,
|
||||
throw new ConfigException.BadValue(originForException,
|
||||
pathForException, "Could not parse time unit '"
|
||||
+ originalUnitString
|
||||
+ "' (try ns, us, ms, s, m, h, d)");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
@ -577,6 +587,77 @@ final class SimpleConfig implements Config, MergeableValue, Serializable {
|
||||
}
|
||||
}
|
||||
|
||||
private static enum MemoryUnit {
|
||||
BYTES("", 1024, 0),
|
||||
|
||||
KILOBYTES("kilo", 1000, 1),
|
||||
MEGABYTES("mega", 1000, 2),
|
||||
GIGABYTES("giga", 1000, 3),
|
||||
TERABYTES("tera", 1000, 4),
|
||||
PETABYTES("peta", 1000, 5),
|
||||
EXABYTES("exa", 1000, 6),
|
||||
ZETTABYTES("zetta", 1000, 7),
|
||||
YOTTABYTES("yotta", 1000, 8),
|
||||
|
||||
KIBIBYTES("kibi", 1024, 1),
|
||||
MEBIBYTES("mebi", 1024, 2),
|
||||
GIBIBYTES("gibi", 1024, 3),
|
||||
TEBIBYTES("tebi", 1024, 4),
|
||||
PEBIBYTES("pebi", 1024, 5),
|
||||
EXBIBYTES("exbi", 1024, 6),
|
||||
ZEBIBYTES("zebi", 1024, 7),
|
||||
YOBIBYTES("yobi", 1024, 8);
|
||||
|
||||
final String prefix;
|
||||
final int powerOf;
|
||||
final int power;
|
||||
final BigInteger bytes;
|
||||
|
||||
MemoryUnit(String prefix, int powerOf, int power) {
|
||||
this.prefix = prefix;
|
||||
this.powerOf = powerOf;
|
||||
this.power = power;
|
||||
this.bytes = BigInteger.valueOf(powerOf).pow(power);
|
||||
}
|
||||
|
||||
private static Map<String, MemoryUnit> makeUnitsMap() {
|
||||
Map<String, MemoryUnit> map = new HashMap<String, MemoryUnit>();
|
||||
for (MemoryUnit unit : MemoryUnit.values()) {
|
||||
map.put(unit.prefix + "byte", unit);
|
||||
map.put(unit.prefix + "bytes", unit);
|
||||
if (unit.prefix.length() == 0) {
|
||||
map.put("b", unit);
|
||||
map.put("B", unit);
|
||||
map.put("", unit); // no unit specified means bytes
|
||||
} else {
|
||||
String first = unit.prefix.substring(0, 1);
|
||||
String firstUpper = first.toUpperCase();
|
||||
if (unit.powerOf == 1024) {
|
||||
map.put(first, unit); // 512m
|
||||
map.put(firstUpper, unit); // 512M
|
||||
map.put(firstUpper + "i", unit); // 512Mi
|
||||
map.put(firstUpper + "iB", unit); // 512MiB
|
||||
} else if (unit.powerOf == 1000) {
|
||||
if (unit.power == 1) {
|
||||
map.put(first + "B", unit); // 512kB
|
||||
} else {
|
||||
map.put(firstUpper + "B", unit); // 512MB
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException("broken MemoryUnit enum");
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
private static Map<String, MemoryUnit> unitsMap = makeUnitsMap();
|
||||
|
||||
static MemoryUnit parseUnit(String unit) {
|
||||
return unitsMap.get(unit);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a size-in-bytes string. If no units are specified in the string,
|
||||
* it is assumed to be in bytes. The returned value is in bytes. The purpose
|
||||
|
@ -1,32 +1,34 @@
|
||||
package beanconfig;
|
||||
|
||||
import com.typesafe.config.ConfigMemorySize;
|
||||
|
||||
public class BytesConfig {
|
||||
|
||||
private Long kilobyte;
|
||||
private Long kibibyte;
|
||||
private Long thousandBytes;
|
||||
private ConfigMemorySize kilobyte;
|
||||
private ConfigMemorySize kibibyte;
|
||||
private ConfigMemorySize thousandBytes;
|
||||
|
||||
public Long getKilobyte() {
|
||||
public ConfigMemorySize getKilobyte() {
|
||||
return kilobyte;
|
||||
}
|
||||
|
||||
public void setKilobyte(Long kilobyte) {
|
||||
public void setKilobyte(ConfigMemorySize kilobyte) {
|
||||
this.kilobyte = kilobyte;
|
||||
}
|
||||
|
||||
public Long getKibibyte() {
|
||||
public ConfigMemorySize getKibibyte() {
|
||||
return kibibyte;
|
||||
}
|
||||
|
||||
public void setKibibyte(Long kibibyte) {
|
||||
public void setKibibyte(ConfigMemorySize kibibyte) {
|
||||
this.kibibyte = kibibyte;
|
||||
}
|
||||
|
||||
public Long getThousandBytes() {
|
||||
public ConfigMemorySize getThousandBytes() {
|
||||
return thousandBytes;
|
||||
}
|
||||
|
||||
public void setThousandBytes(Long thousandBytes) {
|
||||
public void setThousandBytes(ConfigMemorySize thousandBytes) {
|
||||
this.thousandBytes = thousandBytes;
|
||||
}
|
||||
}
|
||||
|
@ -1,33 +1,34 @@
|
||||
package beanconfig;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
public class DurationsConfig {
|
||||
Long second;
|
||||
Long secondAsNumber;
|
||||
Long halfSecond;
|
||||
Duration second;
|
||||
Duration secondAsNumber;
|
||||
Duration halfSecond;
|
||||
|
||||
|
||||
public Long getSecond() {
|
||||
public Duration getSecond() {
|
||||
return second;
|
||||
}
|
||||
|
||||
public void setSecond(Long second) {
|
||||
public void setSecond(Duration second) {
|
||||
this.second = second;
|
||||
}
|
||||
|
||||
public Long getSecondAsNumber() {
|
||||
public Duration getSecondAsNumber() {
|
||||
return secondAsNumber;
|
||||
}
|
||||
|
||||
public void setSecondAsNumber(Long secondAsNumber) {
|
||||
public void setSecondAsNumber(Duration secondAsNumber) {
|
||||
this.secondAsNumber = secondAsNumber;
|
||||
}
|
||||
|
||||
public Long getHalfSecond() {
|
||||
public Duration getHalfSecond() {
|
||||
return halfSecond;
|
||||
}
|
||||
|
||||
public void setHalfSecond(Long halfSecond) {
|
||||
public void setHalfSecond(Duration halfSecond) {
|
||||
this.halfSecond = halfSecond;
|
||||
}
|
||||
}
|
||||
|
@ -55,7 +55,7 @@
|
||||
},
|
||||
"durations" : {
|
||||
"second" : 1s,
|
||||
"secondAsNumber" : 1000000000,
|
||||
"secondAsNumber" : 1000,
|
||||
"halfSecond" : 0.5s
|
||||
},
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
package com.typesafe.config
|
||||
|
||||
import java.io.{ InputStream, InputStreamReader }
|
||||
import java.util.concurrent.TimeUnit
|
||||
import java.time.Duration;
|
||||
|
||||
import beanconfig._
|
||||
import org.junit.Assert._
|
||||
@ -70,18 +70,18 @@ class ConfigBeanFactoryTest {
|
||||
def testCreateDuration() {
|
||||
val beanConfig: DurationsConfig = ConfigBeanFactory.create(loadConfig().getConfig("durations"), classOf[DurationsConfig])
|
||||
assertNotNull(beanConfig)
|
||||
assertEquals(beanConfig.getHalfSecond, TimeUnit.MILLISECONDS.toNanos(500))
|
||||
assertEquals(beanConfig.getSecond, TimeUnit.SECONDS.toNanos(1))
|
||||
assertEquals(beanConfig.getSecondAsNumber, TimeUnit.SECONDS.toNanos(1))
|
||||
assertEquals(beanConfig.getHalfSecond, Duration.ofMillis(500))
|
||||
assertEquals(beanConfig.getSecond, Duration.ofMillis(1000))
|
||||
assertEquals(beanConfig.getSecondAsNumber, Duration.ofMillis(1000))
|
||||
}
|
||||
|
||||
@Test
|
||||
def testCreateBytes() {
|
||||
val beanConfig: BytesConfig = ConfigBeanFactory.create(loadConfig().getConfig("bytes"), classOf[BytesConfig])
|
||||
assertNotNull(beanConfig)
|
||||
assertEquals(beanConfig.getKibibyte, 1024L)
|
||||
assertEquals(beanConfig.getKilobyte, 1000L)
|
||||
assertEquals(beanConfig.getThousandBytes, 1000L)
|
||||
assertEquals(beanConfig.getKibibyte, ConfigMemorySize.ofBytes(1024))
|
||||
assertEquals(beanConfig.getKilobyte, ConfigMemorySize.ofBytes(1000))
|
||||
assertEquals(beanConfig.getThousandBytes, ConfigMemorySize.ofBytes(1000))
|
||||
}
|
||||
|
||||
private def loadConfig(): Config = {
|
||||
|
Loading…
Reference in New Issue
Block a user