blob: 52da9d01d803a826601f0cbe3bb50fef7b6de454 [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.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.common.context.FrameworkExt;
import org.apache.dubbo.common.context.LifecycleAdapter;
import org.apache.dubbo.common.extension.DisableInject;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.context.ConfigConfigurationAdapter;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class Environment extends LifecycleAdapter implements FrameworkExt {
public static final String NAME = "environment";
private final PropertiesConfiguration propertiesConfiguration;
private final SystemConfiguration systemConfiguration;
private final EnvironmentConfiguration environmentConfiguration;
private final InmemoryConfiguration externalConfiguration;
private final InmemoryConfiguration appExternalConfiguration;
private final ConcurrentMap<AbstractConfig, CompositeConfiguration> prefixedConfigurations = new ConcurrentHashMap<>();
private CompositeConfiguration globalConfiguration;
private Map<String, String> externalConfigurationMap = new HashMap<>();
private Map<String, String> appExternalConfigurationMap = new HashMap<>();
private boolean configCenterFirst = true;
private DynamicConfiguration dynamicConfiguration;
public Environment() {
this.propertiesConfiguration = new PropertiesConfiguration();
this.systemConfiguration = new SystemConfiguration();
this.environmentConfiguration = new EnvironmentConfiguration();
this.externalConfiguration = new InmemoryConfiguration();
this.appExternalConfiguration = new InmemoryConfiguration();
}
@Override
public void initialize() throws IllegalStateException {
ConfigManager configManager = ApplicationModel.getConfigManager();
Optional<Collection<ConfigCenterConfig>> defaultConfigs = configManager.getDefaultConfigCenter();
defaultConfigs.ifPresent(configs -> {
for (ConfigCenterConfig config : configs) {
this.setExternalConfigMap(config.getExternalConfiguration());
this.setAppExternalConfigMap(config.getAppExternalConfiguration());
}
});
this.externalConfiguration.setProperties(externalConfigurationMap);
this.appExternalConfiguration.setProperties(appExternalConfigurationMap);
}
@DisableInject
public void setExternalConfigMap(Map<String, String> externalConfiguration) {
if (externalConfiguration != null) {
this.externalConfigurationMap = externalConfiguration;
}
}
@DisableInject
public void setAppExternalConfigMap(Map<String, String> appExternalConfiguration) {
if (appExternalConfiguration != null) {
this.appExternalConfigurationMap = appExternalConfiguration;
}
}
public Map<String, String> getExternalConfigurationMap() {
return externalConfigurationMap;
}
public Map<String, String> getAppExternalConfigurationMap() {
return appExternalConfigurationMap;
}
public void updateExternalConfigurationMap(Map<String, String> externalMap) {
this.externalConfigurationMap.putAll(externalMap);
}
public void updateAppExternalConfigurationMap(Map<String, String> externalMap) {
this.appExternalConfigurationMap.putAll(externalMap);
}
/**
* At start-up, Dubbo is driven by various configuration, such as Application, Registry, Protocol, etc.
* All configurations will be converged into a data bus - URL, and then drive the subsequent process.
* <p>
* At present, there are many configuration sources, including AbstractConfig (API, XML, annotation), - D, config center, etc.
* This method helps us to filter out the most priority values from various configuration sources.
*
* @param config
* @return
*/
public synchronized CompositeConfiguration getPrefixedConfiguration(AbstractConfig config) {
// CompositeConfiguration prefixedConfiguration =
// prefixedConfigurations.putIfAbsent(config, new CompositeConfiguration(config.getPrefix(), config.getId()));
// if (prefixedConfiguration != null) {
// return prefixedConfiguration;
// }
// prefixedConfiguration = prefixedConfigurations.get(config);
CompositeConfiguration prefixedConfiguration = new CompositeConfiguration(config.getPrefix(), config.getId());
Configuration configuration = new ConfigConfigurationAdapter(config);
if (this.isConfigCenterFirst()) {
// The sequence would be: SystemConfiguration -> AppExternalConfiguration -> ExternalConfiguration -> AbstractConfig -> PropertiesConfiguration
// Config center has the highest priority
prefixedConfiguration.addConfiguration(systemConfiguration);
prefixedConfiguration.addConfiguration(environmentConfiguration);
prefixedConfiguration.addConfiguration(appExternalConfiguration);
prefixedConfiguration.addConfiguration(externalConfiguration);
prefixedConfiguration.addConfiguration(configuration);
prefixedConfiguration.addConfiguration(propertiesConfiguration);
} else {
// The sequence would be: SystemConfiguration -> AbstractConfig -> AppExternalConfiguration -> ExternalConfiguration -> PropertiesConfiguration
// Config center has the highest priority
prefixedConfiguration.addConfiguration(systemConfiguration);
prefixedConfiguration.addConfiguration(environmentConfiguration);
prefixedConfiguration.addConfiguration(configuration);
prefixedConfiguration.addConfiguration(appExternalConfiguration);
prefixedConfiguration.addConfiguration(externalConfiguration);
prefixedConfiguration.addConfiguration(propertiesConfiguration);
}
return prefixedConfiguration;
}
/**
* There are two ways to get configuration during exposure / reference or at runtime:
* 1. URL, The value in the URL is relatively fixed. we can get value directly.
* 2. The configuration exposed in this method is convenient for us to query the latest values from multiple
* prioritized sources, it also guarantees that configs changed dynamically can take effect on the fly.
*/
public Configuration getConfiguration() {
if (globalConfiguration == null) {
globalConfiguration = new CompositeConfiguration();
if (dynamicConfiguration != null) {
globalConfiguration.addConfiguration(dynamicConfiguration);
}
globalConfiguration.addConfiguration(systemConfiguration);
globalConfiguration.addConfiguration(environmentConfiguration);
globalConfiguration.addConfiguration(appExternalConfiguration);
globalConfiguration.addConfiguration(externalConfiguration);
globalConfiguration.addConfiguration(propertiesConfiguration);
}
return globalConfiguration;
}
public boolean isConfigCenterFirst() {
return configCenterFirst;
}
@DisableInject
public void setConfigCenterFirst(boolean configCenterFirst) {
this.configCenterFirst = configCenterFirst;
}
public Optional<DynamicConfiguration> getDynamicConfiguration() {
return Optional.ofNullable(dynamicConfiguration);
}
@DisableInject
public void setDynamicConfiguration(DynamicConfiguration dynamicConfiguration) {
this.dynamicConfiguration = dynamicConfiguration;
}
@Override
public void destroy() throws IllegalStateException {
clearExternalConfigs();
clearAppExternalConfigs();
}
public PropertiesConfiguration getPropertiesConfiguration() {
return propertiesConfiguration;
}
public SystemConfiguration getSystemConfiguration() {
return systemConfiguration;
}
public EnvironmentConfiguration getEnvironmentConfiguration() {
return environmentConfiguration;
}
public InmemoryConfiguration getExternalConfiguration() {
return externalConfiguration;
}
public InmemoryConfiguration getAppExternalConfiguration() {
return appExternalConfiguration;
}
// For test
public void clearExternalConfigs() {
this.externalConfiguration.clear();
this.externalConfigurationMap.clear();
}
// For test
public void clearAppExternalConfigs() {
this.appExternalConfiguration.clear();
this.appExternalConfigurationMap.clear();
}
}