You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by vi...@apache.org on 2019/07/26 02:14:23 UTC
[dubbo] branch cloud-native updated: Dubbo cloud native (#4666)
This is an automated email from the ASF dual-hosted git repository.
victory pushed a commit to branch cloud-native
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/cloud-native by this push:
new 2691784 Dubbo cloud native (#4666)
2691784 is described below
commit 2691784703031158e712a751662e4bc48c94de71
Author: Mercy Ma <me...@gmail.com>
AuthorDate: Fri Jul 26 10:14:12 2019 +0800
Dubbo cloud native (#4666)
---
dubbo-bootstrap/pom.xml | 6 +
.../dubbo/bootstrap/ApplicationSettings.java | 127 -----
.../org/apache/dubbo/bootstrap/DubboBootstrap.java | 394 +++++++------
.../apache/dubbo/bootstrap/ProtocolSettings.java | 215 -------
.../apache/dubbo/bootstrap/ReferenceSettings.java | 334 -----------
.../apache/dubbo/bootstrap/RegistrySettings.java | 164 ------
.../apache/dubbo/bootstrap/ServiceSettings.java | 384 -------------
.../apache/dubbo/bootstrap/DubboBootstrapTest.java | 14 -
.../bootstrap/DubboServiceConsumerBootstrap.java | 35 +-
.../bootstrap/DubboServiceProviderBootstrap.java | 24 +-
dubbo-common/pom.xml | 4 +
.../config/configcenter/ConfigChangeEvent.java | 6 +-
.../config/configcenter/ConfigurationListener.java | 4 +-
.../config/configcenter/DynamicConfiguration.java | 105 +++-
.../configcenter/DynamicConfigurationFactory.java | 20 +-
.../file/FileSystemDynamicConfiguration.java | 628 +++++++++++++++++++++
.../FileSystemDynamicConfigurationFactory.java | 21 +-
.../configcenter/nop/NopDynamicConfiguration.java | 1 +
.../nop/NopDynamicConfigurationFactory.java | 1 +
.../wrapper/CompositeDynamicConfiguration.java | 3 -
.../apache/dubbo/common/utils/ReflectUtils.java | 30 +-
...config.configcenter.DynamicConfigurationFactory | 3 +-
.../DynamicConfigurationFactoryTest.java | 25 +-
.../file/FileSystemDynamicConfigurationTest.java | 169 ++++++
dubbo-common/src/test/resources/log4j.xml | 4 +-
.../dubbo/config/AbstractInterfaceConfig.java | 23 +-
.../org/apache/dubbo/config/RegistryConfig.java | 12 +-
.../org/apache/dubbo/config/ServiceConfig.java | 17 +-
.../dubbo/config/builders/AbstractBuilder.java | 2 +-
.../apache/dubbo/config/context/ConfigManager.java | 433 +++++++-------
.../metadata/ServiceInstancePortCustomizer.java | 1 -
.../dubbo/config/context/ConfigManagerTest.java | 71 +++
.../ConfigurableMetadataServiceExporterTest.java | 4 +-
.../resources/META-INF/spring/dubbo-provider.xml | 16 +-
.../support/nacos/NacosDynamicConfiguration.java | 13 +-
dubbo-dependencies-bom/pom.xml | 11 +-
.../client/FileSystemServiceDiscovery.java | 114 ++++
37 files changed, 1704 insertions(+), 1734 deletions(-)
diff --git a/dubbo-bootstrap/pom.xml b/dubbo-bootstrap/pom.xml
index 17df134..e38e05d 100644
--- a/dubbo-bootstrap/pom.xml
+++ b/dubbo-bootstrap/pom.xml
@@ -90,6 +90,12 @@
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.curator</groupId>
+ <artifactId>curator-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
</project>
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ApplicationSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ApplicationSettings.java
deleted file mode 100644
index 23934f0..0000000
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ApplicationSettings.java
+++ /dev/null
@@ -1,127 +0,0 @@
-/*
- * 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.bootstrap;
-
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.MonitorConfig;
-import org.apache.dubbo.config.builders.ApplicationBuilder;
-
-import java.util.Map;
-
-/**
- * {@link ApplicationConfig Application} settings
- *
- * @since 2.7.4
- */
-public class ApplicationSettings extends AbstractSettings {
-
- private final ApplicationBuilder builder;
-
- public ApplicationSettings(ApplicationBuilder builder, DubboBootstrap dubboBootstrap) {
- super(dubboBootstrap);
- this.builder = builder;
- }
-
- public ApplicationSettings version(String version) {
- builder.version(version);
- return this;
- }
-
- public ApplicationSettings owner(String owner) {
- builder.owner(owner);
- return this;
- }
-
- public ApplicationSettings organization(String organization) {
- builder.organization(organization);
- return this;
- }
-
- public ApplicationSettings architecture(String architecture) {
- builder.architecture(architecture);
- return this;
- }
-
- public ApplicationSettings environment(String environment) {
- builder.environment(environment);
- return this;
- }
-
- public ApplicationSettings compiler(String compiler) {
- builder.compiler(compiler);
- return this;
- }
-
- public ApplicationSettings logger(String logger) {
- builder.logger(logger);
- return this;
- }
-
- public ApplicationSettings monitor(MonitorConfig monitor) {
- builder.monitor(monitor);
- return this;
- }
-
- public ApplicationSettings monitor(String monitor) {
- builder.monitor(monitor);
- return this;
- }
-
- public ApplicationSettings isDefault(Boolean isDefault) {
- builder.isDefault(isDefault);
- return this;
- }
-
- public ApplicationSettings dumpDirectory(String dumpDirectory) {
- builder.dumpDirectory(dumpDirectory);
- return this;
- }
-
- public ApplicationSettings qosEnable(Boolean qosEnable) {
- builder.qosEnable(qosEnable);
- return this;
- }
-
- public ApplicationSettings qosPort(Integer qosPort) {
- builder.qosPort(qosPort);
- return this;
- }
-
- public ApplicationSettings qosAcceptForeignIp(Boolean qosAcceptForeignIp) {
- builder.qosAcceptForeignIp(qosAcceptForeignIp);
- return this;
- }
-
- public ApplicationSettings shutwait(String shutwait) {
- builder.shutwait(shutwait);
- return this;
- }
-
- public ApplicationSettings appendParameter(String key, String value) {
- builder.appendParameter(key, value);
- return this;
- }
-
- public ApplicationSettings appendParameters(Map<String, String> appendParameters) {
- builder.appendParameters(appendParameters);
- return this;
- }
-
- ApplicationConfig build() {
- return builder.build();
- }
-}
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
index d20e3e0..6a2237f 100644
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
+++ b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/DubboBootstrap.java
@@ -19,14 +19,11 @@ package org.apache.dubbo.bootstrap;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
-import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
import org.apache.dubbo.common.config.configcenter.wrapper.CompositeDynamicConfiguration;
import org.apache.dubbo.common.constants.CommonConstants;
-import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
@@ -59,7 +56,7 @@ import org.apache.dubbo.registry.support.ServiceOrientedRegistry;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.HashMap;
+import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -71,9 +68,13 @@ import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.stream.Collectors;
+import static java.util.Arrays.asList;
import static java.util.concurrent.Executors.newSingleThreadExecutor;
import static org.apache.dubbo.common.config.ConfigurationUtils.parseProperties;
+import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.getDynamicConfiguration;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+import static org.apache.dubbo.config.context.ConfigManager.getInstance;
import static org.apache.dubbo.registry.support.AbstractRegistryFactory.getRegistries;
/**
@@ -91,6 +92,10 @@ public class DubboBootstrap {
public static final String DEFAULT_REFERENCE_ID = "REFERENCE#DEFAULT";
+ public static final String DEFAULT_PROVIDER_ID = "PROVIDER#DEFAULT";
+
+ public static final String DEFAULT_CONSUMER_ID = "CONSUMER#DEFAULT";
+
private static final String NAME = DubboBootstrap.class.getSimpleName();
private final Logger logger = LoggerFactory.getLogger(getClass());
@@ -105,6 +110,8 @@ public class DubboBootstrap {
private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();
+ private final ConfigManager configManager = getInstance();
+
/**
* Is provider or not
*/
@@ -121,20 +128,6 @@ public class DubboBootstrap {
private ServiceInstance serviceInstance;
- private ApplicationBuilder applicationBuilder;
-
- private ConsumerBuilder consumerBuilder;
-
- private ProviderBuilder providerBuilder;
-
- private Map<String, RegistryBuilder> registryBuilders = new HashMap<>();
-
- private Map<String, ProtocolBuilder> protocolBuilders = new HashMap<>();
-
- private Map<String, ServiceBuilder<?>> serviceBuilders = new HashMap<>();
-
- private Map<String, ReferenceBuilder<?>> referenceBuilders = new HashMap<>();
-
public DubboBootstrap() {
DubboShutdownHook.getDubboShutdownHook().register();
}
@@ -150,96 +143,205 @@ public class DubboBootstrap {
return this;
}
- /* accept Config instance */
- public DubboBootstrap application(ApplicationConfig applicationConfig) {
- ConfigManager.getInstance().setApplication(applicationConfig);
+ public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) {
+ configManager.addMetadataReport(metadataReportConfig);
return this;
}
- public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) {
- ConfigManager.getInstance().addConfigCenter(configCenterConfig);
+ public DubboBootstrap metadataReport(List<MetadataReportConfig> metadataReportConfigs) {
+ configManager.addMetadataReports(metadataReportConfigs);
return this;
}
- public DubboBootstrap configCenter(List<ConfigCenterConfig> configCenterConfigs) {
- ConfigManager.getInstance().addConfigCenter(configCenterConfigs);
- return this;
+ // {@link ApplicationConfig} correlative methods
+
+ /**
+ * Set the name of application
+ *
+ * @param name the name of application
+ * @return current {@link DubboBootstrap} instance
+ */
+ public DubboBootstrap application(String name) {
+ return application(name, builder -> {
+ // DO NOTHING
+ });
}
- public DubboBootstrap metadataReport(MetadataReportConfig metadataReportConfig) {
- ConfigManager.getInstance().addMetadataReport(metadataReportConfig);
- return this;
+ /**
+ * Set the name of application and it's future build
+ *
+ * @param name the name of application
+ * @param consumerBuilder {@link ApplicationBuilder}
+ * @return current {@link DubboBootstrap} instance
+ */
+ public DubboBootstrap application(String name, Consumer<ApplicationBuilder> consumerBuilder) {
+ ApplicationBuilder builder = createApplicationBuilder(name);
+ consumerBuilder.accept(builder);
+ return application(builder.build());
}
- public DubboBootstrap metadataReport(List<MetadataReportConfig> metadataReportConfigs) {
- ConfigManager.getInstance().addMetadataReport(metadataReportConfigs);
+ /**
+ * Set the {@link ApplicationConfig}
+ *
+ * @param applicationConfig the {@link ApplicationConfig}
+ * @return current {@link DubboBootstrap} instance
+ */
+ public DubboBootstrap application(ApplicationConfig applicationConfig) {
+ configManager.setApplication(applicationConfig);
return this;
}
+ // {@link RegistryConfig} correlative methods
+
+ /**
+ * Add an instance of {@link RegistryConfig} with {@link #DEFAULT_REGISTRY_ID default ID}
+ *
+ * @param consumerBuilder the {@link Consumer} of {@link RegistryBuilder}
+ * @return current {@link DubboBootstrap} instance
+ */
+ public DubboBootstrap registry(Consumer<RegistryBuilder> consumerBuilder) {
+ return registry(DEFAULT_REGISTRY_ID, consumerBuilder);
+ }
+
+ /**
+ * Add an instance of {@link RegistryConfig} with the specified ID
+ *
+ * @param id the {@link RegistryConfig#getId() id} of {@link RegistryConfig}
+ * @param consumerBuilder the {@link Consumer} of {@link RegistryBuilder}
+ * @return current {@link DubboBootstrap} instance
+ */
+ public DubboBootstrap registry(String id, Consumer<RegistryBuilder> consumerBuilder) {
+ RegistryBuilder builder = createRegistryBuilder(id);
+ consumerBuilder.accept(builder);
+ return registry(builder.build());
+ }
+
+ /**
+ * Add an instance of {@link RegistryConfig}
+ *
+ * @param registryConfig an instance of {@link RegistryConfig}
+ * @return current {@link DubboBootstrap} instance
+ */
public DubboBootstrap registry(RegistryConfig registryConfig) {
- ConfigManager.getInstance().addRegistry(registryConfig, true);
+ configManager.addRegistry(registryConfig);
return this;
}
- public DubboBootstrap registry(List<RegistryConfig> registryConfigs) {
- ConfigManager.getInstance().addRegistries(registryConfigs, true);
+ /**
+ * Add an instance of {@link RegistryConfig}
+ *
+ * @param registryConfigs the multiple instances of {@link RegistryConfig}
+ * @return current {@link DubboBootstrap} instance
+ */
+ public DubboBootstrap registries(Iterable<RegistryConfig> registryConfigs) {
+ registryConfigs.forEach(this::registry);
return this;
}
+ // {@link ProtocolConfig} correlative methods
+
+ public DubboBootstrap protocol(Consumer<ProtocolBuilder> consumerBuilder) {
+ return protocol(DEFAULT_PROTOCOL_ID, consumerBuilder);
+ }
+
+ public DubboBootstrap protocol(String id, Consumer<ProtocolBuilder> consumerBuilder) {
+ ProtocolBuilder builder = createProtocolBuilder(id);
+ consumerBuilder.accept(builder);
+ return protocol(builder.build());
+ }
+
public DubboBootstrap protocol(ProtocolConfig protocolConfig) {
- ConfigManager.getInstance().addProtocol(protocolConfig, true);
- return this;
+ return protocols(asList(protocolConfig));
}
public DubboBootstrap protocols(List<ProtocolConfig> protocolConfigs) {
- ConfigManager.getInstance().addProtocols(protocolConfigs, true);
+ configManager.addProtocols(protocolConfigs, true);
return this;
}
- public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
- ConfigManager.getInstance().addConsumer(consumerConfig);
- return this;
+ // {@link ServiceConfig} correlative methods
+
+ public <S> DubboBootstrap service(Consumer<ServiceBuilder<S>> consumerBuilder) {
+ return service(DEFAULT_SERVICE_ID, consumerBuilder);
}
- public DubboBootstrap provider(ProviderConfig providerConfig) {
- ConfigManager.getInstance().addProvider(providerConfig);
- return this;
+ public <S> DubboBootstrap service(String id, Consumer<ServiceBuilder<S>> consumerBuilder) {
+ ServiceBuilder builder = createServiceBuilder(id);
+ consumerBuilder.accept(builder);
+ return service(builder.build());
}
public DubboBootstrap service(ServiceConfig<?> serviceConfig) {
- ConfigManager.getInstance().addService(serviceConfig);
+ configManager.addService(serviceConfig);
return this;
}
+ // {@link Reference} correlative methods
+
+ public <S> DubboBootstrap reference(Consumer<ReferenceBuilder<S>> consumerBuilder) {
+ return reference(DEFAULT_REFERENCE_ID, consumerBuilder);
+ }
+
+ public <S> DubboBootstrap reference(String id, Consumer<ReferenceBuilder<S>> consumerBuilder) {
+ ReferenceBuilder builder = createReferenceBuilder(id);
+ consumerBuilder.accept(builder);
+ return reference(builder.build());
+ }
+
public DubboBootstrap reference(ReferenceConfig<?> referenceConfig) {
- ConfigManager.getInstance().addReference(referenceConfig);
+ configManager.addReference(referenceConfig);
return this;
}
- /* accept builder functional interface */
- public DubboBootstrap application(String name, Consumer<ApplicationBuilder> builder) {
- initApplicationBuilder(name);
- builder.accept(applicationBuilder);
- return this;
+ // {@link ProviderConfig} correlative methods
+
+ public DubboBootstrap provider(Consumer<ProviderBuilder> builderConsumer) {
+ return provider(DEFAULT_PROVIDER_ID, builderConsumer);
}
- public DubboBootstrap registry(String id, Consumer<RegistryBuilder> builder) {
- builder.accept(initRegistryBuilder(id));
- return this;
+ public DubboBootstrap provider(String id, Consumer<ProviderBuilder> builderConsumer) {
+ ProviderBuilder builder = createProviderBuilder(id);
+ builderConsumer.accept(builder);
+ return provider(builder.build());
+ }
+
+ public DubboBootstrap provider(ProviderConfig providerConfig) {
+ return providers(asList(providerConfig));
}
- public DubboBootstrap protocol(String id, Consumer<ProtocolBuilder> builder) {
- builder.accept(initProtocolBuilder(id));
+ public DubboBootstrap providers(List<ProviderConfig> providerConfigs) {
+ providerConfigs.forEach(configManager::addProvider);
return this;
}
- public <S> DubboBootstrap service(String id, Consumer<ServiceBuilder<S>> builder) {
- builder.accept(initServiceBuilder(id));
+ // {@link ConsumerConfig} correlative methods
+
+ public DubboBootstrap consumer(Consumer<ConsumerBuilder> builderConsumer) {
+ return consumer(DEFAULT_CONSUMER_ID, builderConsumer);
+ }
+
+ public DubboBootstrap consumer(String id, Consumer<ConsumerBuilder> builderConsumer) {
+ ConsumerBuilder builder = createConsumerBuilder(id);
+ builderConsumer.accept(builder);
+ return consumer(builder.build());
+ }
+
+ public DubboBootstrap consumer(ConsumerConfig consumerConfig) {
+ return consumers(asList(consumerConfig));
+ }
+
+ public DubboBootstrap consumers(List<ConsumerConfig> consumerConfigs) {
+ consumerConfigs.forEach(configManager::addConsumer);
return this;
}
- public <S> DubboBootstrap reference(String id, Consumer<ReferenceBuilder<S>> builder) {
- builder.accept(initReferenceBuilder(id));
+ // {@link ConfigCenterConfig} correlative methods
+ public DubboBootstrap configCenter(ConfigCenterConfig configCenterConfig) {
+ return configCenter(asList(configCenterConfig));
+ }
+
+ public DubboBootstrap configCenter(List<ConfigCenterConfig> configCenterConfigs) {
+ configManager.addConfigCenters(configCenterConfigs);
return this;
}
@@ -252,30 +354,13 @@ public class DubboBootstrap {
return;
}
- buildApplicationConfig();
-
- buildRegistryConfigs();
-
- buildProtocolConfigs();
-
- buildServiceConfigs();
-
- buildReferenceConfigs();
-
- clearBuilders();
-
startConfigCenter();
+
startMetadataReport();
loadRemoteConfigs();
- useRegistryAsConfigCenterIfNecessary();
-// checkApplication();
-// checkProvider();
-// chcckConsumer();
-// checkRegistry();
-// checkProtocol();
-// checkMonitor();
+ useRegistryAsConfigCenterIfNecessary();
initialized = true;
@@ -285,8 +370,6 @@ public class DubboBootstrap {
}
private void loadRemoteConfigs() {
- ConfigManager configManager = ConfigManager.getInstance();
-
// registry ids to registry configs
List<RegistryConfig> tmpRegistries = new ArrayList<>();
Set<String> registryIds = configManager.getRegistryIds();
@@ -301,7 +384,7 @@ public class DubboBootstrap {
}
});
- configManager.addRegistries(tmpRegistries, true);
+ configManager.addRegistries(tmpRegistries);
// protocol ids to protocol configs
List<ProtocolConfig> tmpProtocols = new ArrayList<>();
@@ -325,26 +408,26 @@ public class DubboBootstrap {
* there's no config center specified explicitly.
*/
private void useRegistryAsConfigCenterIfNecessary() {
- ConfigManager configManager = ConfigManager.getInstance();
- configManager.getDefaultRegistries().ifPresent(registryConfigs -> {
- for (RegistryConfig registryConfig : registryConfigs) {
- if (registryConfig != null && registryConfig.isZookeeperProtocol()) {
- // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
- Environment.getInstance().getDynamicConfiguration().orElseGet(() -> {
- Set<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
- if (CollectionUtils.isEmpty(configCenters)) {
- ConfigCenterConfig cc = new ConfigCenterConfig();
- cc.setProtocol(registryConfig.getProtocol());
- cc.setAddress(registryConfig.getAddress());
- cc.setHighestPriority(false);
- configManager.addConfigCenter(cc);
- }
- return null;
- });
- }
- }
- startConfigCenter();
+ // we use the loading status of DynamicConfiguration to decide whether ConfigCenter has been initiated.
+ if (Environment.getInstance().getDynamicConfiguration().isPresent()) {
+ return;
+ }
+
+ if (CollectionUtils.isNotEmpty(configManager.getConfigCenters())) {
+ return;
+ }
+
+ configManager.getRegistries().forEach(registryConfig -> {
+ String protocol = registryConfig.getProtocol();
+ String id = "config-center-" + protocol + "-" + registryConfig.getPort();
+ ConfigCenterConfig cc = new ConfigCenterConfig();
+ cc.setId(id);
+ cc.setProtocol(protocol);
+ cc.setAddress(registryConfig.getAddress());
+ cc.setHighestPriority(false);
+ configManager.addConfigCenter(cc);
});
+ startConfigCenter();
}
private List<ServiceDiscovery> getServiceDiscoveries() {
@@ -369,16 +452,15 @@ public class DubboBootstrap {
exportServices();
// Not only provider register and some services are exported
- if (!onlyRegisterProvider && !ConfigManager.getInstance().getServiceConfigs().isEmpty()) {
+ if (!onlyRegisterProvider && !configManager.getServiceConfigs().isEmpty()) {
/**
* export {@link MetadataService}
*/
- ConfigManager configManager = ConfigManager.getInstance();
// TODO, only export to default registry?
- List<URL> exportedURLs = exportMetadataService (
+ List<URL> exportedURLs = exportMetadataService(
configManager.getApplication().orElseThrow(() -> new IllegalStateException("ApplicationConfig cannot be null")),
- configManager.getDefaultRegistries().orElseThrow(() -> new IllegalStateException("No default RegistryConfig")),
- configManager.getDefaultProtocols().orElseThrow(() -> new IllegalStateException("No default ProtocolConfig"))
+ configManager.getRegistries(),
+ configManager.getProtocols()
);
/**
@@ -450,10 +532,10 @@ public class DubboBootstrap {
return started;
}
+
/* serve for builder apis, begin */
- private ApplicationBuilder initApplicationBuilder(String name) {
- applicationBuilder = new ApplicationBuilder().name(name);
- return applicationBuilder;
+ private ApplicationBuilder createApplicationBuilder(String name) {
+ return new ApplicationBuilder().name(name);
}
private RegistryBuilder createRegistryBuilder(String id) {
@@ -472,29 +554,21 @@ public class DubboBootstrap {
return new ReferenceBuilder().id(id);
}
- private RegistryBuilder initRegistryBuilder(String id) {
- return registryBuilders.computeIfAbsent(id, this::createRegistryBuilder);
- }
-
- private ProtocolBuilder initProtocolBuilder(String id) {
- return protocolBuilders.computeIfAbsent(id, this::createProtocolBuilder);
- }
-
- private ServiceBuilder initServiceBuilder(String id) {
- return serviceBuilders.computeIfAbsent(id, this::createServiceBuilder);
+ private ProviderBuilder createProviderBuilder(String id) {
+ return new ProviderBuilder().id(id);
}
- private ReferenceBuilder initReferenceBuilder(String id) {
- return referenceBuilders.computeIfAbsent(id, this::createReferenceBuilder);
+ private ConsumerBuilder createConsumerBuilder(String id) {
+ return new ConsumerBuilder().id(id);
}
/* serve for builder apis, end */
private void startMetadataReport() {
- ApplicationConfig applicationConfig = ConfigManager.getInstance().getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified."));
+ ApplicationConfig applicationConfig = configManager.getApplication().orElseThrow(() -> new IllegalStateException("There's no ApplicationConfig specified."));
// FIXME, multiple metadata config support.
- Set<MetadataReportConfig> metadataReportConfigs = ConfigManager.getInstance().getMetadataConfigs();
+ Collection<MetadataReportConfig> metadataReportConfigs = configManager.getMetadataConfigs();
if (CollectionUtils.isEmpty(metadataReportConfigs)) {
if (CommonConstants.METADATA_REMOTE.equals(applicationConfig.getMetadata())) {
throw new IllegalStateException("No MetadataConfig found, you must specify the remote Metadata Center address when set 'metadata=remote'.");
@@ -512,7 +586,7 @@ public class DubboBootstrap {
}
private void startConfigCenter() {
- Set<ConfigCenterConfig> configCenters = ConfigManager.getInstance().getConfigCenters();
+ Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
if (CollectionUtils.isNotEmpty(configCenters)) {
CompositeDynamicConfiguration compositeDynamicConfiguration = new CompositeDynamicConfiguration();
@@ -522,7 +596,7 @@ public class DubboBootstrap {
}
Environment.getInstance().setDynamicConfiguration(compositeDynamicConfiguration);
}
- ConfigManager.getInstance().refreshAll();
+ configManager.refreshAll();
}
private DynamicConfiguration prepareEnvironment(ConfigCenterConfig configCenter) {
@@ -533,11 +607,11 @@ public class DubboBootstrap {
DynamicConfiguration dynamicConfiguration = getDynamicConfiguration(configCenter.toUrl());
String configContent = dynamicConfiguration.getConfigs(configCenter.getConfigFile(), configCenter.getGroup());
- String appGroup = ConfigManager.getInstance().getApplication().orElse(new ApplicationConfig()).getName();
+ String appGroup = configManager.getApplication().orElse(new ApplicationConfig()).getName();
String appConfigContent = null;
- if (StringUtils.isNotEmpty(appGroup)) {
+ if (isNotEmpty(appGroup)) {
appConfigContent = dynamicConfiguration.getConfigs
- (StringUtils.isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
+ (isNotEmpty(configCenter.getAppConfigFile()) ? configCenter.getAppConfigFile() : configCenter.getConfigFile(),
appGroup
);
}
@@ -553,13 +627,6 @@ public class DubboBootstrap {
return null;
}
- private DynamicConfiguration getDynamicConfiguration(URL url) {
- DynamicConfigurationFactory factory = ExtensionLoader
- .getExtensionLoader(DynamicConfigurationFactory.class)
- .getExtension(url.getProtocol());
- return factory.getDynamicConfiguration(url);
- }
-
/**
* Add an instance of {@link EventListener}
*
@@ -572,8 +639,8 @@ public class DubboBootstrap {
}
private List<URL> exportMetadataService(ApplicationConfig applicationConfig,
- List<RegistryConfig> globalRegistryConfigs,
- List<ProtocolConfig> globalProtocolConfigs) {
+ Collection<RegistryConfig> globalRegistryConfigs,
+ Collection<ProtocolConfig> globalProtocolConfigs) {
ConfigurableMetadataServiceExporter exporter = new ConfigurableMetadataServiceExporter();
exporter.setApplicationConfig(applicationConfig);
exporter.setRegistries(globalRegistryConfigs);
@@ -581,36 +648,8 @@ public class DubboBootstrap {
return exporter.export();
}
- private void buildApplicationConfig() {
- ApplicationConfig applicationConfig = null;
- if (applicationBuilder != null) {
- applicationConfig = applicationBuilder.build();
- }
- ConfigManager.getInstance().setApplication(applicationConfig);
- }
-
- private void buildProtocolConfigs() {
- List<ProtocolConfig> protocolConfigs = buildConfigs(protocolBuilders);
- ConfigManager.getInstance().addProtocols(protocolConfigs, true);
- }
-
- private void buildRegistryConfigs() {
- List<RegistryConfig> registryConfigs = buildConfigs(registryBuilders);
- ConfigManager.getInstance().addRegistries(registryConfigs, true);
- }
-
- private void buildServiceConfigs() {
- List<ServiceConfig<?>> serviceConfigs = buildConfigs(serviceBuilders);
- serviceConfigs.forEach(ConfigManager.getInstance()::addService);
- }
-
- private void buildReferenceConfigs() {
- List<ReferenceConfig<?>> referenceConfigs = buildConfigs(referenceBuilders);
- referenceConfigs.forEach(ConfigManager.getInstance()::addReference);
- }
-
private void exportServices() {
- ConfigManager.getInstance().getServiceConfigs().forEach(this::exportServiceConfig);
+ configManager.getServiceConfigs().forEach(this::exportServiceConfig);
}
public void exportServiceConfig(ServiceConfig<?> serviceConfig) {
@@ -658,46 +697,30 @@ public class DubboBootstrap {
}
private void destroyProtocolConfigs() {
- ConfigManager.getInstance().getProtocols().values().forEach(ProtocolConfig::destroy);
+ configManager.getProtocols().forEach(ProtocolConfig::destroy);
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s all ProtocolConfigs have been destroyed.");
}
}
private void destroyReferenceConfigs() {
- ConfigManager.getInstance().getReferenceConfigs().forEach(ReferenceConfig::destroy);
+ configManager.getReferenceConfigs().forEach(ReferenceConfig::destroy);
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s all ReferenceConfigs have been destroyed.");
}
}
private void clear() {
-
- clearBuilders();
-
clearConfigs();
-
- ConfigManager.getInstance().clear();
}
private void clearConfigs() {
- ConfigManager.getInstance().clear();
+ configManager.clear();
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s configs have been clear.");
}
}
- private void clearBuilders() {
- this.applicationBuilder = null;
- this.registryBuilders.clear();
- this.protocolBuilders.clear();
- this.serviceBuilders.clear();
- this.referenceBuilders.clear();
- if (logger.isDebugEnabled()) {
- logger.debug(NAME + "'s builders have been clear.");
- }
- }
-
private void release() {
executeMutually(() -> {
while (awaited.compareAndSet(false, true)) {
@@ -725,7 +748,8 @@ public class DubboBootstrap {
}
}
- private static <C extends AbstractConfig, B extends AbstractBuilder> List<C> buildConfigs(Map<String, B> map) {
+ private static <C extends AbstractConfig, B extends
+ AbstractBuilder> List<C> buildConfigs(Map<String, B> map) {
List<C> configs = new ArrayList<>();
map.entrySet().forEach(entry -> {
configs.add((C) entry.getValue().build());
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ProtocolSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ProtocolSettings.java
deleted file mode 100644
index 5fc49ca..0000000
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ProtocolSettings.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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.bootstrap;
-
-import org.apache.dubbo.config.ProtocolConfig;
-import org.apache.dubbo.config.builders.ProtocolBuilder;
-
-import java.util.Map;
-
-/**
- * The settings of {@link ProtocolConfig protcol}
- *
- * @see ProtocolBuilder
- * @since 2.7.4
- */
-public class ProtocolSettings extends AbstractSettings {
-
- private final ProtocolBuilder builder;
-
- public ProtocolSettings(ProtocolBuilder builder, DubboBootstrap dubboBootstrap) {
- super(dubboBootstrap);
- this.builder = builder;
- }
-
- public ProtocolSettings name(String name) {
- builder.name(name);
- return this;
- }
-
- public ProtocolSettings host(String host) {
- builder.host(host);
- return this;
- }
-
- public ProtocolSettings port(Integer port) {
- builder.port(port);
- return this;
- }
-
- public ProtocolSettings contextpath(String contextpath) {
- builder.contextpath(contextpath);
- return this;
- }
-
- @Deprecated
- public ProtocolSettings path(String path) {
- builder.path(path);
- return this;
- }
-
- public ProtocolSettings threadpool(String threadpool) {
- builder.threadpool(threadpool);
- return this;
- }
-
- public ProtocolSettings corethreads(Integer corethreads) {
- builder.corethreads(corethreads);
- return this;
- }
-
- public ProtocolSettings threads(Integer threads) {
- builder.threads(threads);
- return this;
- }
-
- public ProtocolSettings iothreads(Integer iothreads) {
- builder.iothreads(iothreads);
- return this;
- }
-
- public ProtocolSettings queues(Integer queues) {
- builder.queues(queues);
- return this;
- }
-
- public ProtocolSettings accepts(Integer accepts) {
- builder.accepts(accepts);
- return this;
- }
-
- public ProtocolSettings codec(String codec) {
- builder.codec(codec);
- return this;
- }
-
- public ProtocolSettings serialization(String serialization) {
- builder.serialization(serialization);
- return this;
- }
-
- public ProtocolSettings charset(String charset) {
- builder.charset(charset);
- return this;
- }
-
- public ProtocolSettings payload(Integer payload) {
- builder.payload(payload);
- return this;
- }
-
- public ProtocolSettings buffer(Integer buffer) {
- builder.buffer(buffer);
- return this;
- }
-
- public ProtocolSettings heartbeat(Integer heartbeat) {
- builder.heartbeat(heartbeat);
- return this;
- }
-
- public ProtocolSettings accesslog(String accesslog) {
- builder.accesslog(accesslog);
- return this;
- }
-
- public ProtocolSettings transporter(String transporter) {
- builder.transporter(transporter);
- return this;
- }
-
- public ProtocolSettings exchanger(String exchanger) {
- builder.exchanger(exchanger);
- return this;
- }
-
- public ProtocolSettings dispatcher(String dispatcher) {
- builder.dispatcher(dispatcher);
- return this;
- }
-
- @Deprecated
- public ProtocolSettings dispather(String dispather) {
- builder.dispather(dispather);
- return this;
- }
-
- public ProtocolSettings networker(String networker) {
- builder.networker(networker);
- return this;
- }
-
- public ProtocolSettings server(String server) {
- builder.server(server);
- return this;
- }
-
- public ProtocolSettings client(String client) {
- builder.client(client);
- return this;
- }
-
- public ProtocolSettings telnet(String telnet) {
- builder.telnet(telnet);
- return this;
- }
-
- public ProtocolSettings prompt(String prompt) {
- builder.prompt(prompt);
- return this;
- }
-
- public ProtocolSettings status(String status) {
- builder.status(status);
- return this;
- }
-
- public ProtocolSettings register(Boolean register) {
- builder.register(register);
- return this;
- }
-
- public ProtocolSettings keepAlive(Boolean keepAlive) {
- builder.keepAlive(keepAlive);
- return this;
- }
-
- public ProtocolSettings optimizer(String optimizer) {
- builder.optimizer(optimizer);
- return this;
- }
-
- public ProtocolSettings extension(String extension) {
- builder.extension(extension);
- return this;
- }
-
- public ProtocolSettings appendParameter(String key, String value) {
- builder.appendParameter(key, value);
- return this;
- }
-
- public ProtocolSettings appendParameters(Map<String, String> appendParameters) {
- builder.appendParameters(appendParameters);
- return this;
- }
-
- public ProtocolSettings isDefault(Boolean isDefault) {
- builder.isDefault(isDefault);
- return this;
- }
-}
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ReferenceSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ReferenceSettings.java
deleted file mode 100644
index bb24e6e..0000000
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ReferenceSettings.java
+++ /dev/null
@@ -1,334 +0,0 @@
-/*
- * 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.bootstrap;
-
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.ConfigCenterConfig;
-import org.apache.dubbo.config.ConsumerConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
-import org.apache.dubbo.config.MethodConfig;
-import org.apache.dubbo.config.ModuleConfig;
-import org.apache.dubbo.config.MonitorConfig;
-import org.apache.dubbo.config.ReferenceConfig;
-import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.builders.ReferenceBuilder;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * The settings of {@link ReferenceConfig}
- *
- * @since 2.7.4
- */
-public class ReferenceSettings<S> extends AbstractSettings {
-
- private final ReferenceBuilder<S> builder;
-
- public ReferenceSettings(ReferenceBuilder<S> builder, DubboBootstrap dubboBootstrap) {
- super(dubboBootstrap);
- this.builder = builder;
- }
-
- public ReferenceSettings<S> interfaceName(String interfaceName) {
- builder.interfaceName(interfaceName);
- return this;
- }
-
- public ReferenceSettings<S> interfaceClass(Class<?> interfaceClass) {
- builder.interfaceClass(interfaceClass);
- return this;
- }
-
- public ReferenceSettings<S> client(String client) {
- builder.client(client);
- return this;
- }
-
- public ReferenceSettings<S> url(String url) {
- builder.url(url);
- return this;
- }
-
- public ReferenceSettings<S> addMethods(List<MethodConfig> methods) {
- builder.addMethods(methods);
- return this;
- }
-
- public ReferenceSettings<S> addMethod(MethodConfig method) {
- builder.addMethod(method);
- return this;
- }
-
- public ReferenceSettings<S> consumer(ConsumerConfig consumer) {
- builder.consumer(consumer);
- return this;
- }
-
- public ReferenceSettings<S> protocol(String protocol) {
- builder.protocol(protocol);
- return this;
- }
-
- public ReferenceSettings<S> check(Boolean check) {
- builder.check(check);
- return this;
- }
-
- public ReferenceSettings<S> init(Boolean init) {
- builder.init(init);
- return this;
- }
-
- public ReferenceSettings<S> generic(String generic) {
- builder.generic(generic);
- return this;
- }
-
- public ReferenceSettings<S> generic(Boolean generic) {
- builder.generic(generic);
- return this;
- }
-
- @Deprecated
- public ReferenceSettings<S> injvm(Boolean injvm) {
- builder.injvm(injvm);
- return this;
- }
-
- public ReferenceSettings<S> lazy(Boolean lazy) {
- builder.lazy(lazy);
- return this;
- }
-
- public ReferenceSettings<S> reconnect(String reconnect) {
- builder.reconnect(reconnect);
- return this;
- }
-
- public ReferenceSettings<S> sticky(Boolean sticky) {
- builder.sticky(sticky);
- return this;
- }
-
- public ReferenceSettings<S> version(String version) {
- builder.version(version);
- return this;
- }
-
- public ReferenceSettings<S> group(String group) {
- builder.group(group);
- return this;
- }
-
- @Deprecated
- public ReferenceSettings<S> local(String local) {
- builder.local(local);
- return this;
- }
-
- @Deprecated
- public ReferenceSettings<S> local(Boolean local) {
- builder.local(local);
- return this;
- }
-
- public ReferenceSettings<S> stub(String stub) {
- builder.stub(stub);
- return this;
- }
-
- public ReferenceSettings<S> stub(Boolean stub) {
- builder.stub(stub);
- return this;
- }
-
- public ReferenceSettings<S> monitor(MonitorConfig monitor) {
- builder.monitor(monitor);
- return this;
- }
-
- public ReferenceSettings<S> monitor(String monitor) {
- builder.monitor(monitor);
- return this;
- }
-
- public ReferenceSettings<S> proxy(String proxy) {
- builder.proxy(proxy);
- return this;
- }
-
- public ReferenceSettings<S> cluster(String cluster) {
- builder.cluster(cluster);
- return this;
- }
-
- public ReferenceSettings<S> filter(String filter) {
- builder.filter(filter);
- return this;
- }
-
- public ReferenceSettings<S> listener(String listener) {
- builder.listener(listener);
- return this;
- }
-
- public ReferenceSettings<S> owner(String owner) {
- builder.owner(owner);
- return this;
- }
-
- public ReferenceSettings<S> connections(Integer connections) {
- builder.connections(connections);
- return this;
- }
-
- public ReferenceSettings<S> layer(String layer) {
- builder.layer(layer);
- return this;
- }
-
- public ReferenceSettings<S> application(ApplicationConfig application) {
- builder.application(application);
- return this;
- }
-
- public ReferenceSettings<S> module(ModuleConfig module) {
- builder.module(module);
- return this;
- }
-
- public ReferenceSettings<S> addRegistries(List<RegistryConfig> registries) {
- builder.addRegistries(registries);
- return this;
- }
-
- public ReferenceSettings<S> addRegistry(RegistryConfig registry) {
- builder.addRegistry(registry);
- return this;
- }
-
- public ReferenceSettings<S> registryIds(String registryIds) {
- builder.registryIds(registryIds);
- return this;
- }
-
- public ReferenceSettings<S> onconnect(String onconnect) {
- builder.onconnect(onconnect);
- return this;
- }
-
- public ReferenceSettings<S> ondisconnect(String ondisconnect) {
- builder.ondisconnect(ondisconnect);
- return this;
- }
-
- public ReferenceSettings<S> metadataReportConfig(MetadataReportConfig metadataReportConfig) {
- builder.metadataReportConfig(metadataReportConfig);
- return this;
- }
-
- public ReferenceSettings<S> configCenter(ConfigCenterConfig configCenter) {
- builder.configCenter(configCenter);
- return this;
- }
-
- public ReferenceSettings<S> callbacks(Integer callbacks) {
- builder.callbacks(callbacks);
- return this;
- }
-
- public ReferenceSettings<S> scope(String scope) {
- builder.scope(scope);
- return this;
- }
-
- public ReferenceSettings<S> tag(String tag) {
- builder.tag(tag);
- return this;
- }
-
- public ReferenceSettings<S> timeout(Integer timeout) {
- builder.timeout(timeout);
- return this;
- }
-
- public ReferenceSettings<S> retries(Integer retries) {
- builder.retries(retries);
- return this;
- }
-
- public ReferenceSettings<S> actives(Integer actives) {
- builder.actives(actives);
- return this;
- }
-
- public ReferenceSettings<S> loadbalance(String loadbalance) {
- builder.loadbalance(loadbalance);
- return this;
- }
-
- public ReferenceSettings<S> async(Boolean async) {
- builder.async(async);
- return this;
- }
-
- public ReferenceSettings<S> sent(Boolean sent) {
- builder.sent(sent);
- return this;
- }
-
- public ReferenceSettings<S> mock(String mock) {
- builder.mock(mock);
- return this;
- }
-
- public ReferenceSettings<S> mock(Boolean mock) {
- builder.mock(mock);
- return this;
- }
-
- public ReferenceSettings<S> merger(String merger) {
- builder.merger(merger);
- return this;
- }
-
- public ReferenceSettings<S> cache(String cache) {
- builder.cache(cache);
- return this;
- }
-
- public ReferenceSettings<S> validation(String validation) {
- builder.validation(validation);
- return this;
- }
-
- public ReferenceSettings<S> appendParameters(Map<String, String> appendParameters) {
- builder.appendParameters(appendParameters);
- return this;
- }
-
- public ReferenceSettings<S> appendParameter(String key, String value) {
- builder.appendParameter(key, value);
- return this;
- }
-
- public ReferenceSettings<S> forks(Integer forks) {
- builder.forks(forks);
- return this;
- }
-}
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/RegistrySettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/RegistrySettings.java
deleted file mode 100644
index 89899ac..0000000
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/RegistrySettings.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.bootstrap;
-
-import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.builders.RegistryBuilder;
-
-import java.util.Map;
-
-/**
- * The settings of {@link RegistryConfig}
- *
- * @since 2.7.4
- */
-public class RegistrySettings extends AbstractSettings {
-
- private final RegistryBuilder builder;
-
- public RegistrySettings(RegistryBuilder builder, DubboBootstrap dubboBootstrap) {
- super(dubboBootstrap);
- this.builder = builder;
- }
-
- public RegistrySettings address(String address) {
- builder.address(address);
- return this;
- }
-
- public RegistrySettings username(String username) {
- builder.username(username);
- return this;
- }
-
- public RegistrySettings password(String password) {
- builder.password(password);
- return this;
- }
-
- public RegistrySettings port(Integer port) {
- builder.port(port);
- return this;
- }
-
- public RegistrySettings protocol(String protocol) {
- builder.protocol(protocol);
- return this;
- }
-
- public RegistrySettings transporter(String transporter) {
- builder.transporter(transporter);
- return this;
- }
-
- @Deprecated
- public RegistrySettings transport(String transport) {
- builder.transport(transport);
- return this;
- }
-
- public RegistrySettings server(String server) {
- builder.server(server);
- return this;
- }
-
- public RegistrySettings client(String client) {
- builder.client(client);
- return this;
- }
-
- public RegistrySettings cluster(String cluster) {
- builder.cluster(cluster);
- return this;
- }
-
- public RegistrySettings group(String group) {
- builder.group(group);
- return this;
- }
-
- public RegistrySettings version(String version) {
- builder.version(version);
- return this;
- }
-
- public RegistrySettings timeout(Integer timeout) {
- builder.timeout(timeout);
- return this;
- }
-
- public RegistrySettings session(Integer session) {
- builder.session(session);
- return this;
- }
-
- public RegistrySettings file(String file) {
- builder.file(file);
- return this;
- }
-
- @Deprecated
- public RegistrySettings wait(Integer wait) {
- builder.wait(wait);
- return this;
- }
-
- public RegistrySettings isCheck(Boolean check) {
- builder.isCheck(check);
- return this;
- }
-
- public RegistrySettings isDynamic(Boolean dynamic) {
- builder.isDynamic(dynamic);
- return this;
- }
-
- public RegistrySettings register(Boolean register) {
- builder.register(register);
- return this;
- }
-
- public RegistrySettings subscribe(Boolean subscribe) {
- builder.subscribe(subscribe);
- return this;
- }
-
- public RegistrySettings appendParameter(String key, String value) {
- builder.appendParameter(key, value);
- return this;
- }
-
- public RegistrySettings appendParameters(Map<String, String> appendParameters) {
- builder.appendParameters(appendParameters);
- return this;
- }
-
- public RegistrySettings isDefault(Boolean isDefault) {
- builder.isDefault(isDefault);
- return this;
- }
-
- public RegistrySettings simplified(Boolean simplified) {
- builder.simplified(simplified);
- return this;
- }
-
- public RegistrySettings extraKeys(String extraKeys) {
- builder.extraKeys(extraKeys);
- return this;
- }
-}
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ServiceSettings.java b/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ServiceSettings.java
deleted file mode 100644
index b17fa83..0000000
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/ServiceSettings.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * 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.bootstrap;
-
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.ConfigCenterConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
-import org.apache.dubbo.config.MethodConfig;
-import org.apache.dubbo.config.ModuleConfig;
-import org.apache.dubbo.config.MonitorConfig;
-import org.apache.dubbo.config.ProtocolConfig;
-import org.apache.dubbo.config.ProviderConfig;
-import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.builders.ServiceBuilder;
-
-import java.util.List;
-import java.util.Map;
-
-/**
- * The settings of {@link ServiceConfig Dubbo service}
- *
- * @since 2.7.4
- */
-public class ServiceSettings<S> extends AbstractSettings {
-
- private final ServiceBuilder<S> builder;
-
- public ServiceSettings(ServiceBuilder<S> builder, DubboBootstrap dubboBootstrap) {
- super(dubboBootstrap);
- this.builder = builder;
- }
-
- public ServiceSettings<S> interfaceName(String interfaceName) {
- builder.interfaceName(interfaceName);
- return this;
- }
-
- public ServiceSettings<S> interfaceClass(Class<?> interfaceClass) {
- builder.interfaceClass(interfaceClass);
- return this;
- }
-
- public ServiceSettings<S> ref(S ref) {
- builder.ref(ref);
- return this;
- }
-
- public ServiceSettings<S> path(String path) {
- builder.path(path);
- return this;
- }
-
- public ServiceSettings<S> addMethod(MethodConfig method) {
- builder.addMethod(method);
- return this;
- }
-
- public ServiceSettings<S> addMethods(List<? extends MethodConfig> methods) {
- builder.addMethods(methods);
- return this;
- }
-
- public ServiceSettings<S> provider(ProviderConfig provider) {
- builder.provider(provider);
- return this;
- }
-
- public ServiceSettings<S> providerIds(String providerIds) {
- builder.providerIds(providerIds);
- return this;
- }
-
- public ServiceSettings<S> generic(String generic) {
- builder.generic(generic);
- return this;
- }
-
- public ServiceSettings<S> mock(String mock) {
- builder.mock(mock);
- return this;
- }
-
- public ServiceSettings<S> mock(Boolean mock) {
- builder.mock(mock);
- return this;
- }
-
- public ServiceSettings<S> version(String version) {
- builder.version(version);
- return this;
- }
-
- public ServiceSettings<S> group(String group) {
- builder.group(group);
- return this;
- }
-
- public ServiceSettings<S> deprecated(Boolean deprecated) {
- builder.deprecated(deprecated);
- return this;
- }
-
- public ServiceSettings<S> delay(Integer delay) {
- builder.delay(delay);
- return this;
- }
-
- public ServiceSettings<S> export(Boolean export) {
- builder.export(export);
- return this;
- }
-
- public ServiceSettings<S> weight(Integer weight) {
- builder.weight(weight);
- return this;
- }
-
- public ServiceSettings<S> document(String document) {
- builder.document(document);
- return this;
- }
-
- public ServiceSettings<S> dynamic(Boolean dynamic) {
- builder.dynamic(dynamic);
- return this;
- }
-
- public ServiceSettings<S> token(String token) {
- builder.token(token);
- return this;
- }
-
- public ServiceSettings<S> token(Boolean token) {
- builder.token(token);
- return this;
- }
-
- public ServiceSettings<S> accesslog(String accesslog) {
- builder.accesslog(accesslog);
- return this;
- }
-
- public ServiceSettings<S> accesslog(Boolean accesslog) {
- builder.accesslog(accesslog);
- return this;
- }
-
- public ServiceSettings<S> addProtocols(List<ProtocolConfig> protocols) {
- builder.addProtocols(protocols);
- return this;
- }
-
- public ServiceSettings<S> addProtocol(ProtocolConfig protocol) {
- builder.addProtocol(protocol);
- return this;
- }
-
- public ServiceSettings<S> protocolIds(String protocolIds) {
- builder.protocolIds(protocolIds);
- return this;
- }
-
- public ServiceSettings<S> executes(Integer executes) {
- builder.executes(executes);
- return this;
- }
-
- public ServiceSettings<S> register(Boolean register) {
- builder.register(register);
- return this;
- }
-
- public ServiceSettings<S> warmup(Integer warmup) {
- builder.warmup(warmup);
- return this;
- }
-
- public ServiceSettings<S> serialization(String serialization) {
- builder.serialization(serialization);
- return this;
- }
-
- @Deprecated
- public ServiceSettings<S> local(String local) {
- builder.local(local);
- return this;
- }
-
- @Deprecated
- public ServiceSettings<S> local(Boolean local) {
- builder.local(local);
- return this;
- }
-
- public ServiceSettings<S> stub(String stub) {
- builder.stub(stub);
- return this;
- }
-
- public ServiceSettings<S> stub(Boolean stub) {
- builder.stub(stub);
- return this;
- }
-
- public ServiceSettings<S> monitor(MonitorConfig monitor) {
- builder.monitor(monitor);
- return this;
- }
-
- public ServiceSettings<S> monitor(String monitor) {
- builder.monitor(monitor);
- return this;
- }
-
- public ServiceSettings<S> proxy(String proxy) {
- builder.proxy(proxy);
- return this;
- }
-
- public ServiceSettings<S> cluster(String cluster) {
- builder.cluster(cluster);
- return this;
- }
-
- public ServiceSettings<S> filter(String filter) {
- builder.filter(filter);
- return this;
- }
-
- public ServiceSettings<S> listener(String listener) {
- builder.listener(listener);
- return this;
- }
-
- public ServiceSettings<S> owner(String owner) {
- builder.owner(owner);
- return this;
- }
-
- public ServiceSettings<S> connections(Integer connections) {
- builder.connections(connections);
- return this;
- }
-
- public ServiceSettings<S> layer(String layer) {
- builder.layer(layer);
- return this;
- }
-
- public ServiceSettings<S> application(ApplicationConfig application) {
- builder.application(application);
- return this;
- }
-
- public ServiceSettings<S> module(ModuleConfig module) {
- builder.module(module);
- return this;
- }
-
- public ServiceSettings<S> addRegistries(List<RegistryConfig> registries) {
- builder.addRegistries(registries);
- return this;
- }
-
- public ServiceSettings<S> addRegistry(RegistryConfig registry) {
- builder.addRegistry(registry);
- return this;
- }
-
- public ServiceSettings<S> registryIds(String registryIds) {
- builder.registryIds(registryIds);
- return this;
- }
-
- public ServiceSettings<S> onconnect(String onconnect) {
- builder.onconnect(onconnect);
- return this;
- }
-
- public ServiceSettings<S> ondisconnect(String ondisconnect) {
- builder.ondisconnect(ondisconnect);
- return this;
- }
-
- public ServiceSettings<S> metadataReportConfig(MetadataReportConfig metadataReportConfig) {
- builder.metadataReportConfig(metadataReportConfig);
- return this;
- }
-
- public ServiceSettings<S> configCenter(ConfigCenterConfig configCenter) {
- builder.configCenter(configCenter);
- return this;
- }
-
- public ServiceSettings<S> callbacks(Integer callbacks) {
- builder.callbacks(callbacks);
- return this;
- }
-
- public ServiceSettings<S> scope(String scope) {
- builder.scope(scope);
- return this;
- }
-
- public ServiceSettings<S> tag(String tag) {
- builder.tag(tag);
- return this;
- }
-
- public ServiceSettings<S> timeout(Integer timeout) {
- builder.timeout(timeout);
- return this;
- }
-
- public ServiceSettings<S> retries(Integer retries) {
- builder.retries(retries);
- return this;
- }
-
- public ServiceSettings<S> actives(Integer actives) {
- builder.actives(actives);
- return this;
- }
-
- public ServiceSettings<S> loadbalance(String loadbalance) {
- builder.loadbalance(loadbalance);
- return this;
- }
-
- public ServiceSettings<S> async(Boolean async) {
- builder.async(async);
- return this;
- }
-
- public ServiceSettings<S> sent(Boolean sent) {
- builder.sent(sent);
- return this;
- }
-
- public ServiceSettings<S> merger(String merger) {
- builder.merger(merger);
- return this;
- }
-
- public ServiceSettings<S> cache(String cache) {
- builder.cache(cache);
- return this;
- }
-
- public ServiceSettings<S> validation(String validation) {
- builder.validation(validation);
- return this;
- }
-
- public ServiceSettings<S> appendParameters(Map<String, String> appendParameters) {
- builder.appendParameters(appendParameters);
- return this;
- }
-
- public ServiceSettings<S> appendParameter(String key, String value) {
- builder.appendParameter(key, value);
- return this;
- }
-
- public ServiceSettings<S> forks(Integer forks) {
- builder.forks(forks);
- return this;
- }
-}
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java
index f49c340..96fbcc7 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboBootstrapTest.java
@@ -16,11 +16,6 @@
*/
package org.apache.dubbo.bootstrap;
-import org.apache.dubbo.config.builders.ApplicationBuilder;
-import org.apache.dubbo.config.builders.ProtocolBuilder;
-import org.apache.dubbo.config.builders.RegistryBuilder;
-import org.apache.dubbo.config.builders.ServiceBuilder;
-
import org.junit.jupiter.api.Test;
import java.io.IOException;
@@ -35,14 +30,5 @@ public class DubboBootstrapTest {
@Test
public void test() throws IOException {
- new DubboBootstrap()
- .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").build())
- .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service&metadata=remote").build())
- .protocol(ProtocolBuilder.newBuilder().port(-1).name("dubbo").build())
- .service(ServiceBuilder.newBuilder().id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).build())
- .start()
- .await();
-
- System.in.read();
}
}
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
index 4e03c1b..191b233 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceConsumerBootstrap.java
@@ -16,9 +16,8 @@
*/
package org.apache.dubbo.bootstrap;
-import org.apache.dubbo.config.builders.ApplicationBuilder;
-import org.apache.dubbo.config.builders.ReferenceBuilder;
-import org.apache.dubbo.config.builders.RegistryBuilder;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.context.ConfigManager;
/**
* Dubbo Provider Bootstrap
@@ -29,23 +28,27 @@ public class DubboServiceConsumerBootstrap {
public static void main(String[] args) throws Exception {
- DubboBootstrap bootstrap = new DubboBootstrap()
- .application(ApplicationBuilder.newBuilder().name("dubbo-consumer-demo").build())
- .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo&metadata=remote").build())
- .reference(ReferenceBuilder.newBuilder().id("ref").interfaceClass(EchoService.class).build())
+ new DubboBootstrap()
+ .application("dubbo-consumer-demo")
+ // Zookeeper
+ .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=dubbo-provider-demo"))
+ // Nacos
+ .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-provider-demo"))
+ .reference("ref", builder -> builder.interfaceClass(EchoService.class))
.onlyRegisterProvider(true)
.start()
.await();
- // TODO,
-// ReferenceConfig<EchoService> referenceConfig = ReferenceConfigCache.getCache().get(EchoService.class.getName(), EchoService.class);
-//
-// EchoService echoService = referenceConfig.get();
-//
-// for (int i = 0; i < 500; i++) {
-// Thread.sleep(2000L);
-// System.out.println(echoService.echo("Hello,World"));
-// }
+ ConfigManager configManager = ConfigManager.getInstance();
+
+ ReferenceConfig<EchoService> referenceConfig = configManager.getReferenceConfig("ref");
+
+ EchoService echoService = referenceConfig.get();
+
+ for (int i = 0; i < 500; i++) {
+ Thread.sleep(2000L);
+ System.out.println(echoService.echo("Hello,World"));
+ }
}
}
diff --git a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
index 7918bff..1ed573f 100644
--- a/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
+++ b/dubbo-bootstrap/src/test/java/org/apache/dubbo/bootstrap/DubboServiceProviderBootstrap.java
@@ -16,14 +16,6 @@
*/
package org.apache.dubbo.bootstrap;
-import org.apache.dubbo.config.builders.ApplicationBuilder;
-import org.apache.dubbo.config.builders.MetadataReportBuilder;
-import org.apache.dubbo.config.builders.ProtocolBuilder;
-import org.apache.dubbo.config.builders.RegistryBuilder;
-import org.apache.dubbo.config.builders.ServiceBuilder;
-
-import java.io.IOException;
-
/**
* Dubbo Provider Bootstrap
*
@@ -31,15 +23,15 @@ import java.io.IOException;
*/
public class DubboServiceProviderBootstrap {
- public static void main(String[] args) throws IOException {
-
+ public static void main(String[] args) {
new DubboBootstrap()
- .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").metadata("remote").build())
- .metadataReport(MetadataReportBuilder.newBuilder().address("zookeeper://127.0.0.1:2181").build())
-// .application(ApplicationBuilder.newBuilder().name("dubbo-provider-demo").build())
- .registry(RegistryBuilder.newBuilder().address("zookeeper://127.0.0.1:2181?registry-type=service").build())
- .protocol(ProtocolBuilder.newBuilder().port(-1).name("dubbo").build())
- .service(ServiceBuilder.newBuilder().id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).build())
+ .application("dubbo-provider-demo")
+ // Zookeeper in service registry type
+ .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service"))
+ // Nacos
+ .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service"))
+ .protocol(builder -> builder.port(-1).name("dubbo"))
+ .service(builder -> builder.id("test").interfaceClass(EchoService.class).ref(new EchoServiceImpl()))
.start()
.await();
}
diff --git a/dubbo-common/pom.xml b/dubbo-common/pom.xml
index 98ecc9b..dabf4bb 100644
--- a/dubbo-common/pom.xml
+++ b/dubbo-common/pom.xml
@@ -77,5 +77,9 @@
<groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId>
</dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java
index 751746f..177551b 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigChangeEvent.java
@@ -16,15 +16,18 @@
*/
package org.apache.dubbo.common.config.configcenter;
+import java.util.EventObject;
+
/**
* Config change event, immutable.
*
* @see ConfigChangeType
*/
-public class ConfigChangeEvent {
+public class ConfigChangeEvent extends EventObject {
private final String key;
private final String value;
+
private final ConfigChangeType changeType;
public ConfigChangeEvent(String key, String value) {
@@ -32,6 +35,7 @@ public class ConfigChangeEvent {
}
public ConfigChangeEvent(String key, String value, ConfigChangeType changeType) {
+ super(key + "=" + value);
this.key = key;
this.value = value;
this.changeType = changeType;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java
index 09746c5..2a1779a 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/ConfigurationListener.java
@@ -16,10 +16,12 @@
*/
package org.apache.dubbo.common.config.configcenter;
+import java.util.EventListener;
+
/**
* Config listener, will get notified when the config it listens on changes.
*/
-public interface ConfigurationListener {
+public interface ConfigurationListener extends EventListener {
/**
* Listener call back method. Listener gets notified by this method once there's any change happens on the config
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
index f5bf9a4..84b6ec3 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
@@ -16,16 +16,17 @@
*/
package org.apache.dubbo.common.config.configcenter;
+import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.Configuration;
import org.apache.dubbo.common.config.Environment;
import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.SortedMap;
-import java.util.SortedSet;
-import java.util.TreeMap;
+import static org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory.getDynamicConfigurationFactory;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
/**
@@ -38,7 +39,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
* <li>3. addListener/removeListener, add or remove listeners for governance rules or config items that need to watch.</li>
* </ul>
*/
-public interface DynamicConfiguration extends Configuration {
+public interface DynamicConfiguration extends Configuration, AutoCloseable {
String DEFAULT_GROUP = "dubbo";
@@ -133,6 +134,20 @@ public interface DynamicConfiguration extends Configuration {
*/
String getConfigs(String key, String group, long timeout) throws IllegalStateException;
+
+ /**
+ * Publish Config mapped to the given key under the {@link #DEFAULT_GROUP default group}
+ *
+ * @param key the key to represent a configuration
+ * @param content the content of configuration
+ * @return <code>true</code> if success, or <code>false</code>
+ * @throws UnsupportedOperationException If the under layer does not support
+ * @since 2.7.4
+ */
+ default boolean publishConfig(String key, String content) throws UnsupportedOperationException {
+ return publishConfig(key, DEFAULT_GROUP, content);
+ }
+
/**
* Publish Config mapped to the given key and the given group.
*
@@ -148,45 +163,92 @@ public interface DynamicConfiguration extends Configuration {
}
/**
+ * Remove Config mapped to the given key under the {@link #DEFAULT_GROUP default group}
+ *
+ * @param key the key to represent a configuration
+ * @return the content of configuration was removed
+ * @throws UnsupportedOperationException If the under layer does not support
+ * @since 2.7.4
+ */
+ default String removeConfig(String key) throws UnsupportedOperationException {
+ return removeConfig(key, DEFAULT_GROUP);
+ }
+
+ /**
+ * Remove Config mapped to the given key and the given group.
+ *
+ * @param key the key to represent a configuration
+ * @param group the group where the key belongs to
+ * @return the content of configuration was removed
+ * @throws UnsupportedOperationException If the under layer does not support
+ * @since 2.7.4
+ */
+ default String removeConfig(String key, String group) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("No support");
+ }
+
+ /**
+ * Get all groups
+ *
+ * @return the read-only non-null {@link Set set} of config keys
+ * @throws UnsupportedOperationException If the under layer does not support
+ * @since 2.7.4
+ */
+ default Set<String> getConfigGroups() throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("No support");
+ }
+
+ /**
* Get the config keys by the specified group
*
* @param group the specified group
- * @return the read-only non-null sorted {@link Set set} of config keys
+ * @return the read-only non-null {@link Set set} of config keys
* @throws UnsupportedOperationException If the under layer does not support
* @since 2.7.4
*/
- default SortedSet<String> getConfigKeys(String group) throws UnsupportedOperationException {
+ default Set<String> getConfigKeys(String group) throws UnsupportedOperationException {
throw new UnsupportedOperationException("No support");
}
/**
- * Get the {@link SortedMap} with with config keys and contents value by the specified group
+ * Get the {@link Map} with with config keys and contents value by the specified group
*
* @param group the specified group
- * @return the read-only non-null sorted {@link SortedMap map}
+ * @return the read-only non-null {@link Map map}
* @throws UnsupportedOperationException If the under layer does not support
* @since 2.7.4
*/
- default SortedMap<String, String> getConfigs(String group) throws UnsupportedOperationException {
+ default Map<String, String> getConfigs(String group) throws UnsupportedOperationException {
return getConfigs(group, -1);
}
/**
- * Get the {@link SortedMap} with with config keys and content value by the specified group
+ * Get the {@link Map} with with config keys and content value by the specified group
*
* @param group the specified group
* @param timeout the millisecond for timeout
- * @return the read-only non-null sorted {@link SortedMap map}
+ * @return the read-only non-null {@link Map map}
* @throws UnsupportedOperationException If the under layer does not support
* @throws IllegalStateException If timeout exceeds
* @since 2.7.4
*/
- default SortedMap<String, String> getConfigs(String group, long timeout) throws UnsupportedOperationException,
+ default Map<String, String> getConfigs(String group, long timeout) throws UnsupportedOperationException,
IllegalStateException {
- SortedMap<String, String> configs = new TreeMap<>();
- SortedSet<String> configKeys = getConfigKeys(group);
+ Map<String, String> configs = new LinkedHashMap<>();
+ Set<String> configKeys = getConfigKeys(group);
configKeys.forEach(key -> configs.put(key, getConfig(key, group, timeout)));
- return Collections.unmodifiableSortedMap(configs);
+ return Collections.unmodifiableMap(configs);
+ }
+
+ /**
+ * Close the configuration
+ *
+ * @throws Exception
+ * @since 2.7.4
+ */
+ @Override
+ default void close() throws Exception {
+ throw new UnsupportedOperationException();
}
/**
@@ -200,4 +262,17 @@ public interface DynamicConfiguration extends Configuration {
.getDefaultExtension()
.getDynamicConfiguration(null));
}
+
+ /**
+ * Get the instance of {@link DynamicConfiguration} by the specified connection {@link URL}
+ *
+ * @param connectionURL
+ * @return non-null
+ * @since 2.7.4
+ */
+ static DynamicConfiguration getDynamicConfiguration(URL connectionURL) {
+ String protocol = connectionURL.getProtocol();
+ DynamicConfigurationFactory factory = getDynamicConfigurationFactory(protocol);
+ return factory.getDynamicConfiguration(connectionURL);
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
index 59c27ce..649eec6 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactory.java
@@ -17,14 +17,30 @@
package org.apache.dubbo.common.config.configcenter;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.SPI;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+
/**
- *
+ * The factory interface to create the instance of {@link DynamicConfiguration}
*/
-@SPI("nop")
+@SPI("file") // 2.7.4 change the default SPI implementation
public interface DynamicConfigurationFactory {
DynamicConfiguration getDynamicConfiguration(URL url);
+ /**
+ * Get an instance of {@link DynamicConfigurationFactory} by the specified name. If not found, take the default
+ * extension of {@link DynamicConfigurationFactory}
+ *
+ * @param name the name of extension of {@link DynamicConfigurationFactory}
+ * @return non-null
+ * @see 2.7.4
+ */
+ static DynamicConfigurationFactory getDynamicConfigurationFactory(String name) {
+ Class<DynamicConfigurationFactory> factoryClass = DynamicConfigurationFactory.class;
+ ExtensionLoader<DynamicConfigurationFactory> loader = getExtensionLoader(factoryClass);
+ return loader.hasExtension(name) ? loader.getExtension(name) : loader.getDefaultExtension();
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
new file mode 100644
index 0000000..b75527e
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
@@ -0,0 +1,628 @@
+/*
+ * 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.configcenter.file;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.function.ThrowableConsumer;
+import org.apache.dubbo.common.function.ThrowableFunction;
+import org.apache.dubbo.common.utils.NamedThreadFactory;
+
+import com.sun.nio.file.SensitivityWatchEventModifier;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Future;
+import java.util.concurrent.SynchronousQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.lang.String.format;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_DELETE;
+import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY;
+import static java.util.Collections.emptySet;
+import static java.util.Collections.unmodifiableMap;
+import static java.util.concurrent.Executors.newFixedThreadPool;
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.apache.commons.io.FileUtils.readFileToString;
+import static org.apache.dubbo.common.utils.StringUtils.isBlank;
+
+/**
+ * File-System based {@link DynamicConfiguration} implementation
+ *
+ * @since 2.7.4
+ */
+public class FileSystemDynamicConfiguration implements DynamicConfiguration {
+
+ public static final String PARAM_NAME_PREFIX = "dubbo.config-center.";
+
+ public static final String CONFIG_CENTER_DIR_PARAM_NAME = PARAM_NAME_PREFIX + "dir";
+
+ public static final String THREAD_POOL_PREFIX_PARAM_NAME = PARAM_NAME_PREFIX + "thread-pool.prefix";
+
+ public static final String THREAD_POOL_SIZE_PARAM_NAME = PARAM_NAME_PREFIX + "thread-pool.size";
+
+ public static final String CONFIG_CENTER_ENCODING_PARAM_NAME = PARAM_NAME_PREFIX + "encoding";
+
+ public static final String DEFAULT_CONFIG_CENTER_DIR_PATH = System.getProperty("user.home") + File.separator
+ + ".dubbo" + File.separator + "config-center";
+
+ public static final String DEFAULT_THREAD_POOL_PREFIX = PARAM_NAME_PREFIX + "workers";
+
+ public static final String DEFAULT_THREAD_POOL_SIZE = "1";
+
+ public static final String DEFAULT_CONFIG_CENTER_ENCODING = "UTF-8";
+
+ private static final WatchEvent.Kind[] INTEREST_PATH_KINDS = of(ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
+
+ /**
+ * The class name of {@linkplain sun.nio.fs.PollingWatchService}
+ */
+ private static final String POLLING_WATCH_SERVICE_CLASS_NAME = "sun.nio.fs.PollingWatchService";
+
+ private static final int THREAD_POOL_SIZE = 1;
+
+ /**
+ * Logger
+ */
+ private static final Log logger = LogFactory.getLog(FileSystemDynamicConfiguration.class);
+
+ /**
+ * The unmodifiable map for {@link ConfigChangeType} whose key is the {@link WatchEvent.Kind#name() name} of
+ * {@link WatchEvent.Kind WatchEvent's Kind}
+ */
+ private static final Map<String, ConfigChangeType> CONFIG_CHANGE_TYPES_MAP =
+ unmodifiableMap(new HashMap<String, ConfigChangeType>() {
+ // Initializes the elements that is mapping ConfigChangeType
+ {
+ put(ENTRY_CREATE.name(), ConfigChangeType.ADDED);
+ put(ENTRY_DELETE.name(), ConfigChangeType.DELETED);
+ put(ENTRY_MODIFY.name(), ConfigChangeType.MODIFIED);
+ }
+ });
+
+ private static final Optional<WatchService> watchService;
+
+ /**
+ * Is Pooling Based Watch Service
+ *
+ * @see #detectPoolingBasedWatchService(Optional)
+ */
+ private static final boolean basedPoolingWatchService;
+
+ private static final WatchEvent.Modifier[] modifiers;
+
+ /**
+ * the delay to action in seconds. If null, execute indirectly
+ */
+ private static final Integer delay;
+
+ /**
+ * The thread pool for {@link WatchEvent WatchEvents} loop
+ * It's optional if there is not any {@link ConfigurationListener} registration
+ *
+ * @see ThreadPoolExecutor
+ */
+ private static final ThreadPoolExecutor watchEventsLoopThreadPool;
+
+ // static initialization
+ static {
+ watchService = newWatchService();
+ basedPoolingWatchService = detectPoolingBasedWatchService(watchService);
+ modifiers = initWatchEventModifiers();
+ delay = initDelay(modifiers);
+ watchEventsLoopThreadPool = newWatchEventsLoopThreadPool();
+ }
+
+ /**
+ * The Root Directory for config center
+ */
+ private final File rootDirectory;
+
+ private final String encoding;
+
+ /**
+ * The thread pool for workers who executes the tasks
+ */
+ private final ThreadPoolExecutor workersThreadPool;
+
+ /**
+ * The {@link Set} of {@link #configDirectory(String) directories} that may be processing,
+ * <p>
+ * if {@link #isBasedPoolingWatchService()} is <code>false</code>, this properties will be
+ * {@link Collections#emptySet() empty}
+ *
+ * @see #initProcessingDirectories()
+ */
+ private final Set<File> processingDirectories;
+
+ private final Map<File, List<ConfigurationListener>> listenersRepository;
+
+ public FileSystemDynamicConfiguration(URL url) {
+ this(initDirectory(url), getEncoding(url), getThreadPoolPrefixName(url), getThreadPoolSize(url));
+ }
+
+ public FileSystemDynamicConfiguration(File rootDirectory, String encoding,
+ String threadPoolPrefixName,
+ int threadPoolSize
+ ) {
+ this.rootDirectory = rootDirectory;
+ this.encoding = encoding;
+ this.workersThreadPool = initWorkersThreadPool(threadPoolPrefixName, threadPoolSize);
+ this.processingDirectories = initProcessingDirectories();
+ this.listenersRepository = new LinkedHashMap<>();
+ }
+
+ private Set<File> initProcessingDirectories() {
+ return isBasedPoolingWatchService() ? new LinkedHashSet<>() : emptySet();
+ }
+
+ @Override
+ public void addListener(String key, String group, ConfigurationListener listener) {
+ doInListener(key, group, (configFilePath, listeners) -> {
+
+ if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before
+ ThrowableConsumer.execute(configFilePath, configFile -> {
+ FileUtils.forceMkdirParent(configFile);
+ // A rootDirectory to be watched
+ File configDirectory = configFile.getParentFile();
+ if (configDirectory != null) {
+ // Register the configDirectory
+ configDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, modifiers);
+ }
+ });
+ }
+
+ // Add into cache
+ listeners.add(listener);
+ });
+ }
+
+ @Override
+ public void removeListener(String key, String group, ConfigurationListener listener) {
+ doInListener(key, group, (file, listeners) -> {
+ // Remove into cache
+ listeners.remove(listener);
+ });
+ }
+
+ protected File configDirectory(String group) {
+ String actualGroup = isBlank(group) ? DEFAULT_GROUP : group;
+ return new File(rootDirectory, actualGroup);
+ }
+
+ protected File configFile(String key, String group) {
+ return new File(configDirectory(group), key);
+ }
+
+ private void doInListener(String key, String group, BiConsumer<File, List<ConfigurationListener>> consumer) {
+ watchService.ifPresent(watchService -> {
+ File configFile = configFile(key, group);
+ executeMutually(configFile.getParentFile(), () -> {
+ // process the WatchEvents if not start
+ if (!isProcessingWatchEvents()) {
+ processWatchEvents(watchService);
+ }
+
+ List<ConfigurationListener> listeners = getListeners(configFile);
+ consumer.accept(configFile, listeners);
+
+ // Nothing to return
+ return null;
+ });
+ });
+ }
+
+ private static boolean isProcessingWatchEvents() {
+ return getWatchEventsLoopThreadPool().getActiveCount() > 0;
+ }
+
+ /**
+ * Process the {@link WatchEvent WatchEvents} loop in async execution
+ *
+ * @param watchService {@link WatchService}
+ */
+ private void processWatchEvents(WatchService watchService) {
+ getWatchEventsLoopThreadPool().execute(() -> { // WatchEvents Loop
+ while (true) {
+ WatchKey watchKey = null;
+ try {
+ watchKey = watchService.take();
+ if (watchKey.isValid()) {
+ for (WatchEvent event : watchKey.pollEvents()) {
+ WatchEvent.Kind kind = event.kind();
+ // configChangeType's key to match WatchEvent's Kind
+ ConfigChangeType configChangeType = CONFIG_CHANGE_TYPES_MAP.get(kind.name());
+ if (configChangeType != null) {
+ Path configDirectoryPath = (Path) watchKey.watchable();
+ Path currentPath = (Path) event.context();
+ Path configFilePath = configDirectoryPath.resolve(currentPath);
+ File configDirectory = configDirectoryPath.toFile();
+ executeMutually(configDirectory, () -> {
+ fireConfigChangeEvent(configFilePath.toFile(), configChangeType);
+ signalConfigDirectory(configDirectory);
+ return null;
+ });
+ }
+ }
+ }
+ } catch (Exception e) {
+ return;
+ } finally {
+ if (watchKey != null) {
+ // reset
+ watchKey.reset();
+ }
+ }
+ }
+ });
+ }
+
+ private void signalConfigDirectory(File configDirectory) {
+ if (isBasedPoolingWatchService()) {
+ // remove configDirectory from processing set because it's done
+ removeProcessingDirectory(configDirectory);
+ // notify configDirectory
+ notifyProcessingDirectory(configDirectory);
+ if (logger.isDebugEnabled()) {
+ logger.debug(format("The config rootDirectory[%s] is signalled...", configDirectory.getName()));
+ }
+ }
+ }
+
+ private void removeProcessingDirectory(File configDirectory) {
+ processingDirectories.remove(configDirectory);
+ }
+
+ private void notifyProcessingDirectory(File configDirectory) {
+ configDirectory.notifyAll();
+ }
+
+ private List<ConfigurationListener> getListeners(File configFile) {
+ return listenersRepository.computeIfAbsent(configFile, p -> new LinkedList<>());
+ }
+
+ private void fireConfigChangeEvent(File configFile, ConfigChangeType configChangeType) {
+ String key = configFile.getName();
+ String value = getConfig(configFile, -1L);
+ // fire ConfigChangeEvent one by one
+ getListeners(configFile).forEach(listener -> {
+ try {
+ listener.process(new ConfigChangeEvent(key, value, configChangeType));
+ } catch (Throwable e) {
+ if (logger.isErrorEnabled()) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ });
+ }
+
+ @Override
+ public String getConfig(String key, String group, long timeout) throws IllegalStateException {
+ File configFile = configFile(key, group);
+ return getConfig(configFile, timeout);
+ }
+
+ protected String getConfig(File configFile, long timeout) {
+ return canRead(configFile) ? execute(() -> readFileToString(configFile, getEncoding()), timeout) : null;
+ }
+
+ private boolean canRead(File file) {
+ return file.exists() && file.canRead();
+ }
+
+ @Override
+ public String getConfigs(String key, String group, long timeout) throws IllegalStateException {
+ return getConfig(key, group, timeout);
+ }
+
+ @Override
+ public Object getInternalProperty(String key) {
+ return null;
+ }
+
+ @Override
+ public boolean publishConfig(String key, String group, String content) {
+ return delay(key, group, configFile -> {
+ FileUtils.write(configFile, content, getEncoding());
+ return true;
+ });
+ }
+
+ @Override
+ public String removeConfig(String key, String group) {
+ return delay(key, group, configFile -> {
+
+ String content = getConfig(configFile, -1L);
+
+ FileUtils.deleteQuietly(configFile);
+
+ return content;
+ });
+ }
+
+ private ThreadPoolExecutor initWorkersThreadPool(String prefix, int size) {
+ return (ThreadPoolExecutor) newFixedThreadPool(size, new NamedThreadFactory(prefix));
+ }
+
+ /**
+ * Delay action for {@link #configFile(String, String) config file}
+ *
+ * @param key the key to represent a configuration
+ * @param group the group where the key belongs to
+ * @param function the customized {@link Function function} with {@link File}
+ * @param <V> the computed value
+ * @return
+ */
+ protected <V> V delay(String key, String group, ThrowableFunction<File, V> function) {
+ File configFile = configFile(key, group);
+ // Must be based on PoolingWatchService and has listeners under config file
+ if (isBasedPoolingWatchService()) {
+ File configDirectory = configFile.getParentFile();
+ executeMutually(configDirectory, () -> {
+ if (hasListeners(configFile) && isProcessing(configDirectory)) {
+ Integer delay = getDelay();
+ if (delay != null) {
+ // wait for delay in seconds
+ long timeout = SECONDS.toMillis(delay);
+ if (logger.isDebugEnabled()) {
+ logger.debug(format("The config[key : %s, group : %s] is about to delay in %d ms.",
+ key, group, timeout));
+ }
+ configDirectory.wait(timeout);
+ }
+ }
+ addProcessing(configDirectory);
+ return null;
+ });
+ }
+
+ V value = null;
+
+ try {
+ value = function.apply(configFile);
+ } catch (Throwable e) {
+ if (logger.isErrorEnabled()) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+
+ return value;
+ }
+
+ private boolean hasListeners(File configFile) {
+ return getListeners(configFile).size() > 0;
+ }
+
+ /**
+ * Is processing on {@link #configDirectory(String) config rootDirectory}
+ *
+ * @param configDirectory {@link #configDirectory(String) config rootDirectory}
+ * @return if processing , return <code>true</code>, or <code>false</code>
+ */
+ private boolean isProcessing(File configDirectory) {
+ return processingDirectories.contains(configDirectory);
+ }
+
+ private void addProcessing(File configDirectory) {
+ processingDirectories.add(configDirectory);
+ }
+
+ @Override
+ public Set<String> getConfigKeys(String group) {
+ return Stream.of(configDirectory(group).listFiles(File::isFile))
+ .map(File::getName)
+ .collect(Collectors.toSet());
+ }
+
+
+ @Override
+ public Set<String> getConfigGroups() {
+ return Stream.of(getRootDirectory().listFiles())
+ .filter(File::isDirectory)
+ .map(File::getName)
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public Map<String, String> getConfigs(String group) throws UnsupportedOperationException {
+ return getConfigs(group, -1);
+ }
+
+ @Override
+ public void close() throws Exception {
+ // TODO
+ }
+
+ private <V> V execute(Callable<V> task, long timeout) {
+ V value = null;
+ try {
+
+ if (timeout < 1) { // less or equal 0
+ value = task.call();
+ } else {
+ Future<V> future = workersThreadPool.submit(task);
+ value = future.get(timeout, TimeUnit.MILLISECONDS);
+ }
+ } catch (Exception e) {
+ if (logger.isErrorEnabled()) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ return value;
+ }
+
+ protected File getRootDirectory() {
+ return rootDirectory;
+ }
+
+ protected ThreadPoolExecutor getWorkersThreadPool() {
+ return workersThreadPool;
+ }
+
+ protected String getEncoding() {
+ return encoding;
+ }
+
+ protected Integer getDelay() {
+ return delay;
+ }
+
+ /**
+ * It's whether the implementation of {@link WatchService} is based on {@linkplain sun.nio.fs.PollingWatchService}
+ * or not.
+ * <p>
+ *
+ * @return if based, return <code>true</code>, or <code>false</code>
+ * @see #detectPoolingBasedWatchService(Optional)
+ */
+ protected static boolean isBasedPoolingWatchService() {
+ return basedPoolingWatchService;
+ }
+
+ private static String getThreadPoolPrefixName(URL url) {
+ return getParameter(url, THREAD_POOL_PREFIX_PARAM_NAME, DEFAULT_THREAD_POOL_PREFIX);
+ }
+
+ protected static ThreadPoolExecutor getWatchEventsLoopThreadPool() {
+ return watchEventsLoopThreadPool;
+ }
+
+ private <V> V executeMutually(Object mutex, Callable<V> callable) {
+ V value = null;
+ synchronized (mutex) {
+ try {
+ value = callable.call();
+ } catch (Exception e) {
+ if (logger.isErrorEnabled()) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ }
+ return value;
+ }
+
+ private static <T> T[] of(T... values) {
+ return values;
+ }
+
+ private static Integer initDelay(WatchEvent.Modifier[] modifiers) {
+ return Stream.of(modifiers)
+ .filter(modifier -> modifier instanceof SensitivityWatchEventModifier)
+ .map(SensitivityWatchEventModifier.class::cast)
+ .map(SensitivityWatchEventModifier::sensitivityValueInSeconds)
+ .max(Integer::compareTo)
+ .orElse(null);
+ }
+
+ private static WatchEvent.Modifier[] initWatchEventModifiers() {
+ if (isBasedPoolingWatchService()) { // If based on PollingWatchService, High sensitivity will be used
+ return of(SensitivityWatchEventModifier.HIGH);
+ } else {
+ return of();
+ }
+ }
+
+ /**
+ * Detect the argument of {@link WatchService} is based on {@linkplain sun.nio.fs.PollingWatchService}
+ * or not.
+ * <p>
+ * Some platforms do not provide the native implementation of {@link WatchService}, just use
+ * {@linkplain sun.nio.fs.PollingWatchService} in periodic poll file modifications.
+ *
+ * @param watchService the instance of {@link WatchService}
+ * @return if based, return <code>true</code>, or <code>false</code>
+ */
+ private static boolean detectPoolingBasedWatchService(Optional<WatchService> watchService) {
+ String className = watchService.map(Object::getClass).map(Class::getName).orElse(null);
+ return POLLING_WATCH_SERVICE_CLASS_NAME.equals(className);
+ }
+
+ private static Optional<WatchService> newWatchService() {
+ Optional<WatchService> watchService = null;
+ FileSystem fileSystem = FileSystems.getDefault();
+ try {
+ watchService = Optional.of(fileSystem.newWatchService());
+ } catch (IOException e) {
+ if (logger.isErrorEnabled()) {
+ logger.error(e.getMessage(), e);
+ }
+ watchService = Optional.empty();
+ }
+ return watchService;
+ }
+
+ private static File initDirectory(URL url) {
+ String directoryPath = getParameter(url, CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH);
+ File rootDirectory = new File(getParameter(url, CONFIG_CENTER_DIR_PARAM_NAME, DEFAULT_CONFIG_CENTER_DIR_PATH));
+ if (!rootDirectory.exists() && !rootDirectory.mkdirs()) {
+ throw new IllegalStateException(format("Dubbo config center rootDirectory[%s] can't be created!",
+ directoryPath));
+ }
+ return rootDirectory;
+ }
+
+ private static String getParameter(URL url, String name, String defaultValue) {
+ if (url != null) {
+ return url.getParameter(name, defaultValue);
+ }
+ return defaultValue;
+ }
+
+ private static String getEncoding(URL url) {
+ return getParameter(url, CONFIG_CENTER_ENCODING_PARAM_NAME, DEFAULT_CONFIG_CENTER_ENCODING);
+ }
+
+ private static int getThreadPoolSize(URL url) {
+ return Integer.parseInt(getParameter(url, THREAD_POOL_SIZE_PARAM_NAME, DEFAULT_THREAD_POOL_SIZE));
+ }
+
+ private static ThreadPoolExecutor newWatchEventsLoopThreadPool() {
+ return new ThreadPoolExecutor(THREAD_POOL_SIZE, THREAD_POOL_SIZE,
+ 0L, MILLISECONDS,
+ new SynchronousQueue(),
+ new NamedThreadFactory("dubbo-config-center-watch-events-loop", true));
+ }
+}
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/AbstractSettings.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java
similarity index 57%
rename from dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/AbstractSettings.java
rename to dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java
index 7ed1de5..f2a1332 100644
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/AbstractSettings.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationFactory.java
@@ -14,23 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.bootstrap;
+package org.apache.dubbo.common.config.configcenter.file;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
/**
- * Abstract {@link Settings}
+ * File-System based {@link DynamicConfigurationFactory} implementation
*
* @since 2.7.4
*/
-public class AbstractSettings implements Settings {
-
- private final DubboBootstrap dubboBootstrap;
-
- public AbstractSettings(DubboBootstrap dubboBootstrap) {
- this.dubboBootstrap = dubboBootstrap;
- }
+public class FileSystemDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory {
@Override
- public DubboBootstrap next() {
- return dubboBootstrap;
+ protected DynamicConfiguration createDynamicConfiguration(URL url) {
+ return new FileSystemDynamicConfiguration(url);
}
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
index 14accb2..a69f115 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
@@ -28,6 +28,7 @@ import static java.util.Collections.emptySortedSet;
* The default extension of {@link DynamicConfiguration}. If user does not specify a config centre, or specifies one
* that is not a valid extension, it will default to this one.
*/
+@Deprecated
public class NopDynamicConfiguration implements DynamicConfiguration {
public NopDynamicConfiguration(URL url) {
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java
index bd45e7f..487f70d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfigurationFactory.java
@@ -23,6 +23,7 @@ import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
/**
*
*/
+@Deprecated
public class NopDynamicConfigurationFactory extends AbstractDynamicConfigurationFactory {
@Override
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java
index 7f98d38..016265d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/wrapper/CompositeDynamicConfiguration.java
@@ -89,9 +89,6 @@ public class CompositeDynamicConfiguration implements DynamicConfiguration {
Object value = null;
for (DynamicConfiguration configuration : configurations) {
value = func.apply(configuration);
- if (value != null) {
- break;
- }
}
return value;
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
index 2720229..f8e987c 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/ReflectUtils.java
@@ -21,6 +21,9 @@ import javassist.CtConstructor;
import javassist.CtMethod;
import javassist.NotFoundException;
+import java.beans.BeanInfo;
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -48,6 +51,7 @@ import java.util.concurrent.Future;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
+import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Collections.unmodifiableSet;
@@ -1127,7 +1131,7 @@ public final class ReflectUtils {
}
return new Type[]{returnType, genericReturnType};
}
-
+
/**
* Find the {@link Set} of {@link ParameterizedType}
*
@@ -1184,4 +1188,28 @@ public final class ReflectUtils {
return unmodifiableSet(hierarchicalTypes);
}
+
+ public static <T> T getProperty(Object bean, String propertyName) {
+ Class<?> beanClass = bean.getClass();
+ BeanInfo beanInfo = null;
+ T propertyValue = null;
+ try {
+ beanInfo = Introspector.getBeanInfo(beanClass);
+ propertyValue = (T) Stream.of(beanInfo.getPropertyDescriptors())
+ .filter(propertyDescriptor -> propertyName.equals(propertyDescriptor.getName()))
+ .map(PropertyDescriptor::getReadMethod)
+ .findFirst()
+ .map(method -> {
+ try {
+ return method.invoke(bean);
+ } catch (Exception e) {
+ }
+ return null;
+ }).get();
+ } catch (Exception e) {
+
+ }
+ return propertyValue;
+ }
+
}
\ No newline at end of file
diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
index 42d6a25..f6fe6d6 100644
--- a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
+++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory
@@ -1 +1,2 @@
-nop=org.apache.dubbo.common.config.configcenter.nop.NopDynamicConfigurationFactory
\ No newline at end of file
+nop=org.apache.dubbo.common.config.configcenter.nop.NopDynamicConfigurationFactory
+file=org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfigurationFactory
\ No newline at end of file
diff --git a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/Settings.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactoryTest.java
similarity index 51%
rename from dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/Settings.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactoryTest.java
index 290bb7e..eacd3ee 100644
--- a/dubbo-bootstrap/src/main/java/org/apache/dubbo/bootstrap/Settings.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/DynamicConfigurationFactoryTest.java
@@ -14,19 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.bootstrap;
+package org.apache.dubbo.common.config.configcenter;
+
+import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfigurationFactory;
+
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.junit.jupiter.api.Assertions.assertEquals;
/**
- * The Dubbo settings
+ * {@link DynamicConfigurationFactory} Test
*
* @since 2.7.4
*/
-public interface Settings {
+public class DynamicConfigurationFactoryTest {
- /**
- * Go next settings
- *
- * @return {@link DubboBootstrap}
- */
- DubboBootstrap next();
+ @Test
+ public void testDefaultExtension() {
+ DynamicConfigurationFactory factory = getExtensionLoader(DynamicConfigurationFactory.class).getDefaultExtension();
+ assertEquals(FileSystemDynamicConfigurationFactory.class, factory.getClass());
+ assertEquals(factory, getExtensionLoader(DynamicConfigurationFactory.class).getExtension("file"));
+ }
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java
new file mode 100644
index 0000000..c68cd4c
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.configcenter.file;
+
+import org.apache.dubbo.common.URL;
+
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static java.util.Collections.singleton;
+import static org.apache.commons.io.FileUtils.deleteQuietly;
+import static org.apache.dubbo.common.URL.valueOf;
+import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_GROUP;
+import static org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration.CONFIG_CENTER_DIR_PARAM_NAME;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link FileSystemDynamicConfiguration} Test
+ */
+public class FileSystemDynamicConfigurationTest {
+
+ private FileSystemDynamicConfiguration configuration;
+
+ private static final String KEY = "abc-def-ghi";
+
+ private static final String CONTENT = "Hello,World";
+
+ @BeforeEach
+ public void init() {
+ String classPath = getClassPath();
+ URL url = valueOf("dubbo://127.0.0.1:20880").addParameter(CONFIG_CENTER_DIR_PARAM_NAME, classPath + File.separator + "config-center");
+ configuration = new FileSystemDynamicConfiguration(url);
+ deleteQuietly(configuration.getRootDirectory());
+ }
+
+ private String getClassPath() {
+ return getClass().getProtectionDomain().getCodeSource().getLocation().getPath();
+ }
+
+ @Test
+ public void testInit() {
+
+ assertEquals(new File(getClassPath(), "config-center"), configuration.getRootDirectory());
+ assertEquals("UTF-8", configuration.getEncoding());
+ assertEquals(ThreadPoolExecutor.class, configuration.getWorkersThreadPool().getClass());
+ assertEquals(1, (configuration.getWorkersThreadPool()).getCorePoolSize());
+ assertEquals(1, (configuration.getWorkersThreadPool()).getMaximumPoolSize());
+ assertNotNull(configuration.getWatchEventsLoopThreadPool());
+ assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getCorePoolSize());
+ assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getMaximumPoolSize());
+
+ if (configuration.isBasedPoolingWatchService()) {
+ assertEquals(2, configuration.getDelay());
+ } else {
+ assertNull(configuration.getDelay());
+ }
+ }
+
+ @Test
+ public void testPublishAndGetConfig() {
+ assertTrue(configuration.publishConfig(KEY, CONTENT));
+ assertTrue(configuration.publishConfig(KEY, CONTENT));
+ assertTrue(configuration.publishConfig(KEY, CONTENT));
+ assertEquals(CONTENT, configuration.getConfig(KEY));
+ assertTrue(configuration.getConfigs(null).size() > 0);
+ }
+
+ @Test
+ public void testPublishAndRemoveConfig() throws InterruptedException {
+ assertTrue(configuration.publishConfig(KEY, CONTENT));
+ configuration.addListener(KEY, event -> {
+ System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
+
+ });
+ assertTrue(configuration.publishConfig(KEY, CONTENT));
+ assertEquals(CONTENT, configuration.removeConfig(KEY));
+ Thread.sleep(configuration.getDelay() * 1000);
+ }
+
+ @Test
+ public void testGetConfigsAndGroups() {
+ assertTrue(configuration.publishConfig(KEY, CONTENT));
+ assertEquals(singleton(KEY), configuration.getConfigKeys(DEFAULT_GROUP));
+ assertEquals(singleton(DEFAULT_GROUP), configuration.getConfigGroups());
+
+ assertTrue(configuration.publishConfig(KEY, "test", CONTENT));
+ assertEquals(singleton(KEY), configuration.getConfigKeys(DEFAULT_GROUP));
+ assertTrue(configuration.getConfigGroups().contains(DEFAULT_GROUP));
+ assertTrue(configuration.getConfigGroups().contains("test"));
+ }
+
+ @Test
+ public void testAddAndRemoveListener() throws InterruptedException {
+
+ configuration.publishConfig(KEY, "A");
+
+ AtomicBoolean processedEvent = new AtomicBoolean();
+
+ configuration.addListener(KEY, event -> {
+
+ processedEvent.set(true);
+ assertEquals(KEY, event.getKey());
+ System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
+ });
+
+
+ configuration.publishConfig(KEY, "B");
+ while (!processedEvent.get()) {
+ Thread.sleep(1 * 1000L);
+ }
+
+ processedEvent.set(false);
+ configuration.publishConfig(KEY, "C");
+ while (!processedEvent.get()) {
+ Thread.sleep(1 * 1000L);
+ }
+
+ processedEvent.set(false);
+ configuration.publishConfig(KEY, "D");
+ while (!processedEvent.get()) {
+ Thread.sleep(1 * 1000L);
+ }
+
+ configuration.addListener("test", "test", event -> {
+ processedEvent.set(true);
+ assertEquals("test", event.getKey());
+ System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
+ });
+ processedEvent.set(false);
+ configuration.publishConfig("test", "test", "TEST");
+ while (!processedEvent.get()) {
+ Thread.sleep(1 * 1000L);
+ }
+
+ configuration.publishConfig("test", "test", "TEST");
+ configuration.publishConfig("test", "test", "TEST");
+ configuration.publishConfig("test", "test", "TEST");
+
+
+ processedEvent.set(false);
+ File keyFile = configuration.configFile(KEY, DEFAULT_GROUP);
+ FileUtils.deleteQuietly(keyFile);
+ while (!processedEvent.get()) {
+ Thread.sleep(1 * 1000L);
+ }
+ }
+}
diff --git a/dubbo-common/src/test/resources/log4j.xml b/dubbo-common/src/test/resources/log4j.xml
index bfb523c..21ea447 100644
--- a/dubbo-common/src/test/resources/log4j.xml
+++ b/dubbo-common/src/test/resources/log4j.xml
@@ -21,14 +21,14 @@
<!-- 以下是appender的定义 -->
<!-- ===================================================================== -->
<appender name="dubbo" class="org.apache.dubbo.common.utils.DubboAppender">
- <param name="File" value="../dubbo.log"/>
+ <param name="File" value="${user.dir}/dubbo.log"/>
<param name="encoding" value="GBK"/>
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d %p [%c:%M] - %m%n"/>
</layout>
</appender>
<root>
- <level value="INFO"/>
+ <level value="DEBUG"/>
<appender-ref ref="dubbo"/>
</root>
</log4j:configuration>
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
index 1ad15ec..874e38b 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
@@ -255,7 +255,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
/**
- *
* Load the registry and conversion it to {@link URL}, the priority order is: system property > dubbo registry config
*
* @param provider whether it is the provider side
@@ -298,7 +297,6 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
}
/**
- *
* Load the monitor config from the system properties and conversation it to {@link URL}
*
* @param registryURL
@@ -358,7 +356,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
* methods configured in the configuration file are included in the interface of remote service
*
* @param interfaceClass the interface of remote service
- * @param methods the methods configured
+ * @param methods the methods configured
*/
protected void checkInterfaceAndMethods(Class<?> interfaceClass, List<MethodConfig> methods) {
// interface cannot be null
@@ -466,15 +464,14 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
private void convertRegistryIdsToRegistries() {
if (StringUtils.isEmpty(registryIds)) {
if (CollectionUtils.isEmpty(registries)) {
- setRegistries(
- ConfigManager.getInstance().getDefaultRegistries()
- .filter(CollectionUtils::isNotEmpty)
- .orElseGet(() -> {
- RegistryConfig registryConfig = new RegistryConfig();
- registryConfig.refresh();
- return Arrays.asList(registryConfig);
- })
- );
+ List<RegistryConfig> registryConfigs = ConfigManager.getInstance().getDefaultRegistries();
+ if (registryConfigs.isEmpty()) {
+ registryConfigs = new ArrayList<>();
+ RegistryConfig registryConfig = new RegistryConfig();
+ registryConfig.refresh();
+ registryConfigs.add(registryConfig);
+ }
+ setRegistries(registryConfigs);
}
} else {
String[] ids = COMMA_SPLIT_PATTERN.split(registryIds);
@@ -668,7 +665,7 @@ public abstract class AbstractInterfaceConfig extends AbstractMethodConfig {
@SuppressWarnings({"unchecked"})
public void setRegistries(List<? extends RegistryConfig> registries) {
- ConfigManager.getInstance().addRegistries((List<RegistryConfig>) registries, false);
+ ConfigManager.getInstance().addRegistries((List<RegistryConfig>) registries);
this.registries = (List<RegistryConfig>) registries;
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
index c9a96cb..a5196df 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/RegistryConfig.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.config;
+import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.remoting.Constants;
@@ -179,9 +180,14 @@ public class RegistryConfig extends AbstractConfig {
public void setAddress(String address) {
this.address = address;
if (address != null) {
- int i = address.indexOf("://");
- if (i > 0) {
- this.updateIdIfAbsent(address.substring(0, i));
+ try {
+ URL url = URL.valueOf(address);
+ setUsername(url.getUsername());
+ setPassword(url.getPassword());
+ setProtocol(url.getProtocol());
+ setPort(url.getPort());
+ setParameters(url.getParameters());
+ } catch (Exception ignored) {
}
}
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index fb9d247..c851ca1 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -882,15 +882,14 @@ public class ServiceConfig<T> extends AbstractServiceConfig {
private void convertProtocolIdsToProtocols() {
if (StringUtils.isEmpty(protocolIds)) {
if (CollectionUtils.isEmpty(protocols)) {
- setProtocols(
- ConfigManager.getInstance().getDefaultProtocols()
- .filter(CollectionUtils::isNotEmpty)
- .orElseGet(() -> {
- ProtocolConfig protocolConfig = new ProtocolConfig();
- protocolConfig.refresh();
- return new ArrayList<>(Arrays.asList(protocolConfig));
- })
- );
+ List<ProtocolConfig> protocolConfigs = ConfigManager.getInstance().getDefaultProtocols();
+ if (protocolConfigs.isEmpty()) {
+ protocolConfigs = new ArrayList<>(1);
+ ProtocolConfig protocolConfig = new ProtocolConfig();
+ protocolConfig.refresh();
+ protocolConfigs.add(protocolConfig);
+ }
+ setProtocols(protocolConfigs);
}
} else {
String[] arr = COMMA_SPLIT_PATTERN.split(protocolIds);
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/AbstractBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/AbstractBuilder.java
index 12d09bf..1f51f1b 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/AbstractBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/builders/AbstractBuilder.java
@@ -36,7 +36,7 @@ public abstract class AbstractBuilder<C extends AbstractConfig, B extends Abstra
protected String id;
protected String prefix;
- protected B id(String id) {
+ public B id(String id) {
this.id = id;
return getThis();
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
index 718d425..1888819 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
@@ -19,8 +19,6 @@ package org.apache.dubbo.config.context;
import org.apache.dubbo.common.config.Environment;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
@@ -34,16 +32,24 @@ import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.ServiceConfig;
-import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.locks.StampedLock;
import java.util.stream.Collectors;
+import static java.lang.Boolean.TRUE;
+import static java.util.Collections.unmodifiableSet;
+import static java.util.Optional.ofNullable;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
+import static org.apache.dubbo.common.utils.ReflectUtils.getProperty;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX;
import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
@@ -82,40 +88,34 @@ import static org.apache.dubbo.config.Constants.REGISTRIES_SUFFIX;
* All workflow internally can rely on ConfigManager.
*/
public class ConfigManager {
- private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
- private static final ConfigManager CONFIG_MANAGER = new ConfigManager();
- private ApplicationConfig application;
- private MonitorConfig monitor;
- private ModuleConfig module;
+ private static final Logger logger = LoggerFactory.getLogger(ConfigManager.class);
- private Map<String, ProtocolConfig> protocols = new ConcurrentHashMap<>();
- private Map<String, RegistryConfig> registries = new ConcurrentHashMap<>();
- private Map<String, ProviderConfig> providers = new ConcurrentHashMap<>();
- private Map<String, ConsumerConfig> consumers = new ConcurrentHashMap<>();
+ private static final ConfigManager CONFIG_MANAGER = new ConfigManager();
- private List<ProtocolConfig> defaultProtocols = new ArrayList<>();
- private List<RegistryConfig> defaultRegistries = new ArrayList<>();
+ private volatile ModuleConfig module;
+ private volatile ApplicationConfig application;
+ private volatile MonitorConfig monitor;
- private Set<ConfigCenterConfig> configCenters = new HashSet<>();
- private Set<MetadataReportConfig> metadataConfigs = new HashSet<>();
- private Set<String> registryIds = new HashSet<>();
- private Set<String> protocolIds = new HashSet<>();
+ private final Map<String, ProtocolConfig> protocols = new ConcurrentHashMap<>();
+ private final Map<String, RegistryConfig> registries = new ConcurrentHashMap<>();
+ private final Map<String, ProviderConfig> providers = new ConcurrentHashMap<>();
+ private final Map<String, ConsumerConfig> consumers = new ConcurrentHashMap<>();
+ private final Map<String, ConfigCenterConfig> configCenters = new ConcurrentHashMap<>();
+ private final Map<String, MetadataReportConfig> metadataConfigs = new ConcurrentHashMap<>();
+ private final Map<String, ServiceConfig<?>> serviceConfigs = new ConcurrentHashMap<>();
+ private final Map<String, ReferenceConfig<?>> referenceConfigs = new ConcurrentHashMap<>();
- private List<ServiceConfig<?>> serviceConfigs = new ArrayList<>();
- private List<ReferenceConfig<?>> referenceConfigs = new ArrayList<>();
+ private final StampedLock lock = new StampedLock();
public static ConfigManager getInstance() {
return CONFIG_MANAGER;
}
private ConfigManager() {
-
}
- public Optional<ApplicationConfig> getApplication() {
- return Optional.ofNullable(application);
- }
+ // ApplicationConfig correlative methods
public void setApplication(ApplicationConfig application) {
if (application != null) {
@@ -124,10 +124,12 @@ public class ConfigManager {
}
}
- public Optional<MonitorConfig> getMonitor() {
- return Optional.ofNullable(monitor);
+ public Optional<ApplicationConfig> getApplication() {
+ return ofNullable(application);
}
+ // MonitorConfig correlative methods
+
public void setMonitor(MonitorConfig monitor) {
if (monitor != null) {
checkDuplicate(this.monitor, monitor);
@@ -135,10 +137,12 @@ public class ConfigManager {
}
}
- public Optional<ModuleConfig> getModule() {
- return Optional.ofNullable(module);
+ public Optional<MonitorConfig> getMonitor() {
+ return ofNullable(monitor);
}
+ // ModuleConfig correlative methods
+
public void setModule(ModuleConfig module) {
if (module != null) {
checkDuplicate(this.module, module);
@@ -146,210 +150,175 @@ public class ConfigManager {
}
}
- public Set<ConfigCenterConfig> getConfigCenters() {
- return configCenters;
+ public Optional<ModuleConfig> getModule() {
+ return ofNullable(module);
}
+ // ConfigCenterConfig correlative methods
+
public void addConfigCenter(ConfigCenterConfig configCenter) {
- if (configCenter != null && !configCenters.contains(configCenter)) {
- this.configCenters.add(configCenter);
- }
+ addIfAbsent(configCenter, configCenters);
}
- public void addConfigCenter(List<ConfigCenterConfig> configCenters) {
- if (CollectionUtils.isNotEmpty(configCenters)) {
- this.configCenters.addAll(configCenters);
- }
+ public void addConfigCenters(Iterable<ConfigCenterConfig> configCenters) {
+ configCenters.forEach(this::addConfigCenter);
+ }
+
+ public ConfigCenterConfig getConfigCenter(String id) {
+ return configCenters.get(id);
}
- public Set<MetadataReportConfig> getMetadataConfigs() {
- return metadataConfigs;
+ public Collection<ConfigCenterConfig> getConfigCenters() {
+ return configCenters.values();
}
+ // MetadataReportConfig correlative methods
+
public void addMetadataReport(MetadataReportConfig metadataReportConfig) {
- if (metadataReportConfig != null && !metadataConfigs.contains(metadataReportConfig)) {
- this.metadataConfigs.add(metadataReportConfig);
- }
+ addIfAbsent(metadataReportConfig, metadataConfigs);
}
- public void addMetadataReport(List<MetadataReportConfig> metadataReportConfigs) {
- if (CollectionUtils.isNotEmpty(metadataReportConfigs)) {
- this.metadataConfigs.addAll(metadataReportConfigs);
- }
+ public void addMetadataReports(Iterable<MetadataReportConfig> metadataReportConfigs) {
+ metadataReportConfigs.forEach(this::addMetadataReport);
+ }
+
+ public Collection<MetadataReportConfig> getMetadataConfigs() {
+ return metadataConfigs.values();
+ }
+
+ // MetadataReportConfig correlative methods
+
+ public void addProvider(ProviderConfig providerConfig) {
+ addIfAbsent(providerConfig, providers);
}
public Optional<ProviderConfig> getProvider(String id) {
- return Optional.ofNullable(providers.get(id));
+ return ofNullable(providers.get(id));
}
public Optional<ProviderConfig> getDefaultProvider() {
- return Optional.ofNullable(providers.get(DEFAULT_KEY));
+ return getProvider(DEFAULT_KEY);
}
- public void addProvider(ProviderConfig providerConfig) {
- if (providerConfig == null) {
- return;
- }
+ public Collection<ProviderConfig> getProviders() {
+ return providers.values();
+ }
- String key = StringUtils.isNotEmpty(providerConfig.getId())
- ? providerConfig.getId()
- : (providerConfig.isDefault() == null || providerConfig.isDefault()) ? DEFAULT_KEY : null;
+ // ConsumerConfig correlative methods
- if (StringUtils.isEmpty(key)) {
- throw new IllegalStateException("A ProviderConfig should either has an id or it's the default one, " + providerConfig);
- }
-
- if (providers.containsKey(key) && !providerConfig.equals(providers.get(key))) {
- logger.warn("Duplicate ProviderConfig found, there already has one default ProviderConfig or more than two ProviderConfigs have the same id, " +
- "you can try to give each ProviderConfig a different id. " + providerConfig);
- } else {
- providers.put(key, providerConfig);
- }
+ public void addConsumer(ConsumerConfig consumerConfig) {
+ addIfAbsent(consumerConfig, consumers);
}
public Optional<ConsumerConfig> getConsumer(String id) {
- return Optional.ofNullable(consumers.get(id));
+ return ofNullable(consumers.get(id));
}
public Optional<ConsumerConfig> getDefaultConsumer() {
- return Optional.ofNullable(consumers.get(DEFAULT_KEY));
+ return getConsumer(DEFAULT_KEY);
}
- public void addConsumer(ConsumerConfig consumerConfig) {
- if (consumerConfig == null) {
- return;
- }
+ public Collection<ConsumerConfig> getConsumers() {
+ return consumers.values();
+ }
- String key = StringUtils.isNotEmpty(consumerConfig.getId())
- ? consumerConfig.getId()
- : (consumerConfig.isDefault() == null || consumerConfig.isDefault()) ? DEFAULT_KEY : null;
+ // ProtocolConfig correlative methods
- if (StringUtils.isEmpty(key)) {
- throw new IllegalStateException("A ConsumerConfig should either has an id or it's the default one, " + consumerConfig);
- }
+ public void addProtocol(ProtocolConfig protocolConfig) {
+ addIfAbsent(protocolConfig, protocols);
+ }
- if (consumers.containsKey(key) && !consumerConfig.equals(consumers.get(key))) {
- logger.warn("Duplicate ConsumerConfig found, there already has one default ConsumerConfig or more than two ConsumerConfigs have the same id, " +
- "you can try to give each ConsumerConfig a different id. " + consumerConfig);
- } else {
- consumers.put(key, consumerConfig);
+ public void addProtocols(Iterable<ProtocolConfig> protocolConfigs, boolean canBeDefault) {
+ if (protocolConfigs != null) {
+ protocolConfigs.forEach(this::addProtocol);
}
}
public Optional<ProtocolConfig> getProtocol(String id) {
- return Optional.ofNullable(protocols.get(id));
+ return ofNullable(protocols.get(id));
}
- public Optional<List<ProtocolConfig>> getDefaultProtocols() {
- return Optional.of(defaultProtocols);
+ public List<ProtocolConfig> getDefaultProtocols() {
+ return getDefaultConfigs(protocols);
}
- public void addProtocols(List<ProtocolConfig> protocolConfigs, boolean canBeDefault) {
- if (protocolConfigs != null) {
- protocolConfigs.forEach(pc -> this.addProtocol(pc, canBeDefault));
- }
+ public Collection<ProtocolConfig> getProtocols() {
+ return protocols.values();
}
- public void addProtocol(ProtocolConfig protocolConfig, boolean canBeDefault) {
- if (protocolConfig == null) {
- return;
- }
+ public Set<String> getProtocolIds() {
+ Set<String> protocolIds = new HashSet<>();
+ protocolIds.addAll(getSubProperties(Environment.getInstance()
+ .getExternalConfigurationMap(), PROTOCOLS_SUFFIX));
+ protocolIds.addAll(getSubProperties(Environment.getInstance()
+ .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX));
- // if isDefault is not false and a ProtocolConfig is not specified being false.
- if (canBeDefault && (protocolConfig.isDefault() == null || protocolConfig.isDefault())) {
- this.defaultProtocols.add(protocolConfig);
- }
+ protocolIds.addAll(protocols.keySet());
+ return unmodifiableSet(protocolIds);
+ }
- String key = StringUtils.isNotEmpty(protocolConfig.getId())
- ? protocolConfig.getId()
- : DEFAULT_KEY;
- if (StringUtils.isEmpty(key)) {
- throw new IllegalStateException("A ProtocolConfig should either has an id or it's the default one, " + protocolConfig);
- }
+ // RegistryConfig correlative methods
- if (protocols.containsKey(key) && !protocolConfig.equals(protocols.get(key))) {
- logger.warn("Duplicate ProtocolConfig found, there already has one default ProtocolConfig or more than two ProtocolConfigs have the same id, " +
- "you can try to give each ProtocolConfig a different id. " + protocolConfig);
- } else {
- protocols.put(key, protocolConfig);
+ public void addRegistry(RegistryConfig registryConfig) {
+ addIfAbsent(registryConfig, registries);
+ }
+
+ public void addRegistries(Iterable<RegistryConfig> registryConfigs) {
+ if (registryConfigs != null) {
+ registryConfigs.forEach(this::addRegistry);
}
}
public Optional<RegistryConfig> getRegistry(String id) {
- return Optional.ofNullable(registries.get(id));
+ return ofNullable(registries.get(id));
}
- public Optional<List<RegistryConfig>> getDefaultRegistries() {
- return Optional.of(defaultRegistries);
+ public List<RegistryConfig> getDefaultRegistries() {
+ return getDefaultConfigs(registries);
}
- public void addRegistries(List<RegistryConfig> registryConfigs, boolean canBeDefault) {
- if (registryConfigs != null) {
- registryConfigs.forEach(rc -> this.addRegistry(rc, canBeDefault));
- }
+ public Collection<RegistryConfig> getRegistries() {
+ return registries.values();
}
- public void addRegistry(RegistryConfig registryConfig, boolean canBeDefault) {
- if (registryConfig == null) {
- return;
- }
+ public Set<String> getRegistryIds() {
+ Set<String> registryIds = new HashSet<>();
+ registryIds.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(),
+ REGISTRIES_SUFFIX));
+ registryIds.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(),
+ REGISTRIES_SUFFIX));
- if (canBeDefault && (registryConfig.isDefault() == null || registryConfig.isDefault())) {
- this.defaultRegistries.add(registryConfig);
- }
- String key = StringUtils.isNotEmpty(registryConfig.getId())
- ? registryConfig.getId()
- : DEFAULT_KEY;
+ registryIds.addAll(registries.keySet());
+ return unmodifiableSet(registryIds);
+ }
- if (StringUtils.isEmpty(key)) {
- throw new IllegalStateException("A RegistryConfig should either has an id or it's the default one, " + registryConfig);
- }
+ // ServiceConfig correlative methods
- if (registries.containsKey(key) && !registryConfig.equals(registries.get(key))) {
- logger.warn("Duplicate RegistryConfig found, there already has one default RegistryConfig or more than two RegistryConfigs have the same id, " +
- "you can try to give each RegistryConfig a different id. " + registryConfig);
- } else {
- registries.put(key, registryConfig);
- }
+ public void addService(ServiceConfig<?> serviceConfig) {
+ addIfAbsent(serviceConfig, serviceConfigs);
}
- public void addProtocolIds(List<String> protocolIds) {
- this.protocolIds.addAll(protocolIds);
+ public Collection<ServiceConfig<?>> getServiceConfigs() {
+ return serviceConfigs.values();
}
- public void addRegistryIds(List<String> registryIds) {
- this.registryIds.addAll(registryIds);
+ public <T> ServiceConfig<T> getServiceConfig(String id) {
+ return (ServiceConfig<T>) serviceConfigs.get(id);
}
- public void addService(ServiceConfig<?> serviceConfig) {
- this.serviceConfigs.add(serviceConfig);
- }
+ // ReferenceConfig correlative methods
public void addReference(ReferenceConfig<?> referenceConfig) {
- this.referenceConfigs.add(referenceConfig);
+ addIfAbsent(referenceConfig, referenceConfigs);
}
- public Set<String> getRegistryIds() {
- Set<String> configedRegistries = new HashSet<>();
- configedRegistries.addAll(getSubProperties(Environment.getInstance().getExternalConfigurationMap(),
- REGISTRIES_SUFFIX));
- configedRegistries.addAll(getSubProperties(Environment.getInstance().getAppExternalConfigurationMap(),
- REGISTRIES_SUFFIX));
-
- configedRegistries.addAll(registryIds);
- return configedRegistries;
+ public Collection<ReferenceConfig<?>> getReferenceConfigs() {
+ return referenceConfigs.values();
}
- public Set<String> getProtocolIds() {
- Set<String> configedProtocols = new HashSet<>();
- configedProtocols.addAll(getSubProperties(Environment.getInstance()
- .getExternalConfigurationMap(), PROTOCOLS_SUFFIX));
- configedProtocols.addAll(getSubProperties(Environment.getInstance()
- .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX));
-
- configedProtocols.addAll(protocolIds);
- return configedProtocols;
+ public <T> ReferenceConfig<T> getReferenceConfig(String id) {
+ return (ReferenceConfig<T>) referenceConfigs.get(id);
}
protected static Set<String> getSubProperties(Map<String, String> properties, String prefix) {
@@ -359,62 +328,130 @@ public class ConfigManager {
}).collect(Collectors.toSet());
}
- public Map<String, ProtocolConfig> getProtocols() {
- return protocols;
- }
+ public void refreshAll() {
+ write(() -> {
+ // refresh all configs here,
+ getApplication().ifPresent(ApplicationConfig::refresh);
+ getMonitor().ifPresent(MonitorConfig::refresh);
+ getModule().ifPresent(ModuleConfig::refresh);
- public Map<String, RegistryConfig> getRegistries() {
- return registries;
- }
+ getProtocols().forEach(ProtocolConfig::refresh);
+ getRegistries().forEach(RegistryConfig::refresh);
+ getProviders().forEach(ProviderConfig::refresh);
+ getConsumers().forEach(ConsumerConfig::refresh);
+ });
- public Map<String, ProviderConfig> getProviders() {
- return providers;
}
- public Map<String, ConsumerConfig> getConsumers() {
- return consumers;
- }
- public List<ServiceConfig<?>> getServiceConfigs() {
- return serviceConfigs;
+ // For test purpose
+ public void clear() {
+ write(() -> {
+ this.application = null;
+ this.monitor = null;
+ this.module = null;
+ this.registries.clear();
+ this.protocols.clear();
+ this.providers.clear();
+ this.consumers.clear();
+ this.configCenters.clear();
+ this.metadataConfigs.clear();
+ });
+ }
+
+ private <V> V write(Callable<V> callable) {
+ V value = null;
+ long stamp = lock.writeLock();
+ try {
+ value = callable.call();
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ } finally {
+ lock.unlockWrite(stamp);
+ }
+ return value;
}
- public List<ReferenceConfig<?>> getReferenceConfigs() {
- return referenceConfigs;
+ private void write(Runnable runnable) {
+ write(() -> {
+ runnable.run();
+ return null;
+ });
}
- public void refreshAll() {
- // refresh all configs here,
- getApplication().ifPresent(ApplicationConfig::refresh);
- getMonitor().ifPresent(MonitorConfig::refresh);
- getModule().ifPresent(ModuleConfig::refresh);
- getProtocols().values().forEach(ProtocolConfig::refresh);
- getRegistries().values().forEach(RegistryConfig::refresh);
- getProviders().values().forEach(ProviderConfig::refresh);
- getConsumers().values().forEach(ConsumerConfig::refresh);
+ private <V> V read(Callable<V> callable) {
+ long stamp = lock.tryOptimisticRead();
+
+ boolean readLock = false;
+
+ V value = null;
+
+ try {
+ readLock = !lock.validate(stamp);
+
+ if (readLock) {
+ stamp = lock.readLock();
+ }
+ value = callable.call();
+ } catch (Throwable e) {
+ throw new RuntimeException(e);
+ } finally {
+ if (readLock) {
+ lock.unlockRead(stamp);
+ }
+ }
+
+ return value;
}
- private void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) {
+ private static void checkDuplicate(AbstractConfig oldOne, AbstractConfig newOne) {
if (oldOne != null && !oldOne.equals(newOne)) {
String configName = oldOne.getClass().getSimpleName();
throw new IllegalStateException("Duplicate Config found for " + configName + ", you should use only one unique " + configName + " for one application.");
}
}
- // For test purpose
- public void clear() {
- this.application = null;
- this.monitor = null;
- this.module = null;
- this.registries.clear();
- this.protocols.clear();
- this.providers.clear();
- this.consumers.clear();
- this.configCenters.clear();
- this.metadataConfigs.clear();
- this.registryIds.clear();
- this.protocolIds.clear();
+ private static Map<Class<? extends AbstractConfig>, Map<String, ? extends AbstractConfig>> newMap() {
+ return new HashMap<>();
+ }
+
+ private static <C extends AbstractConfig> void addIfAbsent(C config, Map<String, C> configsMap) {
+
+ if (config == null) {
+ return;
+ }
+
+ String key = getId(config);
+
+ C existedConfig = configsMap.get(key);
+
+ if (existedConfig != null && !config.equals(existedConfig)) {
+ if (logger.isWarnEnabled()) {
+ String type = config.getClass().getSimpleName();
+ logger.warn(String.format("Duplicate %s found, there already has one default %s or more than two %ss have the same id, " +
+ "you can try to give each %s a different id : %s", type, type, type, type, config));
+ }
+ } else {
+ configsMap.put(key, config);
+ }
+ }
+
+ static <C extends AbstractConfig> String getId(C config) {
+ String id = config.getId();
+ return isNotEmpty(id) ? id : isDefaultConfig(config) ?
+ config.getClass().getSimpleName() + "#" + DEFAULT_KEY : null;
}
+ static <C extends AbstractConfig> boolean isDefaultConfig(C config) {
+ Boolean isDefault = getProperty(config, "default");
+ return isDefault == null || TRUE.equals(isDefault);
+ }
+
+ static <C extends AbstractConfig> List<C> getDefaultConfigs(Map<String, C> configsMap) {
+ return configsMap.values()
+ .stream()
+ .filter(ConfigManager::isDefaultConfig)
+ .collect(Collectors.toList());
+ }
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstancePortCustomizer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstancePortCustomizer.java
index 37e9b3c..25c4d20 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstancePortCustomizer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ServiceInstancePortCustomizer.java
@@ -38,7 +38,6 @@ public class ServiceInstancePortCustomizer implements ServiceInstanceCustomizer
ConfigManager.getInstance()
.getProtocols()
- .values()
.stream()
.findFirst()
.ifPresent(protocolConfig -> {
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
new file mode 100644
index 0000000..44e896d
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.config.context;
+
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.ModuleConfig;
+import org.apache.dubbo.config.MonitorConfig;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.dubbo.config.context.ConfigManager.getInstance;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link ConfigManager} Test
+ *
+ * @since 2.7.4
+ */
+public class ConfigManagerTest {
+
+ private ConfigManager configManager = getInstance();
+
+ @BeforeEach
+ public void init() {
+ configManager.clear();
+ assertFalse(configManager.getApplication().isPresent());
+ assertFalse(configManager.getMonitor().isPresent());
+ assertFalse(configManager.getMonitor().isPresent());
+ }
+
+ @Test
+ public void testApplicationConfig() {
+ ApplicationConfig applicationConfig = new ApplicationConfig();
+ configManager.setApplication(applicationConfig);
+ assertTrue(configManager.getApplication().isPresent());
+ assertEquals(applicationConfig, configManager.getApplication().get());
+ }
+
+ @Test
+ public void testMonitorConfig() {
+ MonitorConfig monitorConfig = new MonitorConfig();
+ configManager.setMonitor(monitorConfig);
+ assertTrue(configManager.getMonitor().isPresent());
+ assertEquals(monitorConfig, configManager.getMonitor().get());
+ }
+
+ @Test
+ public void tesModuleConfig() {
+ ModuleConfig config = new ModuleConfig();
+ configManager.setModule(config);
+ assertTrue(configManager.getModule().isPresent());
+ assertEquals(config, configManager.getModule().get());
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
index e7db07d..43331e9 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporterTest.java
@@ -49,9 +49,9 @@ public class ConfigurableMetadataServiceExporterTest {
configManager.setApplication(applicationConfig);
// Add ProtocolConfig
- configManager.addProtocol(protocolConfig(), true);
+ configManager.addProtocol(protocolConfig());
// Add RegistryConfig
- configManager.addRegistry(registryConfig(), true);
+ configManager.addRegistry(registryConfig());
}
private static ProtocolConfig protocolConfig() {
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-provider.xml b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-provider.xml
index f7064cd..3e56228 100644
--- a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-provider.xml
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/dubbo-provider.xml
@@ -21,8 +21,22 @@
http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
">
+ <bean id="a" class="java.lang.String" abstract="true">
+ <property name="value" value="1" />
+ </bean>
+
+ <bean id="b" parent="a" >
+ <property name="value2" value="2" />
+ </bean>
+
+ <bean id="c" class="java.lang.Object">
+ <property name="b" ref="b" />
+ </bean>
+
<!-- 当前应用信息配置 -->
- <dubbo:application name="dubbo-spring-test"/>
+ <dubbo:application name="dubbo-spring-test" >
+ <dubbo:parameter key="" value="" />
+ </dubbo:application>
<!-- 连接注册中心配置 -->
<dubbo:registry address="N/A"/>
diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
index 8c827a3..6bcafcd 100644
--- a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
@@ -94,12 +94,19 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
}
public void publishNacosConfig(String key, String value) {
+ String[] keyAndGroup = getKeyAndGroup(key);
+ publishConfig(keyAndGroup[0], keyAndGroup[1], value);
+ }
+
+ @Override
+ public boolean publishConfig(String key, String group, String content) {
+ boolean published = false;
try {
- String[] keyAndGroup = getKeyAndGroup(key);
- configService.publishConfig(keyAndGroup[0], keyAndGroup[1], value);
+ published = configService.publishConfig(key, group, content);
} catch (NacosException e) {
logger.error(e.getErrMsg());
}
+ return published;
}
private String[] getKeyAndGroup(String key) {
@@ -107,7 +114,7 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
if (i < 0) {
return new String[]{key, null};
} else {
- return new String[]{key.substring(0, i), key.substring(i+1)};
+ return new String[]{key.substring(0, i), key.substring(i + 1)};
}
}
diff --git a/dubbo-dependencies-bom/pom.xml b/dubbo-dependencies-bom/pom.xml
index d6cf69e..27e284f 100644
--- a/dubbo-dependencies-bom/pom.xml
+++ b/dubbo-dependencies-bom/pom.xml
@@ -15,14 +15,15 @@
limitations under the License.
-->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache</groupId>
<artifactId>apache</artifactId>
<version>21</version>
- <relativePath />
+ <relativePath/>
</parent>
<groupId>org.apache.dubbo</groupId>
@@ -135,6 +136,7 @@
<log4j_version>1.2.16</log4j_version>
<logback_version>1.2.2</logback_version>
<log4j2_version>2.11.1</log4j2_version>
+ <commons_io_version>2.6</commons_io_version>
<embedded_redis_version>0.6</embedded_redis_version>
@@ -443,6 +445,11 @@
<version>${jcl_version}</version>
</dependency>
<dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>${commons_io_version}</version>
+ </dependency>
+ <dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>${log4j_version}</version>
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java
new file mode 100644
index 0000000..1dbf90d
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/FileSystemServiceDiscovery.java
@@ -0,0 +1,114 @@
+/*
+ * 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.registry.client;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
+import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration;
+import org.apache.dubbo.event.EventListener;
+import org.apache.dubbo.registry.client.event.ServiceInstancesChangedEvent;
+import org.apache.dubbo.registry.client.event.listener.ServiceInstancesChangedListener;
+
+import java.util.Set;
+
+import static com.alibaba.fastjson.JSON.toJSONString;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+
+/**
+ * File System {@link ServiceDiscovery} implementation
+ *
+ * @see FileSystemDynamicConfiguration
+ * @since 2.7.4
+ */
+public class FileSystemServiceDiscovery implements ServiceDiscovery, EventListener<ServiceInstancesChangedEvent> {
+
+ private final URL connectionURL;
+
+ private FileSystemDynamicConfiguration dynamicConfiguration;
+
+ public FileSystemServiceDiscovery(URL connectionURL) {
+ this.connectionURL = connectionURL;
+ }
+
+ @Override
+ public void onEvent(ServiceInstancesChangedEvent event) {
+
+ }
+
+ @Override
+ public void start() {
+ if (dynamicConfiguration == null) {
+ dynamicConfiguration = createDynamicConfiguration(connectionURL);
+ }
+ }
+
+ @Override
+ public void stop() {
+ try {
+ if (dynamicConfiguration != null) {
+ dynamicConfiguration.close();
+ }
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private String getConfigKey(ServiceInstance serviceInstance) {
+ return serviceInstance.getId();
+ }
+
+ private String getConfigGroup(ServiceInstance serviceInstance) {
+ return serviceInstance.getServiceName();
+ }
+
+ @Override
+ public void register(ServiceInstance serviceInstance) throws RuntimeException {
+ String key = getConfigKey(serviceInstance);
+ String group = getConfigGroup(serviceInstance);
+ String content = toJSONString(serviceInstance);
+ dynamicConfiguration.publishConfig(key, group, content);
+ }
+
+ @Override
+ public void update(ServiceInstance serviceInstance) throws RuntimeException {
+ register(serviceInstance);
+ }
+
+ @Override
+ public void unregister(ServiceInstance serviceInstance) throws RuntimeException {
+ String key = getConfigKey(serviceInstance);
+ String group = getConfigGroup(serviceInstance);
+ dynamicConfiguration.removeConfig(key, group);
+ }
+
+ @Override
+ public Set<String> getServices() {
+ return null;
+ }
+
+ @Override
+ public void addServiceInstancesChangedListener(String serviceName, ServiceInstancesChangedListener listener) throws
+ NullPointerException, IllegalArgumentException {
+
+ }
+
+ private static FileSystemDynamicConfiguration createDynamicConfiguration(URL connectionURL) {
+ String protocol = connectionURL.getProtocol();
+ DynamicConfigurationFactory factory = getExtensionLoader(DynamicConfigurationFactory.class).getExtension(protocol);
+ return (FileSystemDynamicConfiguration) factory.getDynamicConfiguration(connectionURL);
+ }
+}