blob: 5c3988ab024163dbe66d0c95a42d99765097fced [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.dubbo.common.config;
import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.common.logger.LoggerFactory;
import java.util.NoSuchElementException;
import static org.apache.dubbo.common.config.ConfigurationUtils.isEmptyValue;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_PROPERTY_MISSPELLING;
/**
* Configuration interface, to fetch the value for the specified key.
*/
public interface Configuration {
ErrorTypeAwareLogger interfaceLevelLogger = LoggerFactory.getErrorTypeAwareLogger(Configuration.class);
/**
* Get a string associated with the given configuration key.
*
* @param key The configuration key.
* @return The associated string.
*/
default String getString(String key) {
return convert(String.class, key, null);
}
/**
* Get a string associated with the given configuration key.
* If the key doesn't map to an existing object, the default value
* is returned.
*
* @param key The configuration key.
* @param defaultValue The default value.
* @return The associated string if key is found and has valid
* format, default value otherwise.
*/
default String getString(String key, String defaultValue) {
return convert(String.class, key, defaultValue);
}
default int getInt(String key) {
Integer i = this.getInteger(key, null);
if (i != null) {
return i;
} else {
throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
}
}
default int getInt(String key, int defaultValue) {
Integer i = this.getInteger(key, null);
return i == null ? defaultValue : i;
}
default Integer getInteger(String key, Integer defaultValue) {
try {
return convert(Integer.class, key, defaultValue);
} catch (NumberFormatException e) {
// 0-2 Property type mismatch.
interfaceLevelLogger.error(COMMON_PROPERTY_MISSPELLING, "typo in property value",
"This property requires an integer value.",
"Actual Class: " + getClass().getName(), e);
throw new IllegalStateException('\'' + key + "' doesn't map to a Integer object", e);
}
}
default boolean getBoolean(String key) {
Boolean b = this.getBoolean(key, null);
if (b != null) {
return b;
} else {
throw new NoSuchElementException('\'' + key + "' doesn't map to an existing object");
}
}
default boolean getBoolean(String key, boolean defaultValue) {
return this.getBoolean(key, toBooleanObject(defaultValue));
}
default Boolean getBoolean(String key, Boolean defaultValue) {
try {
return convert(Boolean.class, key, defaultValue);
} catch (Exception e) {
throw new IllegalStateException("Try to get " + '\'' + key + "' failed, maybe because this key doesn't map to a Boolean object", e);
}
}
/**
* Gets a property from the configuration. This is the most basic get
* method for retrieving values of properties. In a typical implementation
* of the {@code Configuration} interface the other get methods (that
* return specific data types) will internally make use of this method. On
* this level variable substitution is not yet performed. The returned
* object is an internal representation of the property value for the passed
* in key. It is owned by the {@code Configuration} object. So a caller
* should not modify this object. It cannot be guaranteed that this object
* will stay constant over time (i.e. further update operations on the
* configuration may change its internal state).
*
* @param key property to retrieve
* @return the value to which this configuration maps the specified key, or
* null if the configuration contains no mapping for this key.
*/
default Object getProperty(String key) {
return getProperty(key, null);
}
/**
* Gets a property from the configuration. The default value will return if the configuration doesn't contain
* the mapping for the specified key.
*
* @param key property to retrieve
* @param defaultValue default value
* @return the value to which this configuration maps the specified key, or default value if the configuration
* contains no mapping for this key.
*/
default Object getProperty(String key, Object defaultValue) {
Object value = getInternalProperty(key);
return value != null ? value : defaultValue;
}
Object getInternalProperty(String key);
/**
* Check if the configuration contains the specified key.
*
* @param key the key whose presence in this configuration is to be tested
* @return {@code true} if the configuration contains a value for this
* key, {@code false} otherwise
*/
default boolean containsKey(String key) {
return !isEmptyValue(getProperty(key));
}
default <T> T convert(Class<T> cls, String key, T defaultValue) {
// we only process String properties for now
String value = (String) getProperty(key);
if (value == null) {
return defaultValue;
}
Object obj = value;
if (cls.isInstance(value)) {
return cls.cast(value);
}
if (Boolean.class.equals(cls) || Boolean.TYPE.equals(cls)) {
obj = Boolean.valueOf(value);
} else if (Number.class.isAssignableFrom(cls) || cls.isPrimitive()) {
if (Integer.class.equals(cls) || Integer.TYPE.equals(cls)) {
obj = Integer.valueOf(value);
} else if (Long.class.equals(cls) || Long.TYPE.equals(cls)) {
obj = Long.valueOf(value);
} else if (Byte.class.equals(cls) || Byte.TYPE.equals(cls)) {
obj = Byte.valueOf(value);
} else if (Short.class.equals(cls) || Short.TYPE.equals(cls)) {
obj = Short.valueOf(value);
} else if (Float.class.equals(cls) || Float.TYPE.equals(cls)) {
obj = Float.valueOf(value);
} else if (Double.class.equals(cls) || Double.TYPE.equals(cls)) {
obj = Double.valueOf(value);
}
} else if (cls.isEnum()) {
obj = Enum.valueOf(cls.asSubclass(Enum.class), value);
}
return cls.cast(obj);
}
static Boolean toBooleanObject(boolean bool) {
return bool ? Boolean.TRUE : Boolean.FALSE;
}
}