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
This commit is contained in:
namelessssssssssss 2023-09-10 20:56:10 +08:00 committed by GitHub
parent a6a6d57dd7
commit 98e7313e71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 1800 additions and 853 deletions

View File

@ -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";

View File

@ -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;

View File

@ -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;
}
}

View File

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

View File

@ -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> {
void validate(AbstractConfig config);
/**
* 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;
boolean isSupport(Class<?> configClass);
}

View File

@ -0,0 +1,39 @@
/*
* 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.exception;
/**
* Config validation exception
*/
public class ConfigValidationException extends RuntimeException {
public ConfigValidationException(String message) {
super(message);
}
public ConfigValidationException(String message, Throwable cause) {
super(message, cause);
}
public ConfigValidationException(Throwable cause) {
super(cause);
}
public ConfigValidationException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
}

View File

@ -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.");
}
}
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,2 @@
application=org.apache.dubbo.config.validator.ApplicationConfigValidator
module=org.apache.dubbo.config.validator.ModuleConfigValidator

View File

@ -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

View File

@ -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

View File

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

View File

@ -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);
}

View File

@ -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

View File

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

View File

@ -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);
}
}

View File

@ -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) {}
}

View File

@ -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.");
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,42 @@
/*
* 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.context.ConfigValidator;
@Activate
public class ConsumerConfigValidator implements ConfigValidator<ConsumerConfig> {
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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -131,7 +131,7 @@ class AbstractConfigTest {
protocolConfig.setCodec("exchange");
protocolConfig.setName("test");
protocolConfig.setHost("host");
ConfigValidationUtils.validateProtocolConfig(protocolConfig);
protocolConfig.validate();
}
@Test

View File

@ -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){};
}
}

View File

@ -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"));

View File

@ -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);

View File

@ -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>

View File

@ -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);
}
}

View File

@ -0,0 +1 @@
metadata=org.apache.dubbo.config.validator.MetadataConfigValidator

View File

@ -0,0 +1,42 @@
/*
* 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.MetricsConfig;
import org.apache.dubbo.config.context.ConfigValidator;
@Activate
public class MetricsConfigValidator implements ConfigValidator<MetricsConfig> {
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);
}
}

View File

@ -0,0 +1 @@
metrics=org.apache.dubbo.config.validator.MetricsConfigValidator

View File

@ -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();

View File

@ -0,0 +1,42 @@
/*
* 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.TracingConfig;
import org.apache.dubbo.config.context.ConfigValidator;
@Activate
public class TracingConfigValidator implements ConfigValidator<TracingConfig> {
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);
}
}

View File

@ -0,0 +1 @@
tracing=org.apache.dubbo.config.validator.TracingConfigValidator

View File

@ -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;
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1 @@
monitor=org.apache.dubbo.config.validator.MonitorConfigValidator

View File

@ -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))

View File

@ -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);
}
}

View File

@ -0,0 +1,40 @@
/*
* 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.SslConfig;
import org.apache.dubbo.config.context.ConfigValidator;
@Activate
public class SslConfigValidator implements ConfigValidator<SslConfig> {
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);
}
}

View File

@ -0,0 +1 @@
ssl=org.apache.dubbo.config.validator.SslConfigValidator

View File

@ -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);
}
}

View File

@ -0,0 +1 @@
protocol=org.apache.dubbo.config.validator.ProtocolConfigValidator