| /* |
| * 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(); |
| } |
| } |