You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by al...@apache.org on 2023/09/10 12:56:17 UTC
[dubbo] branch 3.3-config-api-refactor updated: Split DefaultConfigValidator to SPI implements (#12948)
This is an automated email from the ASF dual-hosted git repository.
albumenj pushed a commit to branch 3.3-config-api-refactor
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/3.3-config-api-refactor by this push:
new 98e7313e71 Split DefaultConfigValidator to SPI implements (#12948)
98e7313e71 is described below
commit 98e7313e71fab2d24103956ee3befc7b13ebdd92
Author: namelessssssssssss <10...@users.noreply.github.com>
AuthorDate: Sun Sep 10 20:56:10 2023 +0800
Split DefaultConfigValidator to SPI implements (#12948)
* * Simplify responsibilities of ConfigValidationUtils
* * Update validators
* * Bug fix
* * Bug fix
* Add ut
* * Add license
* * Rename folder
* * Fix pom & name
* * Code style fix
* * Bug fix
* * Bug fix
* * Update validator init process
* * Refactor ConfigValidateFacade init method
* * Bug fix
* Add license
* * Fix test
* * Fix ut
* * Update ConfigValidateFacade init process
* * Bug fix
* * Bug fix
* * Bug fix
* * Doc fix
* * Bug fix
* * Bug fix
* * Bug fix
* * Bug fix
* * Bug fix
* * Test fix
* * refactor validator mapping
* * Code style fix
* * Fix conflict
* * Fix conflict
* * Remove default instance of ConfigValidateFacade
* * Remove default instance of ConfigValidateFacade
* * Add license
---
.../dubbo/common/constants/CommonConstants.java | 2 +
.../org/apache/dubbo/config/AbstractConfig.java | 7 +
.../apache/dubbo/config/ConfigValidateFacade.java | 115 ++++
.../config/context/AbstractConfigManager.java | 13 +-
.../dubbo/config/context/ConfigValidator.java | 20 +-
.../ConfigValidationException.java} | 22 +-
.../dubbo/config/utils/ConfigValidationUtils.java | 355 ++++++++++
.../validator/ApplicationConfigValidator.java | 97 +++
.../config/validator/ModuleConfigValidator.java | 49 ++
.../java/org/apache/dubbo/registry/Constants.java | 0
.../org/apache/dubbo/rpc/cluster/Constants.java | 0
...org.apache.dubbo.config.context.ConfigValidator | 2 +
.../dubbo/config/context/ConfigManagerTest.java | 2 +
.../dubbo/config/ConfigScopeModelInitializer.java | 3 -
.../org/apache/dubbo/config/ReferenceConfig.java | 6 +-
.../org/apache/dubbo/config/ServiceConfig.java | 5 +-
.../application/ApplicationLifecycle.java | 3 +
.../ConfigCenterApplicationLifecycle.java | 5 +-
.../application/MetadataInitializeLifecycle.java | 4 +-
.../ValidatorRegistryDeployListener.java | 41 ++
.../dubbo/config/utils/ConfigValidationUtils.java | 741 ---------------------
.../dubbo/config/utils/DefaultConfigValidator.java | 62 --
.../validator/ConfigCenterConfigValidator.java | 44 ++
.../config/validator/ConsumerConfigValidator.java | 25 +-
.../config/validator/InterfaceConfigValidator.java | 68 ++
.../config/validator/MethodConfigValidator.java | 63 ++
.../config/validator/ProviderConfigValidator.java | 58 ++
.../config/validator/ReferenceConfigValidator.java | 65 ++
.../config/validator/ServiceConfigValidator.java | 78 +++
...org.apache.dubbo.config.context.ConfigValidator | 8 +
...ploy.lifecycle.application.ApplicationLifecycle | 1 +
.../apache/dubbo/config/AbstractConfigTest.java | 2 +-
.../dubbo/config/ConfigValidatorExistTest.java | 94 +++
.../dubbo/config/bootstrap/DubboBootstrapTest.java | 18 +-
.../config/utils/ConfigValidationUtilsTest.java | 39 +-
dubbo-distribution/dubbo-all/pom.xml | 7 +
.../config/validator/MetadataConfigValidator.java | 64 ++
...org.apache.dubbo.config.context.ConfigValidator | 1 +
.../config/validator/MetricsConfigValidator.java | 25 +-
...org.apache.dubbo.config.context.ConfigValidator | 1 +
.../metrics/collector/DefaultCollectorTest.java | 5 +-
.../config/validator/TracingConfigValidator.java | 25 +-
...org.apache.dubbo.config.context.ConfigValidator | 1 +
.../java/org/apache/dubbo/util/MonitorUrlUtil.java | 102 +++
.../config/validator/MonitorConfigValidator.java | 53 ++
...org.apache.dubbo.config.context.ConfigValidator | 1 +
.../security/cert/CertDeployerListenerTest.java | 3 +-
.../config/validate/RegistryConfigValidator.java | 56 ++
.../dubbo/config/validator/SslConfigValidator.java | 23 +-
...org.apache.dubbo.config.context.ConfigValidator | 1 +
.../config/validator/ProtocolConfigValidator.java | 82 +++
...org.apache.dubbo.config.context.ConfigValidator | 1 +
52 files changed, 1695 insertions(+), 873 deletions(-)
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
index 3380621774..4224da82fd 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
@@ -337,6 +337,8 @@ public interface CommonConstants {
String REGISTRY_PROTOCOL_LISTENER_KEY = "registry.protocol.listener";
+ String REGISTRY_SERVICE_CLASS_NAME = "org.apache.dubbo.registry.RegistryService";
+
String DUBBO_VERSION_KEY = "dubbo";
String TAG_KEY = "dubbo.tag";
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index 75a80c8999..3c23216f09 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@ -172,6 +172,13 @@ public abstract class AbstractConfig implements Serializable {
appendParameters0(parameters, config, prefix, false);
}
+ public boolean validate() {
+ if(scopeModel == null || scopeModel.getBeanFactory() == null || scopeModel.getBeanFactory().isDestroyed()){
+ return ConfigValidateFacade.getDefaultInstance().validate(this);
+ }
+ return scopeModel.getBeanFactory().getOrRegisterBean(ConfigValidateFacade.class,clz -> new ConfigValidateFacade(scopeModel)).validate(this);
+ }
+
private static void appendParameters0(Map<String, String> parameters, Object config, String prefix, boolean asParameters) {
if (config == null) {
return;
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigValidateFacade.java b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigValidateFacade.java
new file mode 100644
index 0000000000..732ec39f30
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/ConfigValidateFacade.java
@@ -0,0 +1,115 @@
+/*
+ * 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;
+
+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.config.context.ConfigValidator;
+import org.apache.dubbo.config.exception.ConfigValidationException;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ScopeModel;
+
+import java.util.Collections;
+import java.util.List;
+
+@SuppressWarnings({"rawtypes", "unchecked"})
+public class ConfigValidateFacade implements ConfigValidator{
+
+ private static final Logger LOGGER = LoggerFactory.getErrorTypeAwareLogger(ConfigValidateFacade.class);
+
+ private final List<ConfigValidator> validators;
+
+ /**
+ * For test
+ */
+ private static boolean enableValidate = true;
+
+ public ConfigValidateFacade(ScopeModel scopeModel) {
+ if(scopeModel != null) {
+ ExtensionLoader<ConfigValidator> extensionLoader = scopeModel.getExtensionLoader(ConfigValidator.class);
+ if (extensionLoader != null) {
+ this.validators = extensionLoader.getActivateExtensions();
+ this.validators.forEach(scopeModel.getBeanFactory()::registerBean);
+ } else {
+ this.validators = Collections.emptyList();
+ }
+ }else {
+ this.validators = Collections.emptyList();
+ }
+ }
+
+ public List<ConfigValidator> getValidators() {
+ return validators;
+ }
+
+ /**
+ * Auto choose a appropriate validator to validate config.
+ *
+ * @param config the config to validate
+ * @return TRUE if pass the validation.
+ * FALSE if no ConfigValidator found for this config,
+ * or one of the supported {@link ConfigValidator#validate(AbstractConfig)} returns FALSE.
+ */
+ @Override
+ public boolean validate(AbstractConfig config) throws ConfigValidationException{
+ if(!enableValidate){
+ return true;
+ }
+ if (config == null) {
+ return false;
+ }
+ boolean validated = false;
+ try {
+ for (ConfigValidator validator : validators) {
+ if (validator.isSupport(config.getClass())) {
+ validated = true;
+ if(!validator.validate(config)){
+ return false;
+ }
+ }
+ }
+ }catch (Throwable t){
+ throw new ConfigValidationException(config.getClass().getSimpleName()+" validation failed: "+t.getMessage(),t);
+ }
+ if (!validated) {
+ LOGGER.info(config.getClass().getSimpleName()+" is not validated. This may caused by you did not imported the relevant module.");
+ }
+ return validated;
+ }
+
+ @Override
+ public boolean isSupport(Class configClass) {
+ return true;
+ }
+
+ /**
+ * For test
+ */
+ @Deprecated
+ public static ConfigValidateFacade getDefaultInstance() {
+ return ApplicationModel.defaultModel().getBeanFactory().getOrRegisterBean(ConfigValidateFacade.class);
+ }
+
+ /**
+ * For test
+ */
+ @Deprecated
+ public static void setEnableValidate(boolean enable){
+ enableValidate = enable;
+ }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/AbstractConfigManager.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/AbstractConfigManager.java
index 0f8a0e23d4..d61009799d 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/AbstractConfigManager.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/AbstractConfigManager.java
@@ -31,6 +31,7 @@ import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.config.AbstractConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigKeys;
+import org.apache.dubbo.config.ConfigValidateFacade;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.MetricsConfig;
import org.apache.dubbo.config.ModuleConfig;
@@ -585,10 +586,8 @@ public abstract class AbstractConfigManager extends LifecycleAdapter {
// validate configs
Collection<T> configs = this.getConfigs(configType);
- if (getConfigValidator() != null) {
- for (T config : configs) {
- getConfigValidator().validate(config);
- }
+ for (T config : configs) {
+ getConfigValidator().validate(config);
}
// check required default
@@ -611,11 +610,11 @@ public abstract class AbstractConfigManager extends LifecycleAdapter {
return true;
}
- private ConfigValidator getConfigValidator() {
+ private ConfigValidateFacade getConfigValidator() {
if (configValidator == null) {
- configValidator = applicationModel.getBeanFactory().getBean(ConfigValidator.class);
+ configValidator = applicationModel.getBeanFactory().getOrRegisterBean(ConfigValidateFacade.class, clz -> new ConfigValidateFacade(scopeModel));
}
- return configValidator;
+ return (ConfigValidateFacade) configValidator;
}
/**
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
index 7d20b1b658..22b630f158 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
@@ -16,10 +16,26 @@
*/
package org.apache.dubbo.config.context;
+import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.exception.ConfigValidationException;
-public interface ConfigValidator {
+/**
+ * ConfigValidator. Allow provides an optional validation logic for a {@link AbstractConfig} impl.
+ * @param <T> type of {@link AbstractConfig} implement
+ */
+@SPI
+public interface ConfigValidator<T extends AbstractConfig> {
+
+ /**
+ * Validate a config.
+ * If the config does not pass validation, returns false or throws exception, depends on implementation.
+ *
+ * @param config the config to validate
+ * @return TRUE if pass validation
+ */
+ boolean validate(T config) throws ConfigValidationException;
- void validate(AbstractConfig config);
+ boolean isSupport(Class<?> configClass);
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java b/dubbo-common/src/main/java/org/apache/dubbo/config/exception/ConfigValidationException.java
similarity index 56%
copy from dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
copy to dubbo-common/src/main/java/org/apache/dubbo/config/exception/ConfigValidationException.java
index 7d20b1b658..5ee95d0c54 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/exception/ConfigValidationException.java
@@ -14,12 +14,26 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.context;
+package org.apache.dubbo.config.exception;
-import org.apache.dubbo.config.AbstractConfig;
+/**
+ * Config validation exception
+ */
+public class ConfigValidationException extends RuntimeException {
+
+ public ConfigValidationException(String message) {
+ super(message);
+ }
-public interface ConfigValidator {
+ public ConfigValidationException(String message, Throwable cause) {
+ super(message, cause);
+ }
- void validate(AbstractConfig config);
+ public ConfigValidationException(Throwable cause) {
+ super(cause);
+ }
+ public ConfigValidationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
new file mode 100644
index 0000000000..f4313a0b2a
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
@@ -0,0 +1,355 @@
+/*
+ * 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.utils;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.URLBuilder;
+import org.apache.dubbo.common.config.ConfigurationUtils;
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.AbstractInterfaceConfig;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.registry.Constants;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SERVICE_CLASS_NAME;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX;
+import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_PARAMETER_FORMAT_ERROR;
+
+import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_ALL;
+import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_INSTANCE;
+import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_INTERFACE;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL;
+import static org.apache.dubbo.common.constants.RegistryConstants.DUBBO_REGISTER_MODE_DEFAULT_KEY;
+import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+import static org.apache.dubbo.config.Constants.IGNORE_CHECK_KEYS;
+import static org.apache.dubbo.config.Constants.REGISTER_KEY;
+
+public class ConfigValidationUtils {
+ public static final String IPV6_START_MARK = "[";
+ public static final String IPV6_END_MARK = "]";
+ /**
+ * The maximum length of a <b>parameter's value</b>
+ */
+ private static final int MAX_LENGTH = 200;
+ /**
+ * The maximum length of a <b>path</b>
+ */
+ private static final int MAX_PATH_LENGTH = 200;
+ /**
+ * The rule qualification for <b>name</b>
+ */
+ private static final Pattern PATTERN_NAME = Pattern.compile("[\\-._0-9a-zA-Z]+");
+ /**
+ * The rule qualification for <b>multiply name</b>
+ */
+ private static final Pattern PATTERN_MULTI_NAME = Pattern.compile("[,\\-._0-9a-zA-Z]+");
+ /**
+ * The rule qualification for <b>method names</b>
+ */
+ private static final Pattern PATTERN_METHOD_NAME = Pattern.compile("[a-zA-Z][0-9a-zA-Z]*");
+ /**
+ * The rule qualification for <b>path</b>
+ */
+ private static final Pattern PATTERN_PATH = Pattern.compile("[/\\-$._0-9a-zA-Z]+");
+ /**
+ * The pattern matches a value who has a symbol
+ */
+ private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,\\s/\\-._0-9a-zA-Z]+");
+ /**
+ * The pattern matches a property key
+ */
+ private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+");
+ private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ConfigValidationUtils.class);
+
+ public static List<URL> loadRegistries(AbstractInterfaceConfig interfaceConfig, boolean provider) {
+ // check && override if necessary
+ List<URL> registryList = new ArrayList<>();
+ ApplicationConfig application = interfaceConfig.getApplication();
+ List<RegistryConfig> registries = interfaceConfig.getRegistries();
+ if (CollectionUtils.isNotEmpty(registries)) {
+ for (RegistryConfig config : registries) {
+ // try to refresh registry in case it is set directly by user using config.setRegistries()
+ if (!config.isRefreshed()) {
+ config.refresh();
+ }
+ String address = config.getAddress();
+ if (StringUtils.isEmpty(address)) {
+ address = ANYHOST_VALUE;
+ }
+ if (!RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) {
+ Map<String, String> map = new HashMap<String, String>();
+ AbstractConfig.appendParameters(map, application);
+ AbstractConfig.appendParameters(map, config);
+ map.put(PATH_KEY,REGISTRY_SERVICE_CLASS_NAME);
+ AbstractInterfaceConfig.appendRuntimeParameters(map);
+ if (!map.containsKey(PROTOCOL_KEY)) {
+ map.put(PROTOCOL_KEY, DUBBO_PROTOCOL);
+ }
+ List<URL> urls = UrlUtils.parseURLs(address, map);
+
+ for (URL url : urls) {
+ url = URLBuilder.from(url)
+ .addParameter(REGISTRY_KEY, url.getProtocol())
+ .setProtocol(extractRegistryType(url))
+ .setScopeModel(interfaceConfig.getScopeModel())
+ .build();
+ // provider delay register state will be checked in RegistryProtocol#export
+ if (provider && url.getParameter(REGISTER_KEY, true)) {
+ registryList.add(url);
+ }
+ if (!provider && url.getParameter(Constants.SUBSCRIBE_KEY, true)) {
+ registryList.add(url);
+ }
+ }
+ }
+ }
+ }
+ return genCompatibleRegistries(interfaceConfig.getScopeModel(), registryList, provider);
+ }
+
+ private static List<URL> genCompatibleRegistries(ScopeModel scopeModel, List<URL> registryList, boolean provider) {
+ List<URL> result = new ArrayList<>(registryList.size());
+ registryList.forEach(registryURL -> {
+ if (provider) {
+ // for registries enabled service discovery, automatically register interface compatible addresses.
+ String registerMode;
+ if (SERVICE_REGISTRY_PROTOCOL.equals(registryURL.getProtocol())) {
+ registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(scopeModel, DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_INSTANCE));
+ if (!isValidRegisterMode(registerMode)) {
+ registerMode = DEFAULT_REGISTER_MODE_INSTANCE;
+ }
+ result.add(registryURL);
+ if (DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(registerMode)
+ && registryNotExists(registryURL, registryList, REGISTRY_PROTOCOL)) {
+ URL interfaceCompatibleRegistryURL = URLBuilder.from(registryURL)
+ .setProtocol(REGISTRY_PROTOCOL)
+ .removeParameter(REGISTRY_TYPE_KEY)
+ .build();
+ result.add(interfaceCompatibleRegistryURL);
+ }
+ } else {
+ registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(scopeModel, DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_ALL));
+ if (!isValidRegisterMode(registerMode)) {
+ registerMode = DEFAULT_REGISTER_MODE_INTERFACE;
+ }
+ if ((DEFAULT_REGISTER_MODE_INSTANCE.equalsIgnoreCase(registerMode) || DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(registerMode))
+ && registryNotExists(registryURL, registryList, SERVICE_REGISTRY_PROTOCOL)) {
+ URL serviceDiscoveryRegistryURL = URLBuilder.from(registryURL)
+ .setProtocol(SERVICE_REGISTRY_PROTOCOL)
+ .removeParameter(REGISTRY_TYPE_KEY)
+ .build();
+ result.add(serviceDiscoveryRegistryURL);
+ }
+
+ if (DEFAULT_REGISTER_MODE_INTERFACE.equalsIgnoreCase(registerMode) || DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(registerMode)) {
+ result.add(registryURL);
+ }
+ }
+
+ FrameworkStatusReportService reportService = ScopeModelUtil.getApplicationModel(scopeModel).getBeanFactory().getBean(FrameworkStatusReportService.class);
+ reportService.reportRegistrationStatus(reportService.createRegistrationReport(registerMode));
+ } else {
+ result.add(registryURL);
+ }
+ });
+
+ return result;
+ }
+
+ private static boolean isValidRegisterMode(String mode) {
+ return isNotEmpty(mode)
+ && (DEFAULT_REGISTER_MODE_INTERFACE.equalsIgnoreCase(mode)
+ || DEFAULT_REGISTER_MODE_INSTANCE.equalsIgnoreCase(mode)
+ || DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(mode)
+ );
+ }
+
+ private static boolean registryNotExists(URL registryURL, List<URL> registryList, String registryType) {
+ return registryList.stream().noneMatch(
+ url -> registryType.equals(url.getProtocol()) && registryURL.getBackupAddress().equals(url.getBackupAddress())
+ );
+ }
+
+ private static String extractRegistryType(URL url) {
+ return UrlUtils.hasServiceDiscoveryRegistryTypeKey(url) ? SERVICE_REGISTRY_PROTOCOL : getRegistryProtocolType(url);
+ }
+
+ private static String getRegistryProtocolType(URL url) {
+ String registryProtocol = url.getParameter("registry-protocol-type");
+ return isNotEmpty(registryProtocol) ? registryProtocol : REGISTRY_PROTOCOL;
+ }
+
+ public static void checkExtension(ScopeModel scopeModel, Class<?> type, String property, String value) {
+ checkName(property, value);
+ if (isNotEmpty(value)
+ && !scopeModel.getExtensionLoader(type).hasExtension(value)) {
+ throw new IllegalStateException("No such extension " + value + " for " + property + "/" + type.getName());
+ }
+ }
+
+ /**
+ * Check whether there is a <code>Extension</code> who's name (property) is <code>value</code> (special treatment is
+ * required)
+ *
+ * @param type The Extension type
+ * @param property The extension key
+ * @param value The Extension name
+ */
+ public static void checkMultiExtension(ScopeModel scopeModel, Class<?> type, String property, String value) {
+ checkMultiExtension(scopeModel, Collections.singletonList(type), property, value);
+ }
+
+ public static void checkMultiExtension(ScopeModel scopeModel, List<Class<?>> types, String property, String value) {
+ checkMultiName(property, value);
+ if (isNotEmpty(value)) {
+ String[] values = value.split("\\s*[,]+\\s*");
+ for (String v : values) {
+ v = StringUtils.trim(v);
+ if (v.startsWith(REMOVE_VALUE_PREFIX)) {
+ continue;
+ }
+ if (DEFAULT_KEY.equals(v)) {
+ continue;
+ }
+ boolean match = false;
+ for (Class<?> type : types) {
+ if (scopeModel.getExtensionLoader(type).hasExtension(v)) {
+ match = true;
+ }
+ }
+ if (!match) {
+ throw new IllegalStateException("No such extension " + v + " for " + property + "/" +
+ types.stream().map(Class::getName).collect(Collectors.joining(",")));
+ }
+ }
+ }
+ }
+
+ public static void checkLength(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, null);
+ }
+
+ public static void checkPathLength(String property, String value) {
+ checkProperty(property, value, MAX_PATH_LENGTH, null);
+ }
+
+ public static void checkName(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_NAME);
+ }
+
+ public static void checkHost(String property, String value) {
+ if (StringUtils.isEmpty(value)) {
+ return;
+ }
+ if (value.startsWith(IPV6_START_MARK) && value.endsWith(IPV6_END_MARK)) {
+ // if the value start with "[" and end with "]", check whether it is IPV6
+ try {
+ InetAddress.getByName(value);
+ return;
+ } catch (UnknownHostException e) {
+ // not a IPv6 string, do nothing, go on to checkName
+ }
+ }
+ checkName(property, value);
+ }
+
+ public static void checkNameHasSymbol(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_NAME_HAS_SYMBOL);
+ }
+
+ public static void checkKey(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_KEY);
+ }
+
+ public static void checkMultiName(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_MULTI_NAME);
+ }
+
+ public static void checkPathName(String property, String value) {
+ checkProperty(property, value, MAX_PATH_LENGTH, PATTERN_PATH);
+ }
+
+ public static void checkMethodName(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_METHOD_NAME);
+ }
+
+ public static void checkParameterName(Map<String, String> parameters) {
+ if (CollectionUtils.isEmptyMap(parameters)) {
+ return;
+ }
+ List<String> ignoreCheckKeys = new ArrayList<>();
+ ignoreCheckKeys.add(BACKUP_KEY);
+ String ignoreCheckKeysStr = parameters.get(IGNORE_CHECK_KEYS);
+ if (!StringUtils.isBlank(ignoreCheckKeysStr)) {
+ ignoreCheckKeys.addAll(Arrays.asList(ignoreCheckKeysStr.split(",")));
+ }
+ for (Map.Entry<String, String> entry : parameters.entrySet()) {
+ if (!ignoreCheckKeys.contains(entry.getKey())) {
+ checkNameHasSymbol(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ public static void checkProperty(String property, String value, int maxlength, Pattern pattern) {
+ if (StringUtils.isEmpty(value)) {
+ return;
+ }
+ if (value.length() > maxlength) {
+ logger.error(CONFIG_PARAMETER_FORMAT_ERROR, "the value content is too long", "", "Parameter value format error. Invalid " +
+ property + "=\"" + value + "\" is longer than " + maxlength);
+ }
+ if (pattern != null) {
+ Matcher matcher = pattern.matcher(value);
+ if (!matcher.matches()) {
+ logger.error(CONFIG_PARAMETER_FORMAT_ERROR, "the value content is illegal character", "", "Parameter value format error. Invalid " +
+ property + "=\"" + value + "\" contains illegal " +
+ "character, only digit, letter, '-', '_' or '.' is legal.");
+ }
+ }
+ }
+
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/validator/ApplicationConfigValidator.java b/dubbo-common/src/main/java/org/apache/dubbo/config/validator/ApplicationConfigValidator.java
new file mode 100644
index 0000000000..c9563aab88
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/validator/ApplicationConfigValidator.java
@@ -0,0 +1,97 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.config.PropertiesConfiguration;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.ClassUtils;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.exception.ConfigValidationException;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.rpc.model.ScopeModel;
+import org.apache.dubbo.rpc.model.ScopeModelUtil;
+
+import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_SECONDS_KEY;
+import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CLASS_NOT_FOUND;
+import static org.apache.dubbo.config.Constants.ARCHITECTURE;
+import static org.apache.dubbo.config.Constants.ENVIRONMENT;
+import static org.apache.dubbo.config.Constants.NAME;
+import static org.apache.dubbo.config.Constants.ORGANIZATION;
+import static org.apache.dubbo.config.Constants.OWNER;
+
+@Activate
+public class ApplicationConfigValidator implements ConfigValidator<ApplicationConfig> {
+
+ private static ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ApplicationConfigValidator.class);
+
+ public static void validateApplicationConfig(ApplicationConfig config) {
+ if (config == null) {
+ return;
+ }
+
+ if (!config.isValid()) {
+ throw new ConfigValidationException("No application config found or it's not a valid config! " +
+ "Please add <dubbo:application name=\"...\" /> to your spring config.");
+ }
+
+ // backward compatibility
+ ScopeModel scopeModel = ScopeModelUtil.getOrDefaultApplicationModel(config.getScopeModel());
+ PropertiesConfiguration configuration = scopeModel.modelEnvironment().getPropertiesConfiguration();
+ String wait = configuration.getProperty(SHUTDOWN_WAIT_KEY);
+ if (wait != null && wait.trim().length() > 0) {
+ System.setProperty(SHUTDOWN_WAIT_KEY, wait.trim());
+ } else {
+ wait = configuration.getProperty(SHUTDOWN_WAIT_SECONDS_KEY);
+ if (wait != null && wait.trim().length() > 0) {
+ System.setProperty(SHUTDOWN_WAIT_SECONDS_KEY, wait.trim());
+ }
+ }
+
+ ConfigValidationUtils.checkName(NAME, config.getName());
+ ConfigValidationUtils.checkMultiName(OWNER, config.getOwner());
+ ConfigValidationUtils.checkName(ORGANIZATION, config.getOrganization());
+ ConfigValidationUtils.checkName(ARCHITECTURE, config.getArchitecture());
+ ConfigValidationUtils.checkName(ENVIRONMENT, config.getEnvironment());
+ ConfigValidationUtils.checkParameterName(config.getParameters());
+ checkQosDependency(config);
+ }
+
+ public static void checkQosDependency(ApplicationConfig config) {
+ if (!Boolean.FALSE.equals(config.getQosEnable())) {
+ try {
+ ClassUtils.forName("org.apache.dubbo.qos.protocol.QosProtocolWrapper");
+ } catch (ClassNotFoundException e) {
+ logger.warn(COMMON_CLASS_NOT_FOUND, "", "", "No QosProtocolWrapper class was found. Please check the dependency of dubbo-qos whether was imported correctly.", e);
+ }
+ }
+ }
+
+ @Override
+ public boolean validate(ApplicationConfig config) {
+ validateApplicationConfig(config);
+ return true;
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return ApplicationConfig.class.isAssignableFrom(configClass);
+ }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/validator/ModuleConfigValidator.java b/dubbo-common/src/main/java/org/apache/dubbo/config/validator/ModuleConfigValidator.java
new file mode 100644
index 0000000000..85ddd314aa
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/validator/ModuleConfigValidator.java
@@ -0,0 +1,49 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.ModuleConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+
+import static org.apache.dubbo.config.Constants.NAME;
+import static org.apache.dubbo.config.Constants.ORGANIZATION;
+import static org.apache.dubbo.config.Constants.OWNER;
+
+@Activate
+public class ModuleConfigValidator implements ConfigValidator<ModuleConfig> {
+
+ @Override
+ public boolean validate(ModuleConfig config) {
+ validateModuleConfig(config);
+ return true;
+ }
+
+ public static void validateModuleConfig(ModuleConfig config) {
+ if (config != null) {
+ ConfigValidationUtils.checkName(NAME, config.getName());
+ ConfigValidationUtils.checkName(OWNER, config.getOwner());
+ ConfigValidationUtils.checkName(ORGANIZATION, config.getOrganization());
+ }
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return ModuleConfig.class.isAssignableFrom(configClass);
+ }
+}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/registry/Constants.java
similarity index 100%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/Constants.java
rename to dubbo-common/src/main/java/org/apache/dubbo/registry/Constants.java
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java b/dubbo-common/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
similarity index 100%
rename from dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
rename to dubbo-common/src/main/java/org/apache/dubbo/rpc/cluster/Constants.java
diff --git a/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
new file mode 100644
index 0000000000..8fe3a6c328
--- /dev/null
+++ b/dubbo-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
@@ -0,0 +1,2 @@
+application=org.apache.dubbo.config.validator.ApplicationConfigValidator
+module=org.apache.dubbo.config.validator.ModuleConfigValidator
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
index 5ddd74aad4..00d1ec7fcc 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.config.context;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ConfigCenterConfig;
+import org.apache.dubbo.config.ConfigValidateFacade;
import org.apache.dubbo.config.ConsumerConfig;
import org.apache.dubbo.config.MetricsConfig;
import org.apache.dubbo.config.ModuleConfig;
@@ -64,6 +65,7 @@ class ConfigManagerTest {
ApplicationModel applicationModel = ApplicationModel.defaultModel();
configManager = applicationModel.getApplicationConfigManager();
moduleConfigManager = applicationModel.getDefaultModule().getConfigManager();
+ ConfigValidateFacade.setEnableValidate(false);
}
@Test
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigScopeModelInitializer.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigScopeModelInitializer.java
index 955da26d23..fa82316dca 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigScopeModelInitializer.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigScopeModelInitializer.java
@@ -22,7 +22,6 @@ import org.apache.dubbo.common.deploy.ModuleDeployer;
import org.apache.dubbo.config.deploy.DefaultApplicationDeployer;
import org.apache.dubbo.config.deploy.DefaultModuleDeployer;
import org.apache.dubbo.config.deploy.FrameworkModelCleaner;
-import org.apache.dubbo.config.utils.DefaultConfigValidator;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
import org.apache.dubbo.rpc.model.ModuleModel;
@@ -38,11 +37,9 @@ public class ConfigScopeModelInitializer implements ScopeModelInitializer {
@Override
public void initializeApplicationModel(ApplicationModel applicationModel) {
ScopeBeanFactory beanFactory = applicationModel.getBeanFactory();
- beanFactory.registerBean(DefaultConfigValidator.class);
// applicationDeployer
ApplicationDeployer applicationDeployer = beanFactory.registerBean(DefaultApplicationDeployer.class);
applicationModel.setDeployer(applicationDeployer);
-
}
@Override
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index c11f9c3f62..924b1a9cb8 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -53,6 +53,7 @@ import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol;
import org.apache.dubbo.rpc.service.GenericService;
import org.apache.dubbo.rpc.stub.StubSuppliers;
import org.apache.dubbo.rpc.support.ProtocolUtils;
+import org.apache.dubbo.util.MonitorUrlUtil;
import java.beans.Transient;
import java.util.ArrayList;
@@ -179,7 +180,6 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
@Override
protected void postProcessAfterScopeModelChanged(ScopeModel oldScopeModel, ScopeModel newScopeModel) {
super.postProcessAfterScopeModelChanged(oldScopeModel, newScopeModel);
-
protocolSPI = this.getExtensionLoader(Protocol.class).getAdaptiveExtension();
proxyFactory = this.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
}
@@ -579,7 +579,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
List<URL> us = ConfigValidationUtils.loadRegistries(this, false);
if (CollectionUtils.isNotEmpty(us)) {
for (URL u : us) {
- URL monitorUrl = ConfigValidationUtils.loadMonitor(this, u);
+ URL monitorUrl = MonitorUrlUtil.loadMonitor(this, u);
if (monitorUrl != null) {
u = u.putAttribute(MONITOR_KEY, monitorUrl);
}
@@ -746,7 +746,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
}
resolveFile();
- ConfigValidationUtils.validateReferenceConfig(this);
+ validate();
postProcessConfig();
}
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 d9d6862255..91dde23fda 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
@@ -54,6 +54,7 @@ import org.apache.dubbo.rpc.model.ProviderModel;
import org.apache.dubbo.rpc.model.ScopeModel;
import org.apache.dubbo.rpc.model.ServiceDescriptor;
import org.apache.dubbo.rpc.service.GenericService;
+import org.apache.dubbo.util.MonitorUrlUtil;
import java.beans.Transient;
import java.lang.reflect.Method;
@@ -468,7 +469,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
}
}
checkStubAndLocal(interfaceClass);
- ConfigValidationUtils.validateServiceConfig(this);
+ validate();
postProcessConfig();
}
@@ -805,7 +806,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
}
url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY));
- URL monitorUrl = ConfigValidationUtils.loadMonitor(this, registryURL);
+ URL monitorUrl = MonitorUrlUtil.loadMonitor(this, registryURL);
if (monitorUrl != null) {
url = url.putAttribute(MONITOR_KEY, monitorUrl);
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ApplicationLifecycle.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ApplicationLifecycle.java
index 505c228cf4..08aaeb2060 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ApplicationLifecycle.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ApplicationLifecycle.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.config.deploy.lifecycle.application;
+import org.apache.dubbo.common.deploy.ApplicationDeployListener;
import org.apache.dubbo.common.deploy.DeployState;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.config.deploy.context.ApplicationContext;
@@ -27,6 +28,8 @@ import org.apache.dubbo.rpc.model.ModuleModel;
* <br>
* Used in an application Lifecycle managing procedure, and dubbo packages
* can implement this interface to define what to do when application status changes.
+ * <p>
+ * Note: If you want to auto registry some extensions to BeanFactory, use {@link ApplicationDeployListener} instead.
* <br>
*/
@SPI
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ConfigCenterApplicationLifecycle.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ConfigCenterApplicationLifecycle.java
index 82515fe48e..90e4926385 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ConfigCenterApplicationLifecycle.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ConfigCenterApplicationLifecycle.java
@@ -34,7 +34,6 @@ import org.apache.dubbo.config.ConfigCenterConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.deploy.context.ApplicationContext;
-import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.metrics.config.event.ConfigCenterEvent;
import org.apache.dubbo.metrics.event.MetricsEventBus;
import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -85,7 +84,7 @@ public class ConfigCenterApplicationLifecycle implements ApplicationLifecycle {
ConfigCenterConfig configCenterConfig = new ConfigCenterConfig();
configCenterConfig.setScopeModel(applicationModel);
configCenterConfig.refresh();
- ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
+ configCenterConfig.validate();
if (configCenterConfig.isValid()) {
configManager.addConfigCenter(configCenterConfig);
configCenters = configManager.getConfigCenters();
@@ -93,7 +92,7 @@ public class ConfigCenterApplicationLifecycle implements ApplicationLifecycle {
} else {
for (ConfigCenterConfig configCenterConfig : configCenters) {
configCenterConfig.refresh();
- ConfigValidationUtils.validateConfigCenterConfig(configCenterConfig);
+ configCenterConfig.validate();
}
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/MetadataInitializeLifecycle.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/MetadataInitializeLifecycle.java
index fb35d4a141..a9e9bfdf4f 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/MetadataInitializeLifecycle.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/MetadataInitializeLifecycle.java
@@ -28,7 +28,6 @@ import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.config.deploy.context.ApplicationContext;
-import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.metadata.report.MetadataReportFactory;
import org.apache.dubbo.metadata.report.MetadataReportInstance;
import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -91,8 +90,7 @@ public class MetadataInitializeLifecycle implements ApplicationLifecycle {
List<MetadataReportConfig> validMetadataReportConfigs = new ArrayList<>(metadataReportConfigs.size());
for (MetadataReportConfig metadataReportConfig : metadataReportConfigs) {
- if (ConfigValidationUtils.isValidMetadataConfig(metadataReportConfig)) {
- ConfigValidationUtils.validateMetadataConfig(metadataReportConfig);
+ if (metadataReportConfig.validate()) {
validMetadataReportConfigs.add(metadataReportConfig);
}
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ValidatorRegistryDeployListener.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ValidatorRegistryDeployListener.java
new file mode 100644
index 0000000000..3f5d75ffcf
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/deploy/lifecycle/application/ValidatorRegistryDeployListener.java
@@ -0,0 +1,41 @@
+/*
+ * 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.deploy.lifecycle.application;
+
+import org.apache.dubbo.common.deploy.ApplicationDeployListener;
+import org.apache.dubbo.config.ConfigValidateFacade;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+public class ValidatorRegistryDeployListener implements ApplicationDeployListener {
+
+ @Override
+ public void onStarting(ApplicationModel scopeModel) {
+ ConfigValidateFacade validateFacade = new ConfigValidateFacade(scopeModel);
+ scopeModel.getBeanFactory().registerBean(validateFacade);
+ }
+
+ @Override
+ public void onInitialize(ApplicationModel scopeModel) {}
+ @Override
+ public void onStarted(ApplicationModel scopeModel) {}
+ @Override
+ public void onStopping(ApplicationModel scopeModel) {}
+ @Override
+ public void onStopped(ApplicationModel scopeModel) {}
+ @Override
+ public void onFailure(ApplicationModel scopeModel, Throwable cause) {}
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
deleted file mode 100644
index 1f92b894ad..0000000000
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
+++ /dev/null
@@ -1,741 +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.config.utils;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.URLBuilder;
-import org.apache.dubbo.common.config.ConfigurationUtils;
-import org.apache.dubbo.common.config.PropertiesConfiguration;
-import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.serialize.Serialization;
-import org.apache.dubbo.common.status.StatusChecker;
-import org.apache.dubbo.common.status.reporter.FrameworkStatusReportService;
-import org.apache.dubbo.common.threadpool.ThreadPool;
-import org.apache.dubbo.common.utils.ClassUtils;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.ConfigUtils;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.common.utils.UrlUtils;
-import org.apache.dubbo.config.AbstractConfig;
-import org.apache.dubbo.config.AbstractInterfaceConfig;
-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.MetricsConfig;
-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.ReferenceConfig;
-import org.apache.dubbo.config.RegistryConfig;
-import org.apache.dubbo.config.ServiceConfig;
-import org.apache.dubbo.config.SslConfig;
-import org.apache.dubbo.config.TracingConfig;
-import org.apache.dubbo.monitor.MonitorFactory;
-import org.apache.dubbo.monitor.MonitorService;
-import org.apache.dubbo.registry.RegistryService;
-import org.apache.dubbo.remoting.Codec2;
-import org.apache.dubbo.remoting.Dispatcher;
-import org.apache.dubbo.remoting.Transporter;
-import org.apache.dubbo.remoting.exchange.Exchanger;
-import org.apache.dubbo.remoting.telnet.TelnetHandler;
-import org.apache.dubbo.rpc.ExporterListener;
-import org.apache.dubbo.rpc.Filter;
-import org.apache.dubbo.rpc.InvokerListener;
-import org.apache.dubbo.rpc.ProxyFactory;
-import org.apache.dubbo.rpc.cluster.Cluster;
-import org.apache.dubbo.rpc.cluster.LoadBalance;
-import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
-import org.apache.dubbo.rpc.model.ScopeModel;
-import org.apache.dubbo.rpc.model.ScopeModelUtil;
-
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
-import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_MONITOR_ADDRESS;
-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
-import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.FILTER_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.LOADBALANCE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
-import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.REMOVE_VALUE_PREFIX;
-import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.SHUTDOWN_WAIT_SECONDS_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
-import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CLASS_NOT_FOUND;
-import static org.apache.dubbo.common.constants.LoggerCodeConstants.CONFIG_PARAMETER_FORMAT_ERROR;
-import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_ALL;
-import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_INSTANCE;
-import static org.apache.dubbo.common.constants.RegistryConstants.DEFAULT_REGISTER_MODE_INTERFACE;
-import static org.apache.dubbo.common.constants.RegistryConstants.DUBBO_REGISTER_MODE_DEFAULT_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTER_MODE_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL;
-import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
-import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
-import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
-import static org.apache.dubbo.config.Constants.ARCHITECTURE;
-import static org.apache.dubbo.config.Constants.CONTEXTPATH_KEY;
-import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
-import static org.apache.dubbo.config.Constants.ENVIRONMENT;
-import static org.apache.dubbo.config.Constants.IGNORE_CHECK_KEYS;
-import static org.apache.dubbo.config.Constants.LAYER_KEY;
-import static org.apache.dubbo.config.Constants.NAME;
-import static org.apache.dubbo.config.Constants.ORGANIZATION;
-import static org.apache.dubbo.config.Constants.OWNER;
-import static org.apache.dubbo.config.Constants.REGISTER_KEY;
-import static org.apache.dubbo.config.Constants.STATUS_KEY;
-import static org.apache.dubbo.monitor.Constants.LOGSTAT_PROTOCOL;
-import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
-import static org.apache.dubbo.registry.Constants.SUBSCRIBE_KEY;
-import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
-import static org.apache.dubbo.remoting.Constants.CODEC_KEY;
-import static org.apache.dubbo.remoting.Constants.DISPATCHER_KEY;
-import static org.apache.dubbo.remoting.Constants.EXCHANGER_KEY;
-import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY;
-import static org.apache.dubbo.remoting.Constants.SERVER_KEY;
-import static org.apache.dubbo.remoting.Constants.TELNET_KEY;
-import static org.apache.dubbo.remoting.Constants.TRANSPORTER_KEY;
-import static org.apache.dubbo.rpc.Constants.FAIL_PREFIX;
-import static org.apache.dubbo.rpc.Constants.FORCE_PREFIX;
-import static org.apache.dubbo.rpc.Constants.LOCAL_KEY;
-import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
-import static org.apache.dubbo.rpc.Constants.PROXY_KEY;
-import static org.apache.dubbo.rpc.Constants.RETURN_PREFIX;
-import static org.apache.dubbo.rpc.Constants.THROW_PREFIX;
-import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
-import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
-
-public class ConfigValidationUtils {
- private static ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(ConfigValidationUtils.class);
- /**
- * The maximum length of a <b>parameter's value</b>
- */
- private static final int MAX_LENGTH = 200;
-
- /**
- * The maximum length of a <b>path</b>
- */
- private static final int MAX_PATH_LENGTH = 200;
-
- /**
- * The rule qualification for <b>name</b>
- */
- private static final Pattern PATTERN_NAME = Pattern.compile("[\\-._0-9a-zA-Z]+");
-
- /**
- * The rule qualification for <b>multiply name</b>
- */
- private static final Pattern PATTERN_MULTI_NAME = Pattern.compile("[,\\-._0-9a-zA-Z]+");
-
- /**
- * The rule qualification for <b>method names</b>
- */
- private static final Pattern PATTERN_METHOD_NAME = Pattern.compile("[a-zA-Z][0-9a-zA-Z]*");
-
- /**
- * The rule qualification for <b>path</b>
- */
- private static final Pattern PATTERN_PATH = Pattern.compile("[/\\-$._0-9a-zA-Z]+");
-
- /**
- * The pattern matches a value who has a symbol
- */
- private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,\\s/\\-._0-9a-zA-Z]+");
-
- /**
- * The pattern matches a property key
- */
- private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+");
-
- public static final String IPV6_START_MARK = "[";
-
- public static final String IPV6_END_MARK = "]";
-
- public static List<URL> loadRegistries(AbstractInterfaceConfig interfaceConfig, boolean provider) {
- // check && override if necessary
- List<URL> registryList = new ArrayList<>();
- ApplicationConfig application = interfaceConfig.getApplication();
- List<RegistryConfig> registries = interfaceConfig.getRegistries();
- if (CollectionUtils.isNotEmpty(registries)) {
- for (RegistryConfig config : registries) {
- // try to refresh registry in case it is set directly by user using config.setRegistries()
- if (!config.isRefreshed()) {
- config.refresh();
- }
- String address = config.getAddress();
- if (StringUtils.isEmpty(address)) {
- address = ANYHOST_VALUE;
- }
- if (!RegistryConfig.NO_AVAILABLE.equalsIgnoreCase(address)) {
- Map<String, String> map = new HashMap<String, String>();
- AbstractConfig.appendParameters(map, application);
- AbstractConfig.appendParameters(map, config);
- map.put(PATH_KEY, RegistryService.class.getName());
- AbstractInterfaceConfig.appendRuntimeParameters(map);
- if (!map.containsKey(PROTOCOL_KEY)) {
- map.put(PROTOCOL_KEY, DUBBO_PROTOCOL);
- }
- List<URL> urls = UrlUtils.parseURLs(address, map);
-
- for (URL url : urls) {
- url = URLBuilder.from(url)
- .addParameter(REGISTRY_KEY, url.getProtocol())
- .setProtocol(extractRegistryType(url))
- .setScopeModel(interfaceConfig.getScopeModel())
- .build();
- // provider delay register state will be checked in RegistryProtocol#export
- if (provider && url.getParameter(REGISTER_KEY, true)) {
- registryList.add(url);
- }
- if (!provider && url.getParameter(SUBSCRIBE_KEY, true)) {
- registryList.add(url);
- }
- }
- }
- }
- }
- return genCompatibleRegistries(interfaceConfig.getScopeModel(), registryList, provider);
- }
-
- private static List<URL> genCompatibleRegistries(ScopeModel scopeModel, List<URL> registryList, boolean provider) {
- List<URL> result = new ArrayList<>(registryList.size());
- registryList.forEach(registryURL -> {
- if (provider) {
- // for registries enabled service discovery, automatically register interface compatible addresses.
- String registerMode;
- if (SERVICE_REGISTRY_PROTOCOL.equals(registryURL.getProtocol())) {
- registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(scopeModel, DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_INSTANCE));
- if (!isValidRegisterMode(registerMode)) {
- registerMode = DEFAULT_REGISTER_MODE_INSTANCE;
- }
- result.add(registryURL);
- if (DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(registerMode)
- && registryNotExists(registryURL, registryList, REGISTRY_PROTOCOL)) {
- URL interfaceCompatibleRegistryURL = URLBuilder.from(registryURL)
- .setProtocol(REGISTRY_PROTOCOL)
- .removeParameter(REGISTRY_TYPE_KEY)
- .build();
- result.add(interfaceCompatibleRegistryURL);
- }
- } else {
- registerMode = registryURL.getParameter(REGISTER_MODE_KEY, ConfigurationUtils.getCachedDynamicProperty(scopeModel, DUBBO_REGISTER_MODE_DEFAULT_KEY, DEFAULT_REGISTER_MODE_ALL));
- if (!isValidRegisterMode(registerMode)) {
- registerMode = DEFAULT_REGISTER_MODE_INTERFACE;
- }
- if ((DEFAULT_REGISTER_MODE_INSTANCE.equalsIgnoreCase(registerMode) || DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(registerMode))
- && registryNotExists(registryURL, registryList, SERVICE_REGISTRY_PROTOCOL)) {
- URL serviceDiscoveryRegistryURL = URLBuilder.from(registryURL)
- .setProtocol(SERVICE_REGISTRY_PROTOCOL)
- .removeParameter(REGISTRY_TYPE_KEY)
- .build();
- result.add(serviceDiscoveryRegistryURL);
- }
-
- if (DEFAULT_REGISTER_MODE_INTERFACE.equalsIgnoreCase(registerMode) || DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(registerMode)) {
- result.add(registryURL);
- }
- }
-
- FrameworkStatusReportService reportService = ScopeModelUtil.getApplicationModel(scopeModel).getBeanFactory().getBean(FrameworkStatusReportService.class);
- reportService.reportRegistrationStatus(reportService.createRegistrationReport(registerMode));
- } else {
- result.add(registryURL);
- }
- });
-
- return result;
- }
-
- private static boolean isValidRegisterMode(String mode) {
- return isNotEmpty(mode)
- && (DEFAULT_REGISTER_MODE_INTERFACE.equalsIgnoreCase(mode)
- || DEFAULT_REGISTER_MODE_INSTANCE.equalsIgnoreCase(mode)
- || DEFAULT_REGISTER_MODE_ALL.equalsIgnoreCase(mode)
- );
- }
-
- private static boolean registryNotExists(URL registryURL, List<URL> registryList, String registryType) {
- return registryList.stream().noneMatch(
- url -> registryType.equals(url.getProtocol()) && registryURL.getBackupAddress().equals(url.getBackupAddress())
- );
- }
-
- public static URL loadMonitor(AbstractInterfaceConfig interfaceConfig, URL registryURL) {
- Map<String, String> map = new HashMap<String, String>();
- map.put(INTERFACE_KEY, MonitorService.class.getName());
- AbstractInterfaceConfig.appendRuntimeParameters(map);
- //set ip
- String hostToRegistry = ConfigUtils.getSystemProperty(DUBBO_IP_TO_REGISTRY);
- if (StringUtils.isEmpty(hostToRegistry)) {
- hostToRegistry = NetUtils.getLocalHost();
- } else if (NetUtils.isInvalidLocalHost(hostToRegistry)) {
- throw new IllegalArgumentException("Specified invalid registry ip from property:" +
- DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
- }
- map.put(REGISTER_IP_KEY, hostToRegistry);
-
- MonitorConfig monitor = interfaceConfig.getMonitor();
- ApplicationConfig application = interfaceConfig.getApplication();
- AbstractConfig.appendParameters(map, monitor);
- AbstractConfig.appendParameters(map, application);
- String address = null;
- String sysAddress = System.getProperty(DUBBO_MONITOR_ADDRESS);
- if (sysAddress != null && sysAddress.length() > 0) {
- address = sysAddress;
- } else if (monitor != null) {
- address = monitor.getAddress();
- }
- String protocol = monitor == null ? null : monitor.getProtocol();
- if (monitor != null &&
- (REGISTRY_PROTOCOL.equals(protocol) || SERVICE_REGISTRY_PROTOCOL.equals(protocol))
- && registryURL != null) {
- return URLBuilder.from(registryURL)
- .setProtocol(DUBBO_PROTOCOL)
- .addParameter(PROTOCOL_KEY, protocol)
- .putAttribute(REFER_KEY, map)
- .build();
- } else if (ConfigUtils.isNotEmpty(address) || ConfigUtils.isNotEmpty(protocol)) {
- if (!map.containsKey(PROTOCOL_KEY)) {
- if (interfaceConfig.getScopeModel().getExtensionLoader(MonitorFactory.class).hasExtension(LOGSTAT_PROTOCOL)) {
- map.put(PROTOCOL_KEY, LOGSTAT_PROTOCOL);
- } else if (ConfigUtils.isNotEmpty(protocol)) {
- map.put(PROTOCOL_KEY, protocol);
- } else {
- map.put(PROTOCOL_KEY, DUBBO_PROTOCOL);
- }
- }
- if (ConfigUtils.isEmpty(address)) {
- address = LOCALHOST_VALUE;
- }
- return UrlUtils.parseURL(address, map);
- }
- return null;
- }
-
-
- public static void validateAbstractInterfaceConfig(AbstractInterfaceConfig config) {
- checkName(LOCAL_KEY, config.getLocal());
- checkName("stub", config.getStub());
- checkMultiName("owner", config.getOwner());
-
- checkExtension(config.getScopeModel(), ProxyFactory.class, PROXY_KEY, config.getProxy());
- checkExtension(config.getScopeModel(), Cluster.class, CLUSTER_KEY, config.getCluster());
- checkMultiExtension(config.getScopeModel(), Arrays.asList(Filter.class, ClusterFilter.class), FILTER_KEY, config.getFilter());
- checkNameHasSymbol(LAYER_KEY, config.getLayer());
-
- List<MethodConfig> methods = config.getMethods();
- if (CollectionUtils.isNotEmpty(methods)) {
- methods.forEach(ConfigValidationUtils::validateMethodConfig);
- }
- }
-
- public static void validateServiceConfig(ServiceConfig config) {
- checkKey(VERSION_KEY, config.getVersion());
- checkKey(GROUP_KEY, config.getGroup());
- checkName(TOKEN_KEY, config.getToken());
- checkPathName(PATH_KEY, config.getPath());
-
- checkMultiExtension(config.getScopeModel(), ExporterListener.class, "listener", config.getListener());
-
- validateAbstractInterfaceConfig(config);
-
- List<RegistryConfig> registries = config.getRegistries();
- if (registries != null) {
- for (RegistryConfig registry : registries) {
- validateRegistryConfig(registry);
- }
- }
-
- List<ProtocolConfig> protocols = config.getProtocols();
- if (protocols != null) {
- for (ProtocolConfig protocol : protocols) {
- validateProtocolConfig(protocol);
- }
- }
-
- ProviderConfig providerConfig = config.getProvider();
- if (providerConfig != null) {
- validateProviderConfig(providerConfig);
- }
- }
-
- public static void validateReferenceConfig(ReferenceConfig config) {
- checkMultiExtension(config.getScopeModel(), InvokerListener.class, "listener", config.getListener());
- checkKey(VERSION_KEY, config.getVersion());
- checkKey(GROUP_KEY, config.getGroup());
- checkName(CLIENT_KEY, config.getClient());
-
- validateAbstractInterfaceConfig(config);
-
- List<RegistryConfig> registries = config.getRegistries();
- if (registries != null) {
- for (RegistryConfig registry : registries) {
- validateRegistryConfig(registry);
- }
- }
-
- ConsumerConfig consumerConfig = config.getConsumer();
- if (consumerConfig != null) {
- validateConsumerConfig(consumerConfig);
- }
- }
-
- public static void validateConfigCenterConfig(ConfigCenterConfig config) {
- if (config != null) {
- checkParameterName(config.getParameters());
- }
- }
-
- public static void validateApplicationConfig(ApplicationConfig config) {
- if (config == null) {
- return;
- }
-
- if (!config.isValid()) {
- throw new IllegalStateException("No application config found or it's not a valid config! " +
- "Please add <dubbo:application name=\"...\" /> to your spring config.");
- }
-
- // backward compatibility
- ScopeModel scopeModel = ScopeModelUtil.getOrDefaultApplicationModel(config.getScopeModel());
- PropertiesConfiguration configuration = scopeModel.modelEnvironment().getPropertiesConfiguration();
- String wait = configuration.getProperty(SHUTDOWN_WAIT_KEY);
- if (wait != null && wait.trim().length() > 0) {
- System.setProperty(SHUTDOWN_WAIT_KEY, wait.trim());
- } else {
- wait = configuration.getProperty(SHUTDOWN_WAIT_SECONDS_KEY);
- if (wait != null && wait.trim().length() > 0) {
- System.setProperty(SHUTDOWN_WAIT_SECONDS_KEY, wait.trim());
- }
- }
-
- checkName(NAME, config.getName());
- checkMultiName(OWNER, config.getOwner());
- checkName(ORGANIZATION, config.getOrganization());
- checkName(ARCHITECTURE, config.getArchitecture());
- checkName(ENVIRONMENT, config.getEnvironment());
- checkParameterName(config.getParameters());
- checkQosDependency(config);
- }
-
- private static void checkQosDependency(ApplicationConfig config) {
- if (!Boolean.FALSE.equals(config.getQosEnable())) {
- try {
- ClassUtils.forName("org.apache.dubbo.qos.protocol.QosProtocolWrapper");
- } catch (ClassNotFoundException e) {
- logger.warn(COMMON_CLASS_NOT_FOUND, "", "", "No QosProtocolWrapper class was found. Please check the dependency of dubbo-qos whether was imported correctly.", e);
- }
- }
- }
-
- public static void validateModuleConfig(ModuleConfig config) {
- if (config != null) {
- checkName(NAME, config.getName());
- checkName(OWNER, config.getOwner());
- checkName(ORGANIZATION, config.getOrganization());
- }
- }
-
- public static boolean isValidMetadataConfig(MetadataReportConfig metadataReportConfig) {
- if (metadataReportConfig == null) {
- return false;
- }
-
- if (Boolean.FALSE.equals(metadataReportConfig.getReportMetadata()) &&
- Boolean.FALSE.equals(metadataReportConfig.getReportDefinition())) {
- return false;
- }
-
- return !isEmpty(metadataReportConfig.getAddress());
- }
-
- public static void validateMetadataConfig(MetadataReportConfig metadataReportConfig) {
- if (!isValidMetadataConfig(metadataReportConfig)) {
- return;
- }
-
- String address = metadataReportConfig.getAddress();
- String protocol = metadataReportConfig.getProtocol();
-
- if ((isEmpty(address) || !address.contains("://")) && isEmpty(protocol)) {
- throw new IllegalArgumentException("Please specify valid protocol or address for metadata report " + address);
- }
- }
-
- public static void validateMetricsConfig(MetricsConfig metricsConfig) {
- if (metricsConfig == null) {
- return;
- }
- }
-
- public static void validateTracingConfig(TracingConfig tracingConfig) {
- if (tracingConfig == null) {
- return;
- }
- }
-
- public static void validateSslConfig(SslConfig sslConfig) {
- if (sslConfig == null) {
- return;
- }
- }
-
- public static void validateMonitorConfig(MonitorConfig config) {
- if (config != null) {
- if (!config.isValid()) {
- logger.info("There's no valid monitor config found, if you want to open monitor statistics for Dubbo, " +
- "please make sure your monitor is configured properly.");
- }
-
- checkParameterName(config.getParameters());
- }
- }
-
- public static void validateProtocolConfig(ProtocolConfig config) {
- if (config != null) {
- String name = config.getName();
- checkName("name", name);
- checkHost(HOST_KEY, config.getHost());
- checkPathName("contextpath", config.getContextpath());
-
-
- if (DUBBO_PROTOCOL.equals(name)) {
- checkMultiExtension(config.getScopeModel(), Codec2.class, CODEC_KEY, config.getCodec());
- checkMultiExtension(config.getScopeModel(), Serialization.class, SERIALIZATION_KEY, config.getSerialization());
- checkMultiExtension(config.getScopeModel(), Transporter.class, SERVER_KEY, config.getServer());
- checkMultiExtension(config.getScopeModel(), Transporter.class, CLIENT_KEY, config.getClient());
- }
-
- checkMultiExtension(config.getScopeModel(), TelnetHandler.class, TELNET_KEY, config.getTelnet());
- checkMultiExtension(config.getScopeModel(), StatusChecker.class, "status", config.getStatus());
- checkExtension(config.getScopeModel(), Transporter.class, TRANSPORTER_KEY, config.getTransporter());
- checkExtension(config.getScopeModel(), Exchanger.class, EXCHANGER_KEY, config.getExchanger());
- checkExtension(config.getScopeModel(), Dispatcher.class, DISPATCHER_KEY, config.getDispatcher());
- checkExtension(config.getScopeModel(), Dispatcher.class, "dispather", config.getDispather());
- checkExtension(config.getScopeModel(), ThreadPool.class, THREADPOOL_KEY, config.getThreadpool());
- }
- }
-
- public static void validateProviderConfig(ProviderConfig config) {
- checkPathName(CONTEXTPATH_KEY, config.getContextpath());
- checkExtension(config.getScopeModel(), ThreadPool.class, THREADPOOL_KEY, config.getThreadpool());
- checkMultiExtension(config.getScopeModel(), TelnetHandler.class, TELNET_KEY, config.getTelnet());
- checkMultiExtension(config.getScopeModel(), StatusChecker.class, STATUS_KEY, config.getStatus());
- checkExtension(config.getScopeModel(), Transporter.class, TRANSPORTER_KEY, config.getTransporter());
- checkExtension(config.getScopeModel(), Exchanger.class, EXCHANGER_KEY, config.getExchanger());
- }
-
- public static void validateConsumerConfig(ConsumerConfig config) {
- if (config == null) {
- return;
- }
- }
-
- public static void validateRegistryConfig(RegistryConfig config) {
- checkName(PROTOCOL_KEY, config.getProtocol());
- checkName(USERNAME_KEY, config.getUsername());
- checkLength(PASSWORD_KEY, config.getPassword());
- checkPathLength(FILE_KEY, config.getFile());
- checkName(TRANSPORTER_KEY, config.getTransporter());
- checkName(SERVER_KEY, config.getServer());
- checkName(CLIENT_KEY, config.getClient());
- checkParameterName(config.getParameters());
- }
-
- public static void validateMethodConfig(MethodConfig config) {
- checkExtension(config.getScopeModel(), LoadBalance.class, LOADBALANCE_KEY, config.getLoadbalance());
- checkParameterName(config.getParameters());
- checkMethodName("name", config.getName());
-
- String mock = config.getMock();
- if (isNotEmpty(mock)) {
- if (mock.startsWith(RETURN_PREFIX) || mock.startsWith(THROW_PREFIX + " ")) {
- checkLength(MOCK_KEY, mock);
- } else if (mock.startsWith(FAIL_PREFIX) || mock.startsWith(FORCE_PREFIX)) {
- checkNameHasSymbol(MOCK_KEY, mock);
- } else {
- checkName(MOCK_KEY, mock);
- }
- }
- }
-
- private static String extractRegistryType(URL url) {
- return UrlUtils.hasServiceDiscoveryRegistryTypeKey(url) ? SERVICE_REGISTRY_PROTOCOL : getRegistryProtocolType(url);
- }
-
- private static String getRegistryProtocolType(URL url) {
- String registryProtocol = url.getParameter("registry-protocol-type");
- return isNotEmpty(registryProtocol) ? registryProtocol : REGISTRY_PROTOCOL;
- }
-
- public static void checkExtension(ScopeModel scopeModel, Class<?> type, String property, String value) {
- checkName(property, value);
- if (isNotEmpty(value)
- && !scopeModel.getExtensionLoader(type).hasExtension(value)) {
- throw new IllegalStateException("No such extension " + value + " for " + property + "/" + type.getName());
- }
- }
-
- /**
- * Check whether there is a <code>Extension</code> who's name (property) is <code>value</code> (special treatment is
- * required)
- *
- * @param type The Extension type
- * @param property The extension key
- * @param value The Extension name
- */
- public static void checkMultiExtension(ScopeModel scopeModel, Class<?> type, String property, String value) {
- checkMultiExtension(scopeModel, Collections.singletonList(type), property, value);
- }
-
- public static void checkMultiExtension(ScopeModel scopeModel, List<Class<?>> types, String property, String value) {
- checkMultiName(property, value);
- if (isNotEmpty(value)) {
- String[] values = value.split("\\s*[,]+\\s*");
- for (String v : values) {
- v = StringUtils.trim(v);
- if (v.startsWith(REMOVE_VALUE_PREFIX)) {
- continue;
- }
- if (DEFAULT_KEY.equals(v)) {
- continue;
- }
- boolean match = false;
- for (Class<?> type : types) {
- if (scopeModel.getExtensionLoader(type).hasExtension(v)) {
- match = true;
- }
- }
- if (!match) {
- throw new IllegalStateException("No such extension " + v + " for " + property + "/" +
- types.stream().map(Class::getName).collect(Collectors.joining(",")));
- }
- }
- }
- }
-
- public static void checkLength(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, null);
- }
-
- public static void checkPathLength(String property, String value) {
- checkProperty(property, value, MAX_PATH_LENGTH, null);
- }
-
- public static void checkName(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_NAME);
- }
-
- public static void checkHost(String property, String value) {
- if (StringUtils.isEmpty(value)) {
- return;
- }
- if (value.startsWith(IPV6_START_MARK) && value.endsWith(IPV6_END_MARK)) {
- // if the value start with "[" and end with "]", check whether it is IPV6
- try {
- InetAddress.getByName(value);
- return;
- } catch (UnknownHostException e) {
- // not a IPv6 string, do nothing, go on to checkName
- }
- }
- checkName(property, value);
- }
-
- public static void checkNameHasSymbol(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_NAME_HAS_SYMBOL);
- }
-
- public static void checkKey(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_KEY);
- }
-
- public static void checkMultiName(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_MULTI_NAME);
- }
-
- public static void checkPathName(String property, String value) {
- checkProperty(property, value, MAX_PATH_LENGTH, PATTERN_PATH);
- }
-
- public static void checkMethodName(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_METHOD_NAME);
- }
-
- public static void checkParameterName(Map<String, String> parameters) {
- if (CollectionUtils.isEmptyMap(parameters)) {
- return;
- }
- List<String> ignoreCheckKeys = new ArrayList<>();
- ignoreCheckKeys.add(BACKUP_KEY);
- String ignoreCheckKeysStr = parameters.get(IGNORE_CHECK_KEYS);
- if (!StringUtils.isBlank(ignoreCheckKeysStr)) {
- ignoreCheckKeys.addAll(Arrays.asList(ignoreCheckKeysStr.split(",")));
- }
- for (Map.Entry<String, String> entry : parameters.entrySet()) {
- if (!ignoreCheckKeys.contains(entry.getKey())) {
- checkNameHasSymbol(entry.getKey(), entry.getValue());
- }
- }
- }
-
- public static void checkProperty(String property, String value, int maxlength, Pattern pattern) {
- if (StringUtils.isEmpty(value)) {
- return;
- }
- if (value.length() > maxlength) {
- logger.error(CONFIG_PARAMETER_FORMAT_ERROR, "the value content is too long", "", "Parameter value format error. Invalid " +
- property + "=\"" + value + "\" is longer than " + maxlength);
- }
- if (pattern != null) {
- Matcher matcher = pattern.matcher(value);
- if (!matcher.matches()) {
- logger.error(CONFIG_PARAMETER_FORMAT_ERROR, "the value content is illegal character", "", "Parameter value format error. Invalid " +
- property + "=\"" + value + "\" contains illegal " +
- "character, only digit, letter, '-', '_' or '.' is legal.");
- }
- }
- }
-
-}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/DefaultConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/DefaultConfigValidator.java
deleted file mode 100644
index 396f6afc49..0000000000
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/DefaultConfigValidator.java
+++ /dev/null
@@ -1,62 +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.config.utils;
-
-import org.apache.dubbo.config.AbstractConfig;
-import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.ConsumerConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
-import org.apache.dubbo.config.MetricsConfig;
-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.SslConfig;
-import org.apache.dubbo.config.TracingConfig;
-import org.apache.dubbo.config.context.ConfigValidator;
-
-public class DefaultConfigValidator implements ConfigValidator {
-
- @Override
- public void validate(AbstractConfig config) {
- if (config instanceof ProtocolConfig) {
- ConfigValidationUtils.validateProtocolConfig((ProtocolConfig) config);
- } else if (config instanceof RegistryConfig) {
- ConfigValidationUtils.validateRegistryConfig((RegistryConfig) config);
- } else if (config instanceof MetadataReportConfig) {
- ConfigValidationUtils.validateMetadataConfig((MetadataReportConfig) config);
- } else if (config instanceof ProviderConfig) {
- ConfigValidationUtils.validateProviderConfig((ProviderConfig) config);
- } else if (config instanceof ConsumerConfig) {
- ConfigValidationUtils.validateConsumerConfig((ConsumerConfig) config);
- } else if (config instanceof ApplicationConfig) {
- ConfigValidationUtils.validateApplicationConfig((ApplicationConfig) config);
- } else if (config instanceof MonitorConfig) {
- ConfigValidationUtils.validateMonitorConfig((MonitorConfig) config);
- } else if (config instanceof ModuleConfig) {
- ConfigValidationUtils.validateModuleConfig((ModuleConfig) config);
- } else if (config instanceof MetricsConfig) {
- ConfigValidationUtils.validateMetricsConfig((MetricsConfig) config);
- } else if (config instanceof TracingConfig) {
- ConfigValidationUtils.validateTracingConfig((TracingConfig) config);
- } else if (config instanceof SslConfig) {
- ConfigValidationUtils.validateSslConfig((SslConfig) config);
- }
- }
-
-}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ConfigCenterConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ConfigCenterConfigValidator.java
new file mode 100644
index 0000000000..a67580c05c
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ConfigCenterConfigValidator.java
@@ -0,0 +1,44 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.ConfigCenterConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+
+//TODO: Move to configcenter-api
+@Activate
+public class ConfigCenterConfigValidator implements ConfigValidator<ConfigCenterConfig> {
+
+ public static void validateConfigCenterConfig(ConfigCenterConfig config) {
+ if (config != null) {
+ ConfigValidationUtils.checkParameterName(config.getParameters());
+ }
+ }
+
+ @Override
+ public boolean validate(ConfigCenterConfig config) {
+ validateConfigCenterConfig(config);
+ return true;
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return ConfigCenterConfig.class.equals(configClass);
+ }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ConsumerConfigValidator.java
similarity index 53%
copy from dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
copy to dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ConsumerConfigValidator.java
index 7d20b1b658..7c145ebfd2 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ConsumerConfigValidator.java
@@ -14,12 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.context;
+package org.apache.dubbo.config.validator;
-import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
-public interface ConfigValidator {
+@Activate
+public class ConsumerConfigValidator implements ConfigValidator<ConsumerConfig> {
- void validate(AbstractConfig config);
+ public static void validateConsumerConfig(ConsumerConfig config) {
+ //TODO
+ if (config == null) {
+ }
+ }
+ @Override
+ public boolean validate(ConsumerConfig config) {
+ validateConsumerConfig(config);
+ return true;
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return ConsumerConfig.class.isAssignableFrom(configClass);
+ }
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/InterfaceConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/InterfaceConfigValidator.java
new file mode 100644
index 0000000000..4a55275338
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/InterfaceConfigValidator.java
@@ -0,0 +1,68 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.config.AbstractInterfaceConfig;
+import org.apache.dubbo.config.MethodConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.rpc.Filter;
+import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.cluster.Cluster;
+import org.apache.dubbo.rpc.cluster.filter.ClusterFilter;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.FILTER_KEY;
+import static org.apache.dubbo.config.Constants.LAYER_KEY;
+import static org.apache.dubbo.rpc.Constants.LOCAL_KEY;
+import static org.apache.dubbo.rpc.Constants.PROXY_KEY;
+
+@Activate
+public class InterfaceConfigValidator implements ConfigValidator<AbstractInterfaceConfig> {
+
+ public static void validateAbstractInterfaceConfig(AbstractInterfaceConfig config) {
+ ConfigValidationUtils.checkName(LOCAL_KEY, config.getLocal());
+ ConfigValidationUtils.checkName("stub", config.getStub());
+ ConfigValidationUtils.checkMultiName("owner", config.getOwner());
+
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), ProxyFactory.class, PROXY_KEY, config.getProxy());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), Cluster.class, CLUSTER_KEY, config.getCluster());
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), Arrays.asList(Filter.class, ClusterFilter.class), FILTER_KEY, config.getFilter());
+ ConfigValidationUtils.checkNameHasSymbol(LAYER_KEY, config.getLayer());
+
+ List<MethodConfig> methods = config.getMethods();
+ if (CollectionUtils.isNotEmpty(methods)) {
+ methods.forEach(MethodConfig::validate);
+ }
+ }
+
+ @Override
+ public boolean validate(AbstractInterfaceConfig config) {
+ validateAbstractInterfaceConfig(config);
+ return true;
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return AbstractInterfaceConfig.class.isAssignableFrom(configClass);
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/MethodConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/MethodConfigValidator.java
new file mode 100644
index 0000000000..811cd952ae
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/MethodConfigValidator.java
@@ -0,0 +1,63 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.MethodConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.rpc.cluster.LoadBalance;
+
+import static org.apache.dubbo.common.constants.CommonConstants.LOADBALANCE_KEY;
+import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
+import static org.apache.dubbo.rpc.Constants.FAIL_PREFIX;
+import static org.apache.dubbo.rpc.Constants.FORCE_PREFIX;
+import static org.apache.dubbo.rpc.Constants.MOCK_KEY;
+import static org.apache.dubbo.rpc.Constants.RETURN_PREFIX;
+import static org.apache.dubbo.rpc.Constants.THROW_PREFIX;
+
+@Activate
+public class MethodConfigValidator implements ConfigValidator<MethodConfig> {
+
+ public static void validateMethodConfig(MethodConfig config) {
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), LoadBalance.class, LOADBALANCE_KEY, config.getLoadbalance());
+ ConfigValidationUtils.checkParameterName(config.getParameters());
+ ConfigValidationUtils.checkMethodName("name", config.getName());
+
+ String mock = config.getMock();
+ if (isNotEmpty(mock)) {
+ if (mock.startsWith(RETURN_PREFIX) || mock.startsWith(THROW_PREFIX + " ")) {
+ ConfigValidationUtils.checkLength(MOCK_KEY, mock);
+ } else if (mock.startsWith(FAIL_PREFIX) || mock.startsWith(FORCE_PREFIX)) {
+ ConfigValidationUtils.checkNameHasSymbol(MOCK_KEY, mock);
+ } else {
+ ConfigValidationUtils.checkName(MOCK_KEY, mock);
+ }
+ }
+ }
+
+ @Override
+ public boolean validate(MethodConfig config) {
+ validateMethodConfig(config);
+ return true;
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return MethodConfig.class.equals(configClass);
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ProviderConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ProviderConfigValidator.java
new file mode 100644
index 0000000000..1d7b4df139
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ProviderConfigValidator.java
@@ -0,0 +1,58 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.status.StatusChecker;
+import org.apache.dubbo.common.threadpool.ThreadPool;
+import org.apache.dubbo.config.ProviderConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.remoting.Transporter;
+import org.apache.dubbo.remoting.exchange.Exchanger;
+import org.apache.dubbo.remoting.telnet.TelnetHandler;
+
+import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY;
+import static org.apache.dubbo.config.Constants.CONTEXTPATH_KEY;
+import static org.apache.dubbo.config.Constants.STATUS_KEY;
+import static org.apache.dubbo.remoting.Constants.EXCHANGER_KEY;
+import static org.apache.dubbo.remoting.Constants.TELNET_KEY;
+import static org.apache.dubbo.remoting.Constants.TRANSPORTER_KEY;
+
+@Activate
+public class ProviderConfigValidator implements ConfigValidator<ProviderConfig> {
+
+ @Override
+ public boolean validate(ProviderConfig config) {
+ validateProviderConfig(config);
+ return true;
+ }
+
+ public static void validateProviderConfig(ProviderConfig config) {
+ ConfigValidationUtils.checkPathName(CONTEXTPATH_KEY, config.getContextpath());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), ThreadPool.class, THREADPOOL_KEY, config.getThreadpool());
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), TelnetHandler.class, TELNET_KEY, config.getTelnet());
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), StatusChecker.class, STATUS_KEY, config.getStatus());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), Transporter.class, TRANSPORTER_KEY, config.getTransporter());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), Exchanger.class, EXCHANGER_KEY, config.getExchanger());
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return ProviderConfig.class.isAssignableFrom(configClass);
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ReferenceConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ReferenceConfigValidator.java
new file mode 100644
index 0000000000..b804d62db2
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ReferenceConfigValidator.java
@@ -0,0 +1,65 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.ConsumerConfig;
+import org.apache.dubbo.config.ReferenceConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.rpc.InvokerListener;
+
+import java.util.List;
+
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
+
+@Activate
+public class ReferenceConfigValidator implements ConfigValidator<ReferenceConfig<?>> {
+
+ @Override
+ public boolean validate(ReferenceConfig<?> config) {
+ validateReferenceConfig(config);
+ return true;
+ }
+
+ public static void validateReferenceConfig(ReferenceConfig<?> config) {
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), InvokerListener.class, "listener", config.getListener());
+ ConfigValidationUtils.checkKey(VERSION_KEY, config.getVersion());
+ ConfigValidationUtils.checkKey(GROUP_KEY, config.getGroup());
+ ConfigValidationUtils.checkName(CLIENT_KEY, config.getClient());
+
+ List<RegistryConfig> registries = config.getRegistries();
+ if (registries != null) {
+ for (RegistryConfig registry : registries) {
+ registry.validate();
+ }
+ }
+
+ ConsumerConfig consumerConfig = config.getConsumer();
+ if (consumerConfig != null) {
+ consumerConfig.validate();
+ }
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return ReferenceConfig.class.equals(configClass);
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ServiceConfigValidator.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ServiceConfigValidator.java
new file mode 100644
index 0000000000..bea8a54ab0
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/validator/ServiceConfigValidator.java
@@ -0,0 +1,78 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+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.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.rpc.ExporterListener;
+
+import java.util.List;
+
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
+
+@Activate
+public class ServiceConfigValidator implements ConfigValidator<ServiceConfig<?>> {
+
+ public static void validateServiceConfig(ServiceConfig<?> config) {
+
+ ConfigValidationUtils.checkKey(VERSION_KEY, config.getVersion());
+ ConfigValidationUtils.checkKey(GROUP_KEY, config.getGroup());
+ ConfigValidationUtils.checkName(TOKEN_KEY, config.getToken());
+ ConfigValidationUtils.checkPathName(PATH_KEY, config.getPath());
+
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), ExporterListener.class, "listener", config.getListener());
+
+ List<RegistryConfig> registries = config.getRegistries();
+ if (registries != null) {
+ for (RegistryConfig registry : registries) {
+ registry.validate();
+ }
+ }
+
+ List<ProtocolConfig> protocols = config.getProtocols();
+ if (protocols != null) {
+ for (ProtocolConfig protocol : protocols) {
+ protocol.validate();
+ }
+ }
+
+ ProviderConfig providerConfig = config.getProvider();
+ if (providerConfig != null) {
+ providerConfig.validate();
+ }
+ }
+
+ @Override
+ public boolean validate(ServiceConfig<?> config) {
+ validateServiceConfig(config);
+ return true;
+ }
+
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return ServiceConfig.class.equals(configClass);
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
new file mode 100644
index 0000000000..6ab0e95080
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
@@ -0,0 +1,8 @@
+config-center=org.apache.dubbo.config.validator.ConfigCenterConfigValidator
+consumer=org.apache.dubbo.config.validator.ConsumerConfigValidator
+interface=org.apache.dubbo.config.validator.InterfaceConfigValidator
+method=org.apache.dubbo.config.validator.MethodConfigValidator
+provider=org.apache.dubbo.config.validator.ProviderConfigValidator
+reference=org.apache.dubbo.config.validator.ReferenceConfigValidator
+service=org.apache.dubbo.config.validator.ServiceConfigValidator
+
diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.deploy.lifecycle.application.ApplicationLifecycle b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.deploy.lifecycle.application.ApplicationLifecycle
index ca779fe73f..8e806008f2 100644
--- a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.deploy.lifecycle.application.ApplicationLifecycle
+++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.deploy.lifecycle.application.ApplicationLifecycle
@@ -3,3 +3,4 @@ config-post-handle=org.apache.dubbo.config.deploy.lifecycle.application.Applicat
module-initialize=org.apache.dubbo.config.deploy.lifecycle.application.ModuleInitializeLifecycle
post-offline=org.apache.dubbo.config.deploy.lifecycle.application.ApplicationPostOfflineLifecycle
app-prepare=org.apache.dubbo.config.deploy.lifecycle.application.ApplicationPrepareLifecycle
+validator-registry=org.apache.dubbo.config.deploy.lifecycle.application.ValidatorRegistryDeployListener
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
index 1a986a5884..55bcbae629 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/AbstractConfigTest.java
@@ -131,7 +131,7 @@ class AbstractConfigTest {
protocolConfig.setCodec("exchange");
protocolConfig.setName("test");
protocolConfig.setHost("host");
- ConfigValidationUtils.validateProtocolConfig(protocolConfig);
+ protocolConfig.validate();
}
@Test
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigValidatorExistTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigValidatorExistTest.java
new file mode 100644
index 0000000000..980ce01583
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ConfigValidatorExistTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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;
+
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.validator.ConsumerConfigValidator;
+import org.apache.dubbo.config.validator.InterfaceConfigValidator;
+import org.apache.dubbo.config.validator.MethodConfigValidator;
+import org.apache.dubbo.config.validator.ProviderConfigValidator;
+import org.apache.dubbo.config.validator.ReferenceConfigValidator;
+import org.apache.dubbo.config.validator.ServiceConfigValidator;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.FrameworkModel;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+import org.mockito.Mockito;
+
+import java.util.List;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+
+
+public class ConfigValidatorExistTest {
+
+ ConfigValidateFacade validateFacade;
+
+ @Test
+ void testConfigValidatorExist(){
+ FrameworkModel frameworkModel = FrameworkModel.defaultModel();
+ ApplicationModel applicationModel = frameworkModel.newApplication();
+
+ validateFacade = new ConfigValidateFacade(applicationModel);
+ Assertions.assertNotNull(validateFacade);
+ Assertions.assertTrue(validateFacade.getValidators().size() >= 7);
+
+ try(
+ MockedStatic<ConsumerConfigValidator> configValidatorMockedStatic = Mockito.mockStatic(ConsumerConfigValidator.class);
+ MockedStatic<InterfaceConfigValidator> interfaceConfigValidatorMockedStatic = Mockito.mockStatic(InterfaceConfigValidator.class);
+ MockedStatic<MethodConfigValidator> methodConfigValidatorMockedStatic = Mockito.mockStatic(MethodConfigValidator.class);
+ MockedStatic<ProviderConfigValidator> providerConfigValidatorMockedStatic = Mockito.mockStatic(ProviderConfigValidator.class);
+ MockedStatic<ReferenceConfigValidator> referenceConfigValidatorMockedStatic = Mockito.mockStatic(ReferenceConfigValidator.class);
+ MockedStatic<ServiceConfigValidator> serviceConfigValidatorMockedStatic = Mockito.mockStatic(ServiceConfigValidator.class);
+ ){
+ configValidatorMockedStatic.when(()-> ConsumerConfigValidator.validateConsumerConfig(any())).thenCallRealMethod();
+ interfaceConfigValidatorMockedStatic.when(()-> InterfaceConfigValidator.validateAbstractInterfaceConfig(any())).thenCallRealMethod();
+ methodConfigValidatorMockedStatic.when(()-> MethodConfigValidator.validateMethodConfig(any())).thenCallRealMethod();
+ providerConfigValidatorMockedStatic.when(()-> ProviderConfigValidator.validateProviderConfig(any())).thenCallRealMethod();
+ referenceConfigValidatorMockedStatic.when(()-> ReferenceConfigValidator.validateReferenceConfig(any())).thenCallRealMethod();
+ serviceConfigValidatorMockedStatic.when(()->ServiceConfigValidator.validateServiceConfig(any())).thenCallRealMethod();
+ triggerValidate(new ConsumerConfig());
+ triggerValidate(new AbstractInterfaceConfig() {
+ @Override
+ public List<URL> getExportedUrls() {
+ return super.getExportedUrls();
+ }
+ });
+ triggerValidate(new MethodConfig());
+ triggerValidate(new ProviderConfig());
+ triggerValidate(new ReferenceConfig<>());
+ triggerValidate(new ServiceConfig<>());
+
+ configValidatorMockedStatic.verify(()-> ConsumerConfigValidator.validateConsumerConfig(any()),atLeastOnce());
+ interfaceConfigValidatorMockedStatic.verify(()-> InterfaceConfigValidator.validateAbstractInterfaceConfig(any()),atLeastOnce());
+ methodConfigValidatorMockedStatic.verify(()->MethodConfigValidator.validateMethodConfig(any()),atLeastOnce());
+ providerConfigValidatorMockedStatic.verify(()->ProviderConfigValidator.validateProviderConfig(any()),atLeastOnce());
+ referenceConfigValidatorMockedStatic.verify(()->ReferenceConfigValidator.validateReferenceConfig(any()),atLeastOnce());
+ serviceConfigValidatorMockedStatic.verify(()-> ServiceConfigValidator.validateServiceConfig(any()),atLeastOnce());
+ }
+ }
+
+ void triggerValidate(AbstractConfig config){
+ try {
+ validateFacade.validate(config);
+ }catch (Throwable ignored){};
+ }
+
+}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
index 92e6e2b595..83793deab2 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/DubboBootstrapTest.java
@@ -35,6 +35,7 @@ import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
import org.apache.dubbo.config.metadata.ExporterDeployListener;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.config.validator.ApplicationConfigValidator;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.monitor.MonitorService;
import org.apache.dubbo.registry.RegistryService;
@@ -42,6 +43,7 @@ import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol;
import org.apache.dubbo.test.check.registrycenter.config.ZookeeperRegistryCenterConfig;
+import org.apache.dubbo.util.MonitorUrlUtil;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@@ -114,13 +116,13 @@ class DubboBootstrapTest {
writeDubboProperties(SHUTDOWN_WAIT_KEY, "100");
ApplicationModel.defaultModel().modelEnvironment().getPropertiesConfiguration().refresh();
- ConfigValidationUtils.validateApplicationConfig(new ApplicationConfig("demo"));
+ ApplicationConfigValidator.validateApplicationConfig(new ApplicationConfig("demo"));
Assertions.assertEquals("100", System.getProperty(SHUTDOWN_WAIT_KEY));
System.clearProperty(SHUTDOWN_WAIT_KEY);
writeDubboProperties(SHUTDOWN_WAIT_SECONDS_KEY, "1000");
ApplicationModel.defaultModel().modelEnvironment().getPropertiesConfiguration().refresh();
- ConfigValidationUtils.validateApplicationConfig(new ApplicationConfig("demo"));
+ ApplicationConfigValidator.validateApplicationConfig(new ApplicationConfig("demo"));
Assertions.assertEquals("1000", System.getProperty(SHUTDOWN_WAIT_SECONDS_KEY));
} finally {
System.clearProperty("dubbo.application.name");
@@ -162,7 +164,7 @@ class DubboBootstrapTest {
void testLoadUserMonitor_address_only() {
// -Ddubbo.monitor.address=monitor-addr:12080
SysProps.setProperty(DUBBO_MONITOR_ADDRESS, "monitor-addr:12080");
- URL url = ConfigValidationUtils.loadMonitor(getTestInterfaceConfig(new MonitorConfig()), new ServiceConfigURL("dubbo", "addr1", 9090));
+ URL url = MonitorUrlUtil.loadMonitor(getTestInterfaceConfig(new MonitorConfig()), new ServiceConfigURL("dubbo", "addr1", 9090));
Assertions.assertEquals("monitor-addr:12080", url.getAddress());
Assertions.assertEquals(MonitorService.class.getName(), url.getParameter("interface"));
Assertions.assertNotNull(url.getParameter("dubbo"));
@@ -176,7 +178,7 @@ class DubboBootstrapTest {
MonitorConfig monitorConfig = new MonitorConfig();
monitorConfig.setProtocol("registry");
- URL url = ConfigValidationUtils.loadMonitor(getTestInterfaceConfig(monitorConfig), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
+ URL url = MonitorUrlUtil.loadMonitor(getTestInterfaceConfig(monitorConfig), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
Assertions.assertEquals("dubbo", url.getProtocol());
Assertions.assertEquals("registry", url.getParameter("protocol"));
}
@@ -187,14 +189,14 @@ class DubboBootstrapTest {
MonitorConfig monitorConfig = new MonitorConfig();
monitorConfig.setProtocol("service-discovery-registry");
- URL url = ConfigValidationUtils.loadMonitor(getTestInterfaceConfig(monitorConfig), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
+ URL url = MonitorUrlUtil.loadMonitor(getTestInterfaceConfig(monitorConfig), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
Assertions.assertEquals("dubbo", url.getProtocol());
Assertions.assertEquals("service-discovery-registry", url.getParameter("protocol"));
}
@Test
void testLoadUserMonitor_no_monitor() {
- URL url = ConfigValidationUtils.loadMonitor(getTestInterfaceConfig(null), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
+ URL url = MonitorUrlUtil.loadMonitor(getTestInterfaceConfig(null), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
Assertions.assertNull(url);
}
@@ -204,7 +206,7 @@ class DubboBootstrapTest {
MonitorConfig monitorConfig = new MonitorConfig();
monitorConfig.setProtocol("user");
- URL url = ConfigValidationUtils.loadMonitor(getTestInterfaceConfig(monitorConfig), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
+ URL url = MonitorUrlUtil.loadMonitor(getTestInterfaceConfig(monitorConfig), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
Assertions.assertEquals("user", url.getProtocol());
}
@@ -213,7 +215,7 @@ class DubboBootstrapTest {
// dubbo.monitor.address=user://1.2.3.4:5678?k=v
MonitorConfig monitorConfig = new MonitorConfig();
monitorConfig.setAddress("user://1.2.3.4:5678?param1=value1");
- URL url = ConfigValidationUtils.loadMonitor(getTestInterfaceConfig(monitorConfig), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
+ URL url = MonitorUrlUtil.loadMonitor(getTestInterfaceConfig(monitorConfig), URL.valueOf(ZookeeperRegistryCenterConfig.getConnectionAddress()));
Assertions.assertEquals("user", url.getProtocol());
Assertions.assertEquals("1.2.3.4:5678", url.getAddress());
Assertions.assertEquals("value1", url.getParameter("param1"));
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java
index bd059ffb2a..d5bd6eac65 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/utils/ConfigValidationUtilsTest.java
@@ -20,7 +20,9 @@ import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
import org.apache.dubbo.config.AbstractInterfaceConfig;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetadataReportConfig;
-
+import org.apache.dubbo.config.exception.ConfigValidationException;
+import org.apache.dubbo.config.validator.ApplicationConfigValidator;
+import org.apache.dubbo.config.validator.MetadataConfigValidator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
@@ -29,9 +31,12 @@ import org.mockito.Mockito;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
+import java.util.regex.Pattern;
import static org.apache.dubbo.common.constants.LoggerCodeConstants.COMMON_CLASS_NOT_FOUND;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -45,7 +50,7 @@ class ConfigValidationUtilsTest {
MetadataReportConfig config = new MetadataReportConfig();
config.setAddress("protocol://ip:host");
try {
- ConfigValidationUtils.validateMetadataConfig(config);
+ MetadataConfigValidator.validateMetadataConfig(config);
} catch (Exception e) {
Assertions.fail("valid config expected.");
}
@@ -53,7 +58,7 @@ class ConfigValidationUtilsTest {
config.setAddress("ip:host");
config.setProtocol("protocol");
try {
- ConfigValidationUtils.validateMetadataConfig(config);
+ MetadataConfigValidator.validateMetadataConfig(config);
} catch (Exception e) {
Assertions.fail("valid config expected.");
}
@@ -61,17 +66,18 @@ class ConfigValidationUtilsTest {
config.setAddress("ip:host");
config.setProtocol(null);
Assertions.assertThrows(IllegalArgumentException.class, () -> {
- ConfigValidationUtils.validateMetadataConfig(config);
+ MetadataConfigValidator.validateMetadataConfig(config);
});
}
@Test
void testValidateApplicationConfig() throws Exception {
- try (MockedStatic<ConfigValidationUtils> mockedStatic = Mockito.mockStatic(ConfigValidationUtils.class);) {
- mockedStatic.when(() -> ConfigValidationUtils.validateApplicationConfig(any())).thenCallRealMethod();
+ try (MockedStatic<ApplicationConfigValidator> mockedStatic = Mockito.mockStatic(ApplicationConfigValidator.class);
+ MockedStatic<ConfigValidationUtils> configValidationUtilsMockedStatic = Mockito.mockStatic(ConfigValidationUtils.class);) {
+ mockedStatic.when(() -> ApplicationConfigValidator.validateApplicationConfig(any())).thenCallRealMethod();
ApplicationConfig config = new ApplicationConfig();
- Assertions.assertThrows(IllegalStateException.class, () -> {
- ConfigValidationUtils.validateApplicationConfig(config);
+ Assertions.assertThrows(ConfigValidationException.class, () -> {
+ ApplicationConfigValidator.validateApplicationConfig(config);
});
config.setName("testName");
@@ -83,14 +89,19 @@ class ConfigValidationUtilsTest {
map.put("k1", "v1");
map.put("k2", "v2");
config.setParameters(map);
- ConfigValidationUtils.validateApplicationConfig(config);
- mockedStatic.verify(() -> {
+ ApplicationConfigValidator.validateApplicationConfig(config);
+
+ configValidationUtilsMockedStatic.when(()-> ConfigValidationUtils.checkName(anyString(),anyString())).thenCallRealMethod();
+ configValidationUtilsMockedStatic.when(()-> ConfigValidationUtils.checkMultiName(anyString(),anyString())).thenCallRealMethod();
+ configValidationUtilsMockedStatic.when(()-> ConfigValidationUtils.checkParameterName(any())).thenCallRealMethod();
+ configValidationUtilsMockedStatic.when(()-> ConfigValidationUtils.checkProperty(anyString(),anyString(),anyInt(),any(Pattern.class))).thenCallRealMethod();
+ configValidationUtilsMockedStatic.verify(() -> {
ConfigValidationUtils.checkName(any(), any());
}, times(4));
- mockedStatic.verify(() -> {
+ configValidationUtilsMockedStatic.verify(() -> {
ConfigValidationUtils.checkMultiName(any(), any());
}, times(1));
- mockedStatic.verify(() -> {
+ configValidationUtilsMockedStatic.verify(() -> {
ConfigValidationUtils.checkParameterName(any());
}, times(1));
}
@@ -98,13 +109,13 @@ class ConfigValidationUtilsTest {
@Test
void testCheckQosInApplicationConfig() throws Exception {
- ConfigValidationUtils mock = Mockito.mock(ConfigValidationUtils.class);
+ ApplicationConfigValidator mock = Mockito.mock(ApplicationConfigValidator.class);
ErrorTypeAwareLogger loggerMock = Mockito.mock(ErrorTypeAwareLogger.class);
injectField(mock.getClass().getDeclaredField("logger"), loggerMock);
ApplicationConfig config = new ApplicationConfig();
config.setName("testName");
config.setQosEnable(false);
- mock.validateApplicationConfig(config);
+ ApplicationConfigValidator.validateApplicationConfig(config);
verify(loggerMock, never()).warn(any(), any(Throwable.class));
config.setQosEnable(true);
diff --git a/dubbo-distribution/dubbo-all/pom.xml b/dubbo-distribution/dubbo-all/pom.xml
index 8f8efd3369..60f9d50e5b 100644
--- a/dubbo-distribution/dubbo-all/pom.xml
+++ b/dubbo-distribution/dubbo-all/pom.xml
@@ -1590,6 +1590,13 @@
META-INF/dubbo/internal/org.apache.dubbo.config.CommonConfigPostProcessor
</resource>
</transformer>
+
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+ <resource>
+ META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
+ </resource>
+ </transformer>
</transformers>
<filters>
<filter>
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/config/validator/MetadataConfigValidator.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/config/validator/MetadataConfigValidator.java
new file mode 100644
index 0000000000..d0beb62714
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/config/validator/MetadataConfigValidator.java
@@ -0,0 +1,64 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.MetadataReportConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+
+import static org.apache.dubbo.common.utils.StringUtils.isEmpty;
+
+@Activate
+public class MetadataConfigValidator implements ConfigValidator<MetadataReportConfig> {
+
+ @Override
+ public boolean validate(MetadataReportConfig config) {
+ return validateMetadataConfig(config);
+ }
+
+ public static boolean validateMetadataConfig(MetadataReportConfig metadataReportConfig) {
+ if (!isValidMetadataConfig(metadataReportConfig)) {
+ return false;
+ }
+
+ String address = metadataReportConfig.getAddress();
+ String protocol = metadataReportConfig.getProtocol();
+
+ if ((isEmpty(address) || !address.contains("://")) && isEmpty(protocol)) {
+ throw new IllegalArgumentException("Please specify valid protocol or address for metadata report " + address);
+ }
+ return true;
+ }
+
+ public static boolean isValidMetadataConfig(MetadataReportConfig metadataReportConfig) {
+ if (metadataReportConfig == null) {
+ return false;
+ }
+
+ if (Boolean.FALSE.equals(metadataReportConfig.getReportMetadata()) &&
+ Boolean.FALSE.equals(metadataReportConfig.getReportDefinition())) {
+ return false;
+ }
+
+ return !isEmpty(metadataReportConfig.getAddress());
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return MetadataReportConfig.class.isAssignableFrom(configClass);
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
new file mode 100644
index 0000000000..5301ecbc08
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
@@ -0,0 +1 @@
+metadata=org.apache.dubbo.config.validator.MetadataConfigValidator
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/config/validator/MetricsConfigValidator.java
similarity index 53%
copy from dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
copy to dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/config/validator/MetricsConfigValidator.java
index 7d20b1b658..f1fbc062e0 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/java/org/apache/dubbo/config/validator/MetricsConfigValidator.java
@@ -14,12 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.context;
+package org.apache.dubbo.config.validator;
-import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.MetricsConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
-public interface ConfigValidator {
+@Activate
+public class MetricsConfigValidator implements ConfigValidator<MetricsConfig> {
- void validate(AbstractConfig config);
+ public static void validateMetricsConfig(MetricsConfig metricsConfig) {
+ //TODO
+ if (metricsConfig == null) {
+ }
+ }
+ @Override
+ public boolean validate(MetricsConfig config) {
+ validateMetricsConfig(config);
+ return true;
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return MetricsConfig.class.isAssignableFrom(configClass);
+ }
}
diff --git a/dubbo-metrics/dubbo-metrics-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator b/dubbo-metrics/dubbo-metrics-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
new file mode 100644
index 0000000000..2716b9c85f
--- /dev/null
+++ b/dubbo-metrics/dubbo-metrics-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
@@ -0,0 +1 @@
+metrics=org.apache.dubbo.config.validator.MetricsConfigValidator
diff --git a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java
index 9fd5257cc5..1e4ecebbe8 100644
--- a/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java
+++ b/dubbo-metrics/dubbo-metrics-default/src/test/java/org/apache/dubbo/metrics/collector/DefaultCollectorTest.java
@@ -33,7 +33,6 @@ import org.apache.dubbo.metrics.model.key.MetricsKey;
import org.apache.dubbo.metrics.model.key.MetricsKeyWrapper;
import org.apache.dubbo.metrics.model.key.MetricsLevel;
import org.apache.dubbo.metrics.model.key.MetricsPlaceValue;
-import org.apache.dubbo.metrics.model.key.TypeWrapper;
import org.apache.dubbo.metrics.model.sample.CounterMetricSample;
import org.apache.dubbo.metrics.model.sample.GaugeMetricSample;
import org.apache.dubbo.metrics.model.sample.MetricSample;
@@ -45,7 +44,6 @@ import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
-
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
@@ -157,7 +155,8 @@ class DefaultCollectorTest {
// push finish rt +1
List<MetricSample> metricSamples = collector.collect();
//num(total+success+processing) + rt(5) + error code = 9
- Assertions.assertEquals(metricSamples.size(),9);
+ Assertions.assertEquals(9, metricSamples.size());
+
List<String> metricsNames = metricSamples.stream().map(MetricSample::getName).collect(Collectors.toList());
// No error will contain total+success+processing
String REQUESTS = new MetricsKeyWrapper(METRIC_REQUESTS, MetricsPlaceValue.of(side, MetricsLevel.SERVICE)).targetKey();
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java b/dubbo-metrics/dubbo-tracing/src/main/java/org/apache/dubbo/config/validator/TracingConfigValidator.java
similarity index 53%
copy from dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
copy to dubbo-metrics/dubbo-tracing/src/main/java/org/apache/dubbo/config/validator/TracingConfigValidator.java
index 7d20b1b658..a975dc019a 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
+++ b/dubbo-metrics/dubbo-tracing/src/main/java/org/apache/dubbo/config/validator/TracingConfigValidator.java
@@ -14,12 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.context;
+package org.apache.dubbo.config.validator;
-import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.TracingConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
-public interface ConfigValidator {
+@Activate
+public class TracingConfigValidator implements ConfigValidator<TracingConfig> {
- void validate(AbstractConfig config);
+ public static void validateTracingConfig(TracingConfig tracingConfig) {
+ // TODO
+ if (tracingConfig == null) {
+ }
+ }
+ @Override
+ public boolean validate(TracingConfig config) {
+ validateTracingConfig(config);
+ return true;
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return TracingConfig.class.isAssignableFrom(configClass);
+ }
}
diff --git a/dubbo-metrics/dubbo-tracing/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator b/dubbo-metrics/dubbo-tracing/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
new file mode 100644
index 0000000000..32777468ad
--- /dev/null
+++ b/dubbo-metrics/dubbo-tracing/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
@@ -0,0 +1 @@
+tracing=org.apache.dubbo.config.validator.TracingConfigValidator
diff --git a/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/util/MonitorUrlUtil.java b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/util/MonitorUrlUtil.java
new file mode 100644
index 0000000000..23fd61e9c0
--- /dev/null
+++ b/dubbo-monitor/dubbo-monitor-api/src/main/java/org/apache/dubbo/util/MonitorUrlUtil.java
@@ -0,0 +1,102 @@
+/*
+ * 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.util;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.URLBuilder;
+import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.common.utils.UrlUtils;
+import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.config.AbstractInterfaceConfig;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.MonitorConfig;
+import org.apache.dubbo.monitor.Constants;
+import org.apache.dubbo.monitor.MonitorFactory;
+import org.apache.dubbo.monitor.MonitorService;
+
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_MONITOR_ADDRESS;
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
+import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
+import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL;
+import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_PROTOCOL;
+import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
+import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
+
+public class MonitorUrlUtil {
+
+ public static URL loadMonitor(AbstractInterfaceConfig interfaceConfig, URL registryURL) {
+ Map<String, String> map = new HashMap<String, String>();
+ map.put(INTERFACE_KEY, MonitorService.class.getName());
+ AbstractInterfaceConfig.appendRuntimeParameters(map);
+ //set ip
+ String hostToRegistry = ConfigUtils.getSystemProperty(DUBBO_IP_TO_REGISTRY);
+ if (StringUtils.isEmpty(hostToRegistry)) {
+ hostToRegistry = NetUtils.getLocalHost();
+ } else if (NetUtils.isInvalidLocalHost(hostToRegistry)) {
+ throw new IllegalArgumentException("Specified invalid registry ip from property:" +
+ DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
+ }
+ map.put(REGISTER_IP_KEY, hostToRegistry);
+
+ MonitorConfig monitor = interfaceConfig.getMonitor();
+ ApplicationConfig application = interfaceConfig.getApplication();
+ AbstractConfig.appendParameters(map, monitor);
+ AbstractConfig.appendParameters(map, application);
+ String address = null;
+ String sysAddress = System.getProperty(DUBBO_MONITOR_ADDRESS);
+ if (sysAddress != null && sysAddress.length() > 0) {
+ address = sysAddress;
+ } else if (monitor != null) {
+ address = monitor.getAddress();
+ }
+ String protocol = monitor == null ? null : monitor.getProtocol();
+ if (monitor != null &&
+ (REGISTRY_PROTOCOL.equals(protocol) || SERVICE_REGISTRY_PROTOCOL.equals(protocol))
+ && registryURL != null) {
+ return URLBuilder.from(registryURL)
+ .setProtocol(DUBBO_PROTOCOL)
+ .addParameter(PROTOCOL_KEY, protocol)
+ .putAttribute(REFER_KEY, map)
+ .build();
+
+ } else if (ConfigUtils.isNotEmpty(address) || ConfigUtils.isNotEmpty(protocol)) {
+ if (!map.containsKey(PROTOCOL_KEY)) {
+ if (interfaceConfig.getScopeModel().getExtensionLoader(MonitorFactory.class).hasExtension(Constants.LOGSTAT_PROTOCOL)) {
+ map.put(PROTOCOL_KEY, Constants.LOGSTAT_PROTOCOL);
+ } else if (ConfigUtils.isNotEmpty(protocol)) {
+ map.put(PROTOCOL_KEY, protocol);
+ } else {
+ map.put(PROTOCOL_KEY, DUBBO_PROTOCOL);
+ }
+ }
+ if (ConfigUtils.isEmpty(address)) {
+ address = LOCALHOST_VALUE;
+ }
+ return UrlUtils.parseURL(address, map);
+ }
+ return null;
+ }
+}
diff --git a/dubbo-monitor/dubbo-monitor-common/src/main/java/org/apache/dubbo/config/validator/MonitorConfigValidator.java b/dubbo-monitor/dubbo-monitor-common/src/main/java/org/apache/dubbo/config/validator/MonitorConfigValidator.java
new file mode 100644
index 0000000000..efcc3c1bef
--- /dev/null
+++ b/dubbo-monitor/dubbo-monitor-common/src/main/java/org/apache/dubbo/config/validator/MonitorConfigValidator.java
@@ -0,0 +1,53 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.logger.ErrorTypeAwareLogger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.config.MonitorConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+
+
+@Activate
+public class MonitorConfigValidator implements ConfigValidator<MonitorConfig> {
+
+ private static final ErrorTypeAwareLogger logger = LoggerFactory.getErrorTypeAwareLogger(MonitorConfigValidator.class);
+
+ public static boolean validateMonitorConfig(MonitorConfig config) {
+ if (config != null) {
+ if (!config.isValid()) {
+ logger.info("There's no valid monitor config found, if you want to open monitor statistics for Dubbo, " +
+ "please make sure your monitor is configured properly.");
+ return false;
+ }
+ ConfigValidationUtils.checkParameterName(config.getParameters());
+ }
+ return true;
+ }
+
+ @Override
+ public boolean validate(MonitorConfig config) {
+ return validateMonitorConfig(config);
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return MonitorConfig.class.isAssignableFrom(configClass);
+ }
+}
diff --git a/dubbo-monitor/dubbo-monitor-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator b/dubbo-monitor/dubbo-monitor-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
new file mode 100644
index 0000000000..ca6341e3da
--- /dev/null
+++ b/dubbo-monitor/dubbo-monitor-common/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
@@ -0,0 +1 @@
+monitor=org.apache.dubbo.config.validator.MonitorConfigValidator
diff --git a/dubbo-plugin/dubbo-security/src/test/java/org/apache/dubbo/security/cert/CertDeployerListenerTest.java b/dubbo-plugin/dubbo-security/src/test/java/org/apache/dubbo/security/cert/CertDeployerListenerTest.java
index ce6a5fa665..11ca883d94 100644
--- a/dubbo-plugin/dubbo-security/src/test/java/org/apache/dubbo/security/cert/CertDeployerListenerTest.java
+++ b/dubbo-plugin/dubbo-security/src/test/java/org/apache/dubbo/security/cert/CertDeployerListenerTest.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.deploy.ApplicationDeployer;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.SslConfig;
+import org.apache.dubbo.config.exception.ConfigValidationException;
import org.apache.dubbo.rpc.model.ApplicationModel;
import org.apache.dubbo.rpc.model.FrameworkModel;
@@ -111,7 +112,7 @@ class CertDeployerListenerTest {
applicationModel.getApplicationConfigManager().addMetadataReport(new MetadataReportConfig("absent"));
ApplicationDeployer deployer = applicationModel.getDeployer();
- Assertions.assertThrows(IllegalArgumentException.class, deployer::start);
+ Assertions.assertThrows(ConfigValidationException.class, deployer::start);
Mockito.verify(reference.get(), Mockito.times(1))
.connect(Mockito.any());
Mockito.verify(reference.get(), Mockito.atLeast(1))
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/config/validate/RegistryConfigValidator.java b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/config/validate/RegistryConfigValidator.java
new file mode 100644
index 0000000000..ce40b7a974
--- /dev/null
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/config/validate/RegistryConfigValidator.java
@@ -0,0 +1,56 @@
+/*
+ * 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.validate;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+
+import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PASSWORD_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PROTOCOL_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.USERNAME_KEY;
+import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
+import static org.apache.dubbo.remoting.Constants.SERVER_KEY;
+import static org.apache.dubbo.remoting.Constants.TRANSPORTER_KEY;
+
+@Activate
+public class RegistryConfigValidator implements ConfigValidator<RegistryConfig> {
+
+ @Override
+ public boolean validate(RegistryConfig config) {
+ validateRegistryConfig(config);
+ return true;
+ }
+
+ public static void validateRegistryConfig(RegistryConfig config) {
+ ConfigValidationUtils.checkName(PROTOCOL_KEY, config.getProtocol());
+ ConfigValidationUtils.checkName(USERNAME_KEY, config.getUsername());
+ ConfigValidationUtils.checkLength(PASSWORD_KEY, config.getPassword());
+ ConfigValidationUtils.checkPathLength(FILE_KEY, config.getFile());
+ ConfigValidationUtils.checkName(TRANSPORTER_KEY, config.getTransporter());
+ ConfigValidationUtils.checkName(SERVER_KEY, config.getServer());
+ ConfigValidationUtils.checkName(CLIENT_KEY, config.getClient());
+ ConfigValidationUtils.checkParameterName(config.getParameters());
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return RegistryConfig.class.isAssignableFrom(configClass);
+ }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/config/validator/SslConfigValidator.java
similarity index 56%
copy from dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
copy to dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/config/validator/SslConfigValidator.java
index 7d20b1b658..d6bf0374fc 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigValidator.java
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/java/org/apache/dubbo/config/validator/SslConfigValidator.java
@@ -14,12 +14,27 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.context;
+package org.apache.dubbo.config.validator;
-import org.apache.dubbo.config.AbstractConfig;
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.config.SslConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
-public interface ConfigValidator {
+@Activate
+public class SslConfigValidator implements ConfigValidator<SslConfig> {
- void validate(AbstractConfig config);
+ public static void validateSslConfig(SslConfig sslConfig) {
+ // TODO
+ }
+ @Override
+ public boolean validate(SslConfig config) {
+ validateSslConfig(config);
+ return true;
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return SslConfig.class.isAssignableFrom(configClass);
+ }
}
diff --git a/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator b/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
new file mode 100644
index 0000000000..56a39d1693
--- /dev/null
+++ b/dubbo-remoting/dubbo-remoting-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
@@ -0,0 +1 @@
+ssl=org.apache.dubbo.config.validator.SslConfigValidator
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/config/validator/ProtocolConfigValidator.java b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/config/validator/ProtocolConfigValidator.java
new file mode 100644
index 0000000000..2884bf4030
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/config/validator/ProtocolConfigValidator.java
@@ -0,0 +1,82 @@
+/*
+ * 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.validator;
+
+import org.apache.dubbo.common.extension.Activate;
+import org.apache.dubbo.common.serialize.Serialization;
+import org.apache.dubbo.common.status.StatusChecker;
+import org.apache.dubbo.common.threadpool.ThreadPool;
+import org.apache.dubbo.config.ProtocolConfig;
+import org.apache.dubbo.config.context.ConfigValidator;
+import org.apache.dubbo.config.utils.ConfigValidationUtils;
+import org.apache.dubbo.remoting.Codec2;
+import org.apache.dubbo.remoting.Dispatcher;
+import org.apache.dubbo.remoting.Transporter;
+import org.apache.dubbo.remoting.exchange.Exchanger;
+import org.apache.dubbo.remoting.telnet.TelnetHandler;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_PROTOCOL;
+import static org.apache.dubbo.common.constants.CommonConstants.HOST_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.THREADPOOL_KEY;
+import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
+import static org.apache.dubbo.remoting.Constants.CODEC_KEY;
+import static org.apache.dubbo.remoting.Constants.DISPATCHER_KEY;
+import static org.apache.dubbo.remoting.Constants.EXCHANGER_KEY;
+import static org.apache.dubbo.remoting.Constants.SERIALIZATION_KEY;
+import static org.apache.dubbo.remoting.Constants.SERVER_KEY;
+import static org.apache.dubbo.remoting.Constants.TELNET_KEY;
+import static org.apache.dubbo.remoting.Constants.TRANSPORTER_KEY;
+
+@Activate
+public class ProtocolConfigValidator implements ConfigValidator<ProtocolConfig> {
+
+ @Override
+ public boolean validate(ProtocolConfig config) {
+ validateProtocolConfig(config);
+ return true;
+ }
+
+ public static void validateProtocolConfig(ProtocolConfig config) {
+ if (config != null) {
+ String name = config.getName();
+ ConfigValidationUtils.checkName("name", name);
+ ConfigValidationUtils.checkHost(HOST_KEY, config.getHost());
+ ConfigValidationUtils.checkPathName("contextpath", config.getContextpath());
+
+
+ if (DUBBO_PROTOCOL.equals(name)) {
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), Codec2.class, CODEC_KEY, config.getCodec());
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), Serialization.class, SERIALIZATION_KEY, config.getSerialization());
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), Transporter.class, SERVER_KEY, config.getServer());
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), Transporter.class, CLIENT_KEY, config.getClient());
+ }
+
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), TelnetHandler.class, TELNET_KEY, config.getTelnet());
+ ConfigValidationUtils.checkMultiExtension(config.getScopeModel(), StatusChecker.class, "status", config.getStatus());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), Transporter.class, TRANSPORTER_KEY, config.getTransporter());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), Exchanger.class, EXCHANGER_KEY, config.getExchanger());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), Dispatcher.class, DISPATCHER_KEY, config.getDispatcher());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), Dispatcher.class, "dispather", config.getDispather());
+ ConfigValidationUtils.checkExtension(config.getScopeModel(), ThreadPool.class, THREADPOOL_KEY, config.getThreadpool());
+ }
+ }
+
+ @Override
+ public boolean isSupport(Class<?> configClass) {
+ return ProtocolConfig.class.isAssignableFrom(configClass);
+ }
+}
diff --git a/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator b/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
new file mode 100644
index 0000000000..e53a309b5c
--- /dev/null
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.config.context.ConfigValidator
@@ -0,0 +1 @@
+protocol=org.apache.dubbo.config.validator.ProtocolConfigValidator