You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2018/12/24 07:48:50 UTC
[incubator-dubbo] 03/10: Merge branch 'dev-metadata'
This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-dubbo.git
commit b1324511d13aad36d14adee7bce71cdbe65a872a
Merge: 678cdb4 5184416
Author: ken.lj <ke...@gmail.com>
AuthorDate: Sun Dec 23 20:29:38 2018 +0800
Merge branch 'dev-metadata'
# Conflicts:
# dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Router.java
# dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/condition/ConditionRouter.java
# dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/mock/MockInvokersSelector.java
# dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java
# dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/tag/TagRouter.java
# dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
# dubbo-config/dubbo-config-api/src/test/resources/log4j.xml
# dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/RegistryDirectory.java
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderConsumerRegTable.java
# dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
# dubbo-rpc/dubbo-rpc-api/src/test/java/org/apache/dubbo/rpc/support/RuntimeExceptionInvoker.java
# dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
# dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/service/GenericServiceTest.java
# dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationParameter.java
# dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationService.java
# dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/validation/ValidationTest.java
codestyle/checkstyle.xml | 10 +-
dubbo-all/pom.xml | 57 +++
dubbo-bom/pom.xml | 35 ++
dubbo-cluster/pom.xml | 20 +
...rFactory.java => AbstractAppRouterFactory.java} | 24 +-
...uterFactory.java => AbstractRouterFactory.java} | 19 +-
.../org/apache/dubbo/rpc/cluster/Configurator.java | 48 +++
.../java/org/apache/dubbo/rpc/cluster/Router.java | 45 ++-
.../org/apache/dubbo/rpc/cluster/RouterChain.java | 156 ++++++++
.../apache/dubbo/rpc/cluster/RouterFactory.java | 7 +-
.../cluster/configurator/AbstractConfigurator.java | 75 +++-
.../cluster/configurator/parser/ConfigParser.java | 201 ++++++++++
.../configurator/parser/model/ConfigItem.java | 103 +++++
.../parser/model/ConfiguratorConfig.java | 74 ++++
.../rpc/cluster/directory/AbstractDirectory.java | 55 +--
.../rpc/cluster/directory/StaticDirectory.java | 35 +-
.../dubbo/rpc/cluster/router/AbstractRouter.java | 101 +++++
.../rpc/cluster/router/AbstractRouterRule.java | 105 +++++
.../cluster/router/condition/ConditionRouter.java | 46 ++-
.../config/AbstractConfigConditionRouter.java | 145 +++++++
.../condition/config/AppConfigConditionRouter.java | 28 +-
.../config/AppConfigConditionRouterFactory.java} | 19 +-
.../config/ServiceConfigConditionRouter.java | 28 +-
.../ServiceConfigConditionRouterFactory.java} | 19 +-
.../condition/config/model/BlackWhiteListRule.java | 73 ++--
.../config/model/ConditionRouterRule.java | 99 +++--
.../config/model/ConditionRuleParser.java | 57 +++
.../router/{ => mock}/MockInvokersSelector.java | 214 +++++-----
.../MockRouterFactory.java} | 16 +-
.../rpc/cluster/router/script/ScriptRouter.java | 32 +-
.../dubbo/rpc/cluster/router/tag/TagRouter.java | 217 ++++++++--
.../rpc/cluster/router/tag/TagRouterFactory.java | 14 +-
.../dubbo/rpc/cluster/router/tag/model/Tag.java | 80 ++--
.../cluster/router/tag/model/TagRouterRule.java | 86 ++++
.../cluster/router/tag/model/TagRuleParser.java | 45 +++
.../cluster/support/AbstractClusterInvoker.java | 2 +-
.../dubbo/rpc/cluster/support/ClusterUtils.java | 15 +-
.../cluster/support/MergeableClusterInvoker.java | 29 +-
.../rpc/cluster/support/RegistryAwareCluster.java | 25 +-
.../support/RegistryAwareClusterInvoker.java | 59 +++
.../internal/org.apache.dubbo.rpc.cluster.Cluster | 3 +-
.../org.apache.dubbo.rpc.cluster.RouterFactory | 5 +-
.../configurator/parser/ConfigParserTest.java | 167 ++++++++
.../loadbalance/RoundRobinLoadBalanceTest.java | 32 +-
.../cluster/router/ConfigConditionRouterTest.java | 134 +++++++
.../dubbo/rpc/cluster/router/TagRouterTest.java | 67 ++++
.../cluster/router/file/FileRouterEngineTest.java | 14 +-
.../rpc/cluster/router/tag/TagRouterTest.java | 170 --------
.../support/AbstractClusterInvokerTest.java | 10 +-
.../support/wrapper/MockClusterInvokerTest.java | 22 +-
.../src/test/resources/AppAnyServices.yml | 32 ++
.../src/test/resources/AppMultiServices.yml | 32 ++
dubbo-cluster/src/test/resources/AppNoService.yml | 32 ++
dubbo-cluster/src/test/resources/ConditionRule.yml | 56 +++
.../test/resources/ConsumerSpecificProviders.yml | 34 ++
.../src/test/resources/ServiceGroupVersion.yml | 29 ++
.../src/test/resources/ServiceMultiApps.yml | 30 ++
dubbo-cluster/src/test/resources/ServiceNoApp.yml | 29 ++
dubbo-cluster/src/test/resources/ServiceNoRule.yml | 28 ++
dubbo-cluster/src/test/resources/TagRule.yml | 31 ++
.../java/org/apache/dubbo/common/Constants.java | 89 ++++-
.../src/main/java/org/apache/dubbo/common/URL.java | 62 ++-
.../dubbo/common/config/AbstractConfiguration.java | 91 +++++
.../common/config/AbstractPrefixConfiguration.java | 52 +++
.../common/config/CompositeConfiguration.java | 82 ++++
.../apache/dubbo/common/config/Configuration.java | 82 ++++
.../dubbo/common/config/ConfigurationUtils.java | 59 +++
.../apache/dubbo/common/config/Environment.java | 199 ++++++++++
.../common/config/EnvironmentConfiguration.java | 22 +-
.../dubbo/common/config/InmemoryConfiguration.java | 67 ++++
.../common/config/PropertiesConfiguration.java | 28 +-
.../dubbo/common/config/SystemConfiguration.java | 27 +-
.../dubbo/common/extension/ExtensionLoader.java | 20 +-
.../org/apache/dubbo/common/utils/ClassHelper.java | 70 ++++
.../org/apache/dubbo/common/utils/ConfigUtils.java | 40 +-
.../org/apache/dubbo/common/utils/UrlUtils.java | 11 +-
.../config/AbstractPrefixConfigurationTest.java | 46 +--
.../common/config/CompositeConfigurationTest.java | 46 +--
.../dubbo/common/config/EnvironmentTest.java | 46 +--
.../apache/dubbo/common/utils/ConfigUtilsTest.java | 27 --
dubbo-compatible/pom.xml | 7 +-
.../java/com/alibaba/dubbo/rpc/cluster/Router.java | 34 +-
.../dubbo/config/RegistryDataConfigTest.java | 87 ++++
.../apache/dubbo/generic/GenericServiceTest.java | 181 ++++++++-
.../apache/dubbo/rpc/cluster/CompatibleRouter.java | 88 +++--
.../org/apache/dubbo/service/ComplexObject.java | 282 +++++++++++++
.../java/org/apache/dubbo/service/DemoService.java | 8 +-
.../org/apache/dubbo/service/DemoServiceImpl.java | 15 +-
dubbo-config/dubbo-config-api/pom.xml | 5 +
.../org/apache/dubbo/config/AbstractConfig.java | 323 +++++++++------
.../dubbo/config/AbstractInterfaceConfig.java | 297 ++++++++++----
.../apache/dubbo/config/AbstractMethodConfig.java | 16 +-
.../apache/dubbo/config/AbstractServiceConfig.java | 36 +-
.../org/apache/dubbo/config/ApplicationConfig.java | 29 +-
.../apache/dubbo/config/ConfigCenterConfig.java | 313 +++++++++++++++
.../org/apache/dubbo/config/ConsumerConfig.java | 8 +-
.../org/apache/dubbo/config/DubboShutdownHook.java | 9 +-
...onitorConfig.java => MetadataReportConfig.java} | 280 ++++++-------
.../java/org/apache/dubbo/config/MethodConfig.java | 37 ++
.../java/org/apache/dubbo/config/ModuleConfig.java | 8 +-
.../org/apache/dubbo/config/MonitorConfig.java | 13 +-
.../org/apache/dubbo/config/ProtocolConfig.java | 11 +-
.../org/apache/dubbo/config/ReferenceConfig.java | 121 +++---
.../org/apache/dubbo/config/RegistryConfig.java | 49 ++-
.../apache/dubbo/config/RegistryDataConfig.java | 86 ++++
.../org/apache/dubbo/config/ServiceConfig.java | 177 ++++++---
.../invoker/DelegateProviderMetaDataInvoker.java | 2 +-
.../org/apache/dubbo/config/support/Parameter.java | 2 +
.../apache/dubbo/config/AbstractConfigTest.java | 280 ++++++++++++-
.../dubbo/config/AbstractInterfaceConfigTest.java | 5 +-
.../dubbo/config/AbstractReferenceConfigTest.java | 1 +
.../dubbo/config/AbstractServiceConfigTest.java | 1 +
.../apache/dubbo/config/ApplicationConfigTest.java | 1 +
.../org/apache/dubbo/config/MethodConfigTest.java | 1 +
.../apache/dubbo/config/ProtocolConfigTest.java | 1 +
.../apache/dubbo/config/ReferenceConfigTest.java | 6 +
.../apache/dubbo/config/RegistryConfigTest.java | 2 +
.../org/apache/dubbo/config/ServiceConfigTest.java | 6 +-
.../org/apache/dubbo/config/api/DemoException.java | 84 ++--
.../org/apache/dubbo/config/api/DemoService.java | 72 ++--
.../java/org/apache/dubbo/config/api/User.java | 130 +++---
.../apache/dubbo/config/cache/CacheService.java | 52 +--
.../dubbo/config/cache/CacheServiceImpl.java | 64 +--
.../org/apache/dubbo/config/cache/CacheTest.java | 238 +++++------
.../config/consumer/DemoActionByAnnotation.java | 68 ++--
.../dubbo/config/consumer/DemoActionBySetter.java | 70 ++--
.../dubbo/config/consumer/DemoInterceptor.java | 60 +--
.../DelegateProviderMetaDataInvokerTest.java | 3 +-
.../dubbo/config/mock/MockExporterListener.java | 2 +-
.../org/apache/dubbo/config/mock/MockRegistry.java | 16 +-
.../dubbo/config/mock/MockRegistryFactory.java | 2 +-
.../apache/dubbo/config/mock/MockThreadPool.java | 2 +-
.../apache/dubbo/config/mock/MockTransporter.java | 1 +
.../config/provider/impl/DemoServiceImpl.java | 100 ++---
.../org.apache.dubbo.registry.RegistryFactory | 4 +-
.../src/test/resources/dubbo.properties | 2 +
.../dubbo-config-api/src/test/resources/log4j.xml | 54 +--
.../dubbo/config/spring/ConfigCenterBean.java | 154 ++++++++
.../apache/dubbo/config/spring/ReferenceBean.java | 57 ++-
.../apache/dubbo/config/spring/ServiceBean.java | 76 +++-
.../annotation/DubboConfigConfiguration.java | 12 +-
.../spring/schema/DubboBeanDefinitionParser.java | 46 +--
.../spring/schema/DubboNamespaceHandler.java | 2 +
.../src/main/resources/META-INF/compat/dubbo.xsd | 137 ++++++-
.../src/main/resources/META-INF/dubbo.xsd | 128 ++++++
.../dubbo-configcenter-api}/pom.xml | 14 +-
.../configcenter/AbstractDynamicConfiguration.java | 127 ++++++
.../AbstractDynamicConfigurationFactory.java | 26 +-
.../dubbo/configcenter/ConfigChangeEvent.java | 63 +++
.../dubbo/configcenter/ConfigChangeType.java | 63 +--
.../dubbo/configcenter/ConfigurationListener.java | 57 +--
.../dubbo/configcenter/DynamicConfiguration.java | 106 +++++
.../configcenter/DynamicConfigurationFactory.java | 56 +--
.../support/nop/NopDynamicConfiguration.java | 66 ++++
.../nop/NopDynamicConfigurationFactory.java | 17 +-
....dubbo.configcenter.DynamicConfigurationFactory | 1 +
.../mock/AbstractDynamicConfigurationTest.java | 47 +++
.../mock/MockDynamicConfiguration.java | 64 +++
.../mock/MockDynamicConfigurationFactory.java | 17 +-
....dubbo.configcenter.DynamicConfigurationFactory | 1 +
.../dubbo-configcenter-apollo}/pom.xml | 16 +-
.../support/apollo/ApolloDynamicConfiguration.java | 191 +++++++++
.../apollo/ApolloDynamicConfigurationFactory.java | 18 +-
....dubbo.configcenter.DynamicConfigurationFactory | 1 +
.../dubbo-configcenter-zookeeper}/pom.xml | 43 +-
.../support/zookeeper/CacheListener.java | 119 ++++++
.../zookeeper/ZookeeperDynamicConfiguration.java | 162 ++++++++
.../ZookeeperDynamicConfigurationFactory.java | 20 +-
....dubbo.configcenter.DynamicConfigurationFactory | 1 +
.../ZookeeperDynamicConfigurationTest.java | 151 +++++++
{dubbo-cluster => dubbo-configcenter}/pom.xml | 22 +-
dubbo-container/dubbo-container-log4j/pom.xml | 5 +
.../dubbo/container/log4j/Log4jContainer.java | 8 +-
.../java/org/apache/dubbo/demo/DemoService.java | 4 +
dubbo-demo/dubbo-demo-consumer/pom.xml | 14 +-
.../org/apache/dubbo/demo/consumer/Consumer.java | 8 +
.../dubbo/demo/consumer/DemoServiceMock.java | 24 +-
.../META-INF/spring/dubbo-demo-consumer.xml | 8 +-
dubbo-demo/dubbo-demo-provider/pom.xml | 18 +-
.../dubbo/demo/provider/DemoServiceImpl.java | 12 +
.../META-INF/spring/dubbo-demo-provider.xml | 86 ++--
dubbo-dependencies-bom/pom.xml | 54 ++-
.../dubbo-metadata-definition}/pom.xml | 27 +-
.../definition/ServiceDefinitionBuilder.java | 107 +++++
.../metadata/definition/TypeDefinitionBuilder.java | 79 ++++
.../definition/builder/ArrayTypeBuilder.java | 119 +++---
.../definition/builder/CollectionTypeBuilder.java | 79 ++++
.../definition/builder/DefaultTypeBuilder.java | 70 ++++
.../definition/builder/EnumTypeBuilder.java | 63 +++
.../definition/builder/MapTypeBuilder.java | 76 ++++
.../metadata/definition/builder/TypeBuilder.java | 82 ++--
.../definition/model/FullServiceDefinition.java | 30 +-
.../definition/model/MethodDefinition.java | 92 +++++
.../definition/model/ServiceDefinition.java | 96 +++++
.../metadata/definition/model/TypeDefinition.java | 124 ++++++
.../dubbo/metadata/definition/util/ClassUtils.java | 111 ++++++
.../definition/util/JaketConfigurationUtils.java | 100 +++++
.../dubbo/metadata/definition/MetadataTest.java | 143 +++++++
.../dubbo/metadata/definition/MetadataUtils.java | 75 ++++
.../definition/ServiceDefinitionBuildderTest.java | 98 +++++
.../definition/common/ClassExtendsMap.java | 19 +-
.../metadata/definition/common/ColorEnum.java | 45 ++-
.../metadata/definition/common/OuterClass.java | 72 ++--
.../common/ResultWithRawCollections.java | 96 +++--
.../metadata/definition/common/TestService.java | 98 +++--
.../metadata/definition/service/ComplexObject.java | 296 ++++++++++++++
.../metadata/definition/service}/DemoService.java | 67 ++--
.../dubbo-metadata-report-api}/pom.xml | 53 ++-
.../metadata/identifier/MetadataIdentifier.java | 125 ++++++
.../integration/MetadataReportService.java | 103 +++++
.../dubbo/metadata/store/MetadataReport.java | 73 ++--
.../metadata/store/MetadataReportFactory.java | 56 +--
.../metadata/support/AbstractMetadataReport.java | 407 +++++++++++++++++++
.../support/AbstractMetadataReportFactory.java | 64 +++
.../integration/InterfaceNameTestService.java | 48 +--
.../integration/InterfaceNameTestService2.java | 48 +--
.../integration/MetadataReportServiceTest.java | 137 +++++++
.../metadata/integration/RetryTestService.java | 53 +--
.../store/test/JTestMetadataReport4Test.java | 69 ++++
.../test/JTestMetadataReportFactory4Test.java | 25 +-
.../support/AbstractMetadataReportFactoryTest.java | 94 +++++
.../support/AbstractMetadataReportTest.java | 323 +++++++++++++++
...ache.dubbo.metadata.store.MetadataReportFactory | 1 +
.../dubbo-metadata-report-redis}/pom.xml | 35 +-
.../metadata/store/redis/RedisMetadataReport.java | 63 +++
.../store/redis/RedisMetadataReportFactory.java | 17 +-
...ache.dubbo.metadata.store.MetadataReportFactory | 1 +
.../store/redis/RedisMetadata4TstService.java | 12 +
.../store/redis/RedisMetadataReportTest.java | 130 ++++++
.../dubbo-metadata-report-zookeeper}/pom.xml | 29 +-
.../store/zookeeper/ZookeeperMetadataReport.java | 94 +++++
.../zookeeper/ZookeeperMetadataReportFactory.java | 25 +-
...ache.dubbo.metadata.store.MetadataReportFactory | 1 +
.../ZookeeperMetadataReport4TstService.java | 11 +
.../zookeeper/ZookeeperMetadataReportTest.java | 125 ++++++
{dubbo-cluster => dubbo-metadata-report}/pom.xml | 35 +-
dubbo-plugin/dubbo-qos/pom.xml | 2 +-
dubbo-registry/dubbo-registry-api/pom.xml | 23 +-
.../integration/AbstractConfiguratorListener.java | 71 ++++
.../registry/integration/RegistryDirectory.java | 439 +++++++++++++--------
.../registry/integration/RegistryProtocol.java | 317 +++++++++++----
.../registry/support/ProviderConsumerRegTable.java | 48 ++-
.../registry/support/ProviderInvokerWrapper.java | 9 +
.../java/org/apache/dubbo/registry/ZKTools.java | 307 ++++++++++++++
dubbo-registry/dubbo-registry-default/pom.xml | 5 +
.../registry/dubbo/RegistryDirectoryTest.java | 18 +-
.../dubbo/registry/dubbo/RegistryProtocolTest.java | 1 -
.../registry/integration/RegistryProtocolTest.java | 23 ++
.../dubbo/remoting/zookeeper/ZookeeperClient.java | 4 +
.../zookeeper/curator/CuratorZookeeperClient.java | 40 ++
.../zookeeper/support/AbstractZookeeperClient.java | 28 ++
.../zookeeper/zkclient/ZkClientWrapper.java | 15 +
.../zkclient/ZkclientZookeeperClient.java | 25 ++
.../curator/CuratorZookeeperClientTest.java | 30 +-
.../zkclient/ZkclientZookeeperClientTest.java | 30 +-
.../java/org/apache/dubbo/rpc/AsyncContext.java | 1 +
.../java/org/apache/dubbo/rpc/AsyncRpcResult.java | 4 +-
.../main/java/org/apache/dubbo/rpc/RpcContext.java | 5 +-
.../java/org/apache/dubbo/rpc/RpcException.java | 5 +
.../org/apache/dubbo/rpc/filter/ContextFilter.java | 1 -
.../apache/dubbo/rpc/model/ApplicationModel.java | 10 +
dubbo-rpc/dubbo-rpc-dubbo/pom.xml | 5 +
.../dubbo/rpc/protocol/dubbo/DubboInvoker.java | 4 +-
.../dubbo/rpc/protocol/dubbo/DubboProtocol.java | 8 +-
.../protocol/dubbo/DubboInvokerAvilableTest.java | 3 +-
.../dubbo/rpc/protocol/thrift/ThriftProtocol.java | 4 +-
.../webservice/WebserviceProtocolTest.java | 4 +-
.../dubbo/test/provider/DefaultDemoService.java | 10 +
pom.xml | 2 +
269 files changed, 13777 insertions(+), 3060 deletions(-)
diff --cc dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
index f650b6e,20b0a0e..f44c398
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/directory/AbstractDirectory.java
@@@ -16,24 -16,18 +16,20 @@@
*/
package org.apache.dubbo.rpc.cluster.directory;
- import org.apache.dubbo.common.Constants;
import org.apache.dubbo.common.URL;
- import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.rpc.Invocation;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.cluster.Directory;
import org.apache.dubbo.rpc.cluster.Router;
- import org.apache.dubbo.rpc.cluster.RouterFactory;
- import org.apache.dubbo.rpc.cluster.router.MockInvokersSelector;
+ import org.apache.dubbo.rpc.cluster.RouterChain;
import java.util.ArrayList;
- import java.util.Collections;
import java.util.List;
+import java.util.Map;
/**
* Abstract implementation of Directory: Invoker list returned from this Directory's list method have been filtered by Routers
@@@ -64,16 -58,9 +60,16 @@@ public abstract class AbstractDirectory
if (url == null) {
throw new IllegalArgumentException("url == null");
}
- this.url = url;
+
+ if (url.getProtocol().equals(Constants.REGISTRY_PROTOCOL)) {
+ Map<String, String> queryMap = StringUtils.parseQueryString(url.getParameterAndDecoded(Constants.REFER_KEY));
+ this.url = url.clearParameters().addParameters(queryMap).removeParameter(Constants.MONITOR_KEY);
+ } else {
+ this.url = url;
+ }
+
this.consumerUrl = consumerUrl;
- setRouters(routers);
+ setRouterChain(routerChain);
}
@Override
diff --cc dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java
index 7c3070a,05815df..f95573c
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/router/script/ScriptRouter.java
@@@ -40,9 -40,10 +40,9 @@@ import java.util.concurrent.ConcurrentH
/**
* ScriptRouter
- *
*/
- public class ScriptRouter implements Router {
-
+ public class ScriptRouter extends AbstractRouter {
+ public static final String NAME = "SCRIPT_ROUTER";
private static final Logger logger = LoggerFactory.getLogger(ScriptRouter.class);
private static final Map<String, ScriptEngine> engines = new ConcurrentHashMap<String, ScriptEngine>();
diff --cc dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
index 2d3602a,14e9f07..63486aa
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/support/AbstractClusterInvoker.java
@@@ -256,8 -257,8 +256,8 @@@ public abstract class AbstractClusterIn
}
protected void checkInvokers(List<Invoker<T>> invokers, Invocation invocation) {
- if (invokers == null || invokers.isEmpty()) {
+ if (CollectionUtils.isEmpty(invokers)) {
- throw new RpcException("Failed to invoke the method "
+ throw new RpcException(RpcException.NO_INVOKER_AVAILABLE_AFTER_FILTER, "Failed to invoke the method "
+ invocation.getMethodName() + " in the service " + getInterface().getName()
+ ". No provider available for the service " + directory.getUrl().getServiceKey()
+ " from registry " + directory.getUrl().getAddress()
diff --cc dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
index c6f8b1f,5c1006b..1750e31
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/Constants.java
@@@ -671,11 -715,41 +725,42 @@@ public class Constants
public static final String MULTICAST = "multicast";
- public static final String TAG_KEY = "tag";
+ public static final String TAG_KEY = "dubbo.tag";
+
+ public static final String FORCE_USE_TAG = "dubbo.force.tag";
+
+ public static final String HOST_KEY = "host";
+
+ public static final String ADDRESS_KEY = "address";
+
+ public static final String RETRY_TIMES_KEY = "retry.times";
+
+ public static final String RETRY_PERIOD_KEY = "retry.period";
+
+ public static final String SYNC_REPORT_KEY = "sync.report";
+
+ public static final String CYCLE_REPORT_KEY = "cycle.report";
+
+ public static final String CONFIG_VERSION_KEY = "configVersion";
+
+ public static final String COMPATIBLE_CONFIG_KEY = "compatible_config";
+ // package version in the manifest
+ public static final String SPECIFICATION_VERSION_KEY = "specVersion";
+
+ public static final String OVERRIDE_PROVIDERS_KEY = "providerAddreses";
+
+ public static final String PROTOCOLS_SUFFIX = "dubbo.protocols.";
+
+ public static final String PROTOCOL_SUFFIX = "dubbo.protocol.";
+
+ public static final String REGISTRIES_SUFFIX = "dubbo.registries.";
+
+ public static final String[] DEFAULT_REGISTER_PROVIDER_KEYS = {APPLICATION_KEY, CODEC_KEY, EXCHANGER_KEY, SERIALIZATION_KEY, CLUSTER_KEY, CONNECTIONS_KEY, DEPRECATED_KEY,
+ GROUP_KEY, LOADBALANCE_KEY, MOCK_KEY, PATH_KEY, TIMEOUT_KEY, TOKEN_KEY, VERSION_KEY, WARMUP_KEY, WEIGHT_KEY, TIMESTAMP_KEY, DUBBO_VERSION_KEY, SPECIFICATION_VERSION_KEY};
- public static final String REQUEST_TAG_KEY = "request.tag";
+ public static final String[] DEFAULT_REGISTER_CONSUMER_KEYS = {APPLICATION_KEY, VERSION_KEY, GROUP_KEY, DUBBO_VERSION_KEY, SPECIFICATION_VERSION_KEY};
+ public static final String TELNET = "telnet";
/*
* private Constants(){ }
*/
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
index 7cddb97,a64c73e..952853d
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractConfig.java
@@@ -1,535 -1,606 +1,606 @@@
-/*
- * 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.Constants;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.config.Configuration;
-import org.apache.dubbo.common.config.Environment;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
-import org.apache.dubbo.common.utils.ClassHelper;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.ReflectUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.config.support.Parameter;
-import org.apache.dubbo.rpc.model.ConsumerMethodModel;
-
-import java.io.Serializable;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-
-/**
- * Utility methods and public methods for parsing configuration
- *
- * @export
- */
-public abstract class AbstractConfig implements Serializable {
-
- protected static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class);
- private static final long serialVersionUID = 4267533505537413570L;
- private static final int MAX_LENGTH = 200;
-
- private static final int MAX_PATH_LENGTH = 200;
-
- private static final Pattern PATTERN_NAME = Pattern.compile("[\\-._0-9a-zA-Z]+");
-
- private static final Pattern PATTERN_MULTI_NAME = Pattern.compile("[,\\-._0-9a-zA-Z]+");
-
- private static final Pattern PATTERN_METHOD_NAME = Pattern.compile("[a-zA-Z][0-9a-zA-Z]*");
-
- private static final Pattern PATTERN_PATH = Pattern.compile("[/\\-$._0-9a-zA-Z]+");
-
- private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,\\s/\\-._0-9a-zA-Z]+");
-
- private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+");
- private static final Map<String, String> legacyProperties = new HashMap<String, String>();
- private static final String[] SUFFIXES = new String[]{"Config", "Bean"};
-
- static {
- legacyProperties.put("dubbo.protocol.name", "dubbo.service.protocol");
- legacyProperties.put("dubbo.protocol.host", "dubbo.service.server.host");
- legacyProperties.put("dubbo.protocol.port", "dubbo.service.server.port");
- legacyProperties.put("dubbo.protocol.threads", "dubbo.service.max.thread.pool.size");
- legacyProperties.put("dubbo.consumer.timeout", "dubbo.service.invoke.timeout");
- legacyProperties.put("dubbo.consumer.retries", "dubbo.service.max.retry.providers");
- legacyProperties.put("dubbo.consumer.check", "dubbo.service.allow.no.provider");
- legacyProperties.put("dubbo.service.url", "dubbo.service.address");
-
- // this is only for compatibility
- Runtime.getRuntime().addShutdownHook(DubboShutdownHook.getDubboShutdownHook());
- }
-
- protected String id;
- protected String prefix;
-
- private static String convertLegacyValue(String key, String value) {
- if (value != null && value.length() > 0) {
- if ("dubbo.service.max.retry.providers".equals(key)) {
- return String.valueOf(Integer.parseInt(value) - 1);
- } else if ("dubbo.service.allow.no.provider".equals(key)) {
- return String.valueOf(!Boolean.parseBoolean(value));
- }
- }
- return value;
- }
-
- private static String getTagName(Class<?> cls) {
- String tag = cls.getSimpleName();
- for (String suffix : SUFFIXES) {
- if (tag.endsWith(suffix)) {
- tag = tag.substring(0, tag.length() - suffix.length());
- break;
- }
- }
- return tag.substring(0, 1).toLowerCase() + tag.substring(1);
- }
-
- protected static void appendParameters(Map<String, String> parameters, Object config) {
- appendParameters(parameters, config, null);
- }
-
- @SuppressWarnings("unchecked")
- protected static void appendParameters(Map<String, String> parameters, Object config, String prefix) {
- if (config == null) {
- return;
- }
- Method[] methods = config.getClass().getMethods();
- for (Method method : methods) {
- try {
- String name = method.getName();
- if (ClassHelper.isGetter(method)) {
- Parameter parameter = method.getAnnotation(Parameter.class);
- if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
- continue;
- }
- String key;
- if (parameter != null && parameter.key().length() > 0) {
- key = parameter.key();
- } else {
- key = calculatePropertyFromGetter(name);
- }
- Object value = method.invoke(config);
- String str = String.valueOf(value).trim();
- if (value != null && str.length() > 0) {
- if (parameter != null && parameter.escaped()) {
- str = URL.encode(str);
- }
- if (parameter != null && parameter.append()) {
- String pre = parameters.get(Constants.DEFAULT_KEY + "." + key);
- if (pre != null && pre.length() > 0) {
- str = pre + "," + str;
- }
- pre = parameters.get(key);
- if (pre != null && pre.length() > 0) {
- str = pre + "," + str;
- }
- }
- if (prefix != null && prefix.length() > 0) {
- key = prefix + "." + key;
- }
- parameters.put(key, str);
- } else if (parameter != null && parameter.required()) {
- throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null");
- }
- } else if ("getParameters".equals(name)
- && Modifier.isPublic(method.getModifiers())
- && method.getParameterTypes().length == 0
- && method.getReturnType() == Map.class) {
- Map<String, String> map = (Map<String, String>) method.invoke(config, new Object[0]);
- if (map != null && map.size() > 0) {
- String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : "");
- for (Map.Entry<String, String> entry : map.entrySet()) {
- parameters.put(pre + entry.getKey().replace('-', '.'), entry.getValue());
- }
- }
- }
- } catch (Exception e) {
- throw new IllegalStateException(e.getMessage(), e);
- }
- }
- }
-
- protected static void appendAttributes(Map<String, Object> parameters, Object config) {
- appendAttributes(parameters, config, null);
- }
-
- protected static void appendAttributes(Map<String, Object> parameters, Object config, String prefix) {
- if (config == null) {
- return;
- }
- Method[] methods = config.getClass().getMethods();
- for (Method method : methods) {
- try {
- Parameter parameter = method.getAnnotation(Parameter.class);
- if (parameter == null || !parameter.attribute()) {
- continue;
- }
- String name = method.getName();
- if (ClassHelper.isGetter(method)) {
- String key;
- if (parameter.key().length() > 0) {
- key = parameter.key();
- } else {
- key = calculateAttributeFromGetter(name);
- }
- Object value = method.invoke(config);
- if (value != null) {
- if (prefix != null && prefix.length() > 0) {
- key = prefix + "." + key;
- }
- parameters.put(key, value);
- }
- }
- } catch (Exception e) {
- throw new IllegalStateException(e.getMessage(), e);
- }
- }
- }
-
- protected static ConsumerMethodModel.AsyncMethodInfo convertMethodConfig2AyncInfo(MethodConfig methodConfig) {
- if (methodConfig == null || (methodConfig.getOninvoke() == null && methodConfig.getOnreturn() == null && methodConfig.getOnthrow() == null)) {
- return null;
- }
-
- //check config conflict
- if (Boolean.FALSE.equals(methodConfig.isReturn()) && (methodConfig.getOnreturn() != null || methodConfig.getOnthrow() != null)) {
- throw new IllegalStateException("method config error : return attribute must be set true when onreturn or onthrow has been set.");
- }
-
- ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = new ConsumerMethodModel.AsyncMethodInfo();
-
- asyncMethodInfo.setOninvokeInstance(methodConfig.getOninvoke());
- asyncMethodInfo.setOnreturnInstance(methodConfig.getOnreturn());
- asyncMethodInfo.setOnthrowInstance(methodConfig.getOnthrow());
-
- try {
- String oninvokeMethod = methodConfig.getOninvokeMethod();
- if (StringUtils.isNotEmpty(oninvokeMethod)) {
- asyncMethodInfo.setOninvokeMethod(getMethodByName(methodConfig.getOninvoke().getClass(), oninvokeMethod));
- }
-
- String onreturnMethod = methodConfig.getOnreturnMethod();
- if (StringUtils.isNotEmpty(onreturnMethod)) {
- asyncMethodInfo.setOnreturnMethod(getMethodByName(methodConfig.getOnreturn().getClass(), onreturnMethod));
- }
-
- String onthrowMethod = methodConfig.getOnthrowMethod();
- if (StringUtils.isNotEmpty(onthrowMethod)) {
- asyncMethodInfo.setOnthrowMethod(getMethodByName(methodConfig.getOnthrow().getClass(), onthrowMethod));
- }
- } catch (Exception e) {
- throw new IllegalStateException(e.getMessage(), e);
- }
-
- return asyncMethodInfo;
- }
-
- private static Method getMethodByName(Class<?> clazz, String methodName) {
- try {
- return ReflectUtils.findMethodByMethodName(clazz, methodName);
- } catch (Exception e) {
- throw new IllegalStateException(e);
- }
- }
-
- /**
- * We only check boolean value at this moment.
- *
- * @param type
- * @param value
- * @return
- */
- private static boolean isTypeMatch(Class<?> type, String value) {
- if ((type == boolean.class || type == Boolean.class)
- && !("true".equals(value) || "false".equals(value))) {
- return false;
- }
- return true;
- }
-
- protected static void checkExtension(Class<?> type, String property, String value) {
- checkName(property, value);
- if (value != null && value.length() > 0
- && !ExtensionLoader.getExtensionLoader(type).hasExtension(value)) {
- throw new IllegalStateException("No such extension " + value + " for " + property + "/" + type.getName());
- }
- }
-
- protected static void checkMultiExtension(Class<?> type, String property, String value) {
- checkMultiName(property, value);
- if (value != null && value.length() > 0) {
- String[] values = value.split("\\s*[,]+\\s*");
- for (String v : values) {
- if (v.startsWith(Constants.REMOVE_VALUE_PREFIX)) {
- v = v.substring(1);
- }
- if (Constants.DEFAULT_KEY.equals(v)) {
- continue;
- }
- if (!ExtensionLoader.getExtensionLoader(type).hasExtension(v)) {
- throw new IllegalStateException("No such extension " + v + " for " + property + "/" + type.getName());
- }
- }
- }
- }
-
- protected static void checkLength(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, null);
- }
-
- protected static void checkPathLength(String property, String value) {
- checkProperty(property, value, MAX_PATH_LENGTH, null);
- }
-
- protected static void checkName(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_NAME);
- }
-
- protected static void checkNameHasSymbol(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_NAME_HAS_SYMBOL);
- }
-
- protected static void checkKey(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_KEY);
- }
-
- protected static void checkMultiName(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_MULTI_NAME);
- }
-
- protected static void checkPathName(String property, String value) {
- checkProperty(property, value, MAX_PATH_LENGTH, PATTERN_PATH);
- }
-
- protected static void checkMethodName(String property, String value) {
- checkProperty(property, value, MAX_LENGTH, PATTERN_METHOD_NAME);
- }
-
- protected static void checkParameterName(Map<String, String> parameters) {
- if (parameters == null || parameters.size() == 0) {
- return;
- }
- for (Map.Entry<String, String> entry : parameters.entrySet()) {
- checkNameHasSymbol(entry.getKey(), entry.getValue());
- }
- }
-
- protected static void checkProperty(String property, String value, int maxlength, Pattern pattern) {
- if (value == null || value.length() == 0) {
- return;
- }
- if (value.length() > maxlength) {
- throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" is longer than " + maxlength);
- }
- if (pattern != null) {
- Matcher matcher = pattern.matcher(value);
- if (!matcher.matches()) {
- throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" contains illegal " +
- "character, only digit, letter, '-', '_' or '.' is legal.");
- }
- }
- }
-
- protected static Set<String> getSubProperties(Map<String, String> properties, String prefix) {
- return properties.keySet().stream().filter(k -> k.contains(prefix)).map(k -> {
- k = k.substring(prefix.length());
- return k.substring(0, k.indexOf("."));
- }).collect(Collectors.toSet());
- }
-
- private static String extractPropertyName(Class<?> clazz, Method setter) throws Exception {
- String propertyName = setter.getName().substring("set".length());
- Method getter = null;
- try {
- getter = clazz.getMethod("get" + propertyName);
- } catch (NoSuchMethodException e) {
- getter = clazz.getMethod("is" + propertyName);
- }
- Parameter parameter = getter.getAnnotation(Parameter.class);
- if (parameter != null && StringUtils.isNotEmpty(parameter.key()) && parameter.useKeyAsProperty()) {
- propertyName = parameter.key();
- } else {
- propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1);
- }
- return propertyName;
- }
-
- private static String calculatePropertyFromGetter(String name) {
- int i = name.startsWith("get") ? 3 : 2;
- return StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), ".");
- }
-
- private static String calculateAttributeFromGetter(String getter) {
- int i = getter.startsWith("get") ? 3 : 2;
- return getter.substring(i, i + 1).toLowerCase() + getter.substring(i + 1);
- }
-
- @Parameter(excluded = true)
- public String getId() {
- return id;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public void updateIdIfAbsent(String value) {
- if (StringUtils.isNotEmpty(value) && StringUtils.isEmpty(id)) {
- this.id = value;
- }
- }
-
- protected void appendAnnotation(Class<?> annotationClass, Object annotation) {
- Method[] methods = annotationClass.getMethods();
- for (Method method : methods) {
- if (method.getDeclaringClass() != Object.class
- && method.getReturnType() != void.class
- && method.getParameterTypes().length == 0
- && Modifier.isPublic(method.getModifiers())
- && !Modifier.isStatic(method.getModifiers())) {
- try {
- String property = method.getName();
- if ("interfaceClass".equals(property) || "interfaceName".equals(property)) {
- property = "interface";
- }
- String setter = "set" + property.substring(0, 1).toUpperCase() + property.substring(1);
- Object value = method.invoke(annotation);
- if (value != null && !value.equals(method.getDefaultValue())) {
- Class<?> parameterType = ReflectUtils.getBoxedClass(method.getReturnType());
- if ("filter".equals(property) || "listener".equals(property)) {
- parameterType = String.class;
- value = StringUtils.join((String[]) value, ",");
- } else if ("parameters".equals(property)) {
- parameterType = Map.class;
- value = CollectionUtils.toStringMap((String[]) value);
- }
- try {
- Method setterMethod = getClass().getMethod(setter, parameterType);
- setterMethod.invoke(this, value);
- } catch (NoSuchMethodException e) {
- // ignore
- }
- }
- } catch (Throwable e) {
- logger.error(e.getMessage(), e);
- }
- }
- }
- }
-
- /**
- * Should be called after Config was fully initialized.
- * // FIXME: this method should be completely replaced by appendParameters
- *
- * @return
- * @see AbstractConfig#appendParameters(Map, Object, String)
- * <p>
- * Notice! This method should include all properties in the returning map, treat @Parameter differently compared to appendParameters.
- */
- public Map<String, String> getMetaData() {
- Map<String, String> metaData = new HashMap<>();
- Method[] methods = this.getClass().getMethods();
- for (Method method : methods) {
- try {
- String name = method.getName();
- if ((name.startsWith("get") || name.startsWith("is"))
- && !name.equals("get")
- && !"getClass".equals(name)
- && Modifier.isPublic(method.getModifiers())
- && method.getParameterTypes().length == 0
- && ClassHelper.isPrimitive(method.getReturnType())) {
- String prop = calculateAttributeFromGetter(name);
- String key;
- Parameter parameter = method.getAnnotation(Parameter.class);
- if (parameter != null && parameter.key().length() > 0 && parameter.useKeyAsProperty()) {
- key = parameter.key();
- } else {
- key = prop;
- }
- // treat url and configuration differently, the value should always present in configuration though it may not need to present in url.
- //if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
- if (method.getReturnType() == Object.class) {
- metaData.put(key, null);
- continue;
- }
- Object value = method.invoke(this);
- String str = String.valueOf(value).trim();
- if (value != null && str.length() > 0) {
- // ignore escape, keep the original value.
- /*if (parameter != null && parameter.escaped()) {
- str = URL.encode(str);
- }*/
- if (parameter != null && parameter.append()) {
- String pre = String.valueOf(metaData.get(Constants.DEFAULT_KEY + "." + key));
- if (pre != null && pre.length() > 0) {
- str = pre + "," + str;
- }
- pre = String.valueOf(metaData.get(key));
- if (pre != null && pre.length() > 0) {
- str = pre + "," + str;
- }
- }
- /* if (prefix != null && prefix.length() > 0) {
- key = prefix + "." + key;
- }*/
- metaData.put(key, str);
- } else {
- metaData.put(key, null);
- }
- // TODO check required somewhere else.
- /*else if (parameter != null && parameter.required()) {
- throw new IllegalStateException(this.getClass().getSimpleName() + "." + key + " == null");
- }*/
- } else if ("getParameters".equals(name)
- && Modifier.isPublic(method.getModifiers())
- && method.getParameterTypes().length == 0
- && method.getReturnType() == Map.class) {
- Map<String, String> map = (Map<String, String>) method.invoke(this, new Object[0]);
- if (map != null && map.size() > 0) {
-// String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : "");
- for (Map.Entry<String, String> entry : map.entrySet()) {
- metaData.put(entry.getKey().replace('-', '.'), entry.getValue());
- }
- }
- }
- } catch (Exception e) {
- throw new IllegalStateException(e.getMessage(), e);
- }
- }
- return metaData;
- }
-
- @Parameter(excluded = true)
- public String getPrefix() {
- return StringUtils.isNotEmpty(prefix) ? prefix : (Constants.DUBBO + "." + getTagName(this.getClass()));
- }
-
- public void setPrefix(String prefix) {
- this.prefix = prefix;
- }
-
- /**
- * TODO: Currently, only support overriding of properties explicitly defined in Config class, doesn't support
- * overriding of customized parameters stored in 'parameters'.
- */
- public void refresh() {
- try {
- Environment env = Environment.getInstance();
- env.addAppConfig(getPrefix(), getId(), getMetaData());
- Configuration configuration = env.getConfiguration(getPrefix(), getId());
-
- // loop methods, get override value and set the new value back to method
- Method[] methods = getClass().getMethods();
- for (Method method : methods) {
- if (ClassHelper.isSetter(method)) {
- try {
- String value = configuration.getString(extractPropertyName(getClass(), method));
- // isTypeMatch() is called to avoid duplicate and incorrect update, for example, we have two 'setGeneric' methods in ReferenceConfig.
- if (value != null && ClassHelper.isTypeMatch(method.getParameterTypes()[0], value)) {
- method.invoke(this, ClassHelper.convertPrimitive(method.getParameterTypes()[0], value));
- }
- } catch (NoSuchMethodException e) {
- logger.info("Failed to override the property " + method.getName() + " in " +
- this.getClass().getSimpleName() +
- ", please make sure every property has getter/setter method provided.");
- }
- }
- }
- } catch (Exception e) {
- logger.error("Failed to override ", e);
- }
- }
-
- @Override
- public String toString() {
- try {
- StringBuilder buf = new StringBuilder();
- buf.append("<dubbo:");
- buf.append(getTagName(getClass()));
- Method[] methods = getClass().getMethods();
- for (Method method : methods) {
- try {
- if (ClassHelper.isGetter(method)) {
- String name = method.getName();
- String key = calculateAttributeFromGetter(name);
- Object value = method.invoke(this);
- if (value != null) {
- buf.append(" ");
- buf.append(key);
- buf.append("=\"");
- buf.append(value);
- buf.append("\"");
- }
- }
- } catch (Exception e) {
- logger.warn(e.getMessage(), e);
- }
- }
- buf.append(" />");
- return buf.toString();
- } catch (Throwable t) {
- logger.warn(t.getMessage(), t);
- return super.toString();
- }
- }
-
- /**
- * FIXME check @Parameter(required=true) and any conditions that need to match.
- */
- @Parameter(excluded = true)
- public boolean isValid() {
- return true;
- }
-
-}
+/*
+ * 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.Constants;
+import org.apache.dubbo.common.URL;
++import org.apache.dubbo.common.config.Configuration;
++import org.apache.dubbo.common.config.Environment;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
++import org.apache.dubbo.common.utils.ClassHelper;
+import org.apache.dubbo.common.utils.CollectionUtils;
- import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.common.utils.ReflectUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.config.support.Parameter;
+import org.apache.dubbo.rpc.model.ConsumerMethodModel;
+
+import java.io.Serializable;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.Map;
++import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
++import java.util.stream.Collectors;
+
+/**
+ * Utility methods and public methods for parsing configuration
+ *
+ * @export
+ */
+public abstract class AbstractConfig implements Serializable {
+
+ protected static final Logger logger = LoggerFactory.getLogger(AbstractConfig.class);
+ private static final long serialVersionUID = 4267533505537413570L;
+ private static final int MAX_LENGTH = 200;
+
+ private static final int MAX_PATH_LENGTH = 200;
+
+ private static final Pattern PATTERN_NAME = Pattern.compile("[\\-._0-9a-zA-Z]+");
+
+ private static final Pattern PATTERN_MULTI_NAME = Pattern.compile("[,\\-._0-9a-zA-Z]+");
+
+ private static final Pattern PATTERN_METHOD_NAME = Pattern.compile("[a-zA-Z][0-9a-zA-Z]*");
+
+ private static final Pattern PATTERN_PATH = Pattern.compile("[/\\-$._0-9a-zA-Z]+");
+
+ private static final Pattern PATTERN_NAME_HAS_SYMBOL = Pattern.compile("[:*,\\s/\\-._0-9a-zA-Z]+");
+
+ private static final Pattern PATTERN_KEY = Pattern.compile("[*,\\-._0-9a-zA-Z]+");
+ private static final Map<String, String> legacyProperties = new HashMap<String, String>();
+ private static final String[] SUFFIXES = new String[]{"Config", "Bean"};
+
+ static {
+ legacyProperties.put("dubbo.protocol.name", "dubbo.service.protocol");
+ legacyProperties.put("dubbo.protocol.host", "dubbo.service.server.host");
+ legacyProperties.put("dubbo.protocol.port", "dubbo.service.server.port");
+ legacyProperties.put("dubbo.protocol.threads", "dubbo.service.max.thread.pool.size");
+ legacyProperties.put("dubbo.consumer.timeout", "dubbo.service.invoke.timeout");
+ legacyProperties.put("dubbo.consumer.retries", "dubbo.service.max.retry.providers");
+ legacyProperties.put("dubbo.consumer.check", "dubbo.service.allow.no.provider");
+ legacyProperties.put("dubbo.service.url", "dubbo.service.address");
+
+ // this is only for compatibility
+ DubboShutdownHook.getDubboShutdownHook().register();
+ }
+
+ protected String id;
++ protected String prefix;
+
+ private static String convertLegacyValue(String key, String value) {
+ if (value != null && value.length() > 0) {
+ if ("dubbo.service.max.retry.providers".equals(key)) {
+ return String.valueOf(Integer.parseInt(value) - 1);
+ } else if ("dubbo.service.allow.no.provider".equals(key)) {
+ return String.valueOf(!Boolean.parseBoolean(value));
+ }
+ }
+ return value;
+ }
+
- protected static void appendProperties(AbstractConfig config) {
- if (config == null) {
- return;
- }
- String prefix = "dubbo." + getTagName(config.getClass()) + ".";
- Method[] methods = config.getClass().getMethods();
- for (Method method : methods) {
- try {
- String name = method.getName();
- if (name.length() > 3 && name.startsWith("set") && Modifier.isPublic(method.getModifiers())
- && method.getParameterTypes().length == 1 && isPrimitive(method.getParameterTypes()[0])) {
- String property = StringUtils.camelToSplitName(name.substring(3, 4).toLowerCase() + name.substring(4), ".");
-
- String value = null;
- if (config.getId() != null && config.getId().length() > 0) {
- String pn = prefix + config.getId() + "." + property;
- value = System.getProperty(pn);
- if (!StringUtils.isBlank(value)) {
- logger.info("Use System Property " + pn + " to config dubbo");
- }
- }
- if (value == null || value.length() == 0) {
- String pn = prefix + property;
- value = System.getProperty(pn);
- if (!StringUtils.isBlank(value)) {
- logger.info("Use System Property " + pn + " to config dubbo");
- }
- }
- if (value == null || value.length() == 0) {
- Method getter;
- try {
- getter = config.getClass().getMethod("get" + name.substring(3));
- } catch (NoSuchMethodException e) {
- try {
- getter = config.getClass().getMethod("is" + name.substring(3));
- } catch (NoSuchMethodException e2) {
- getter = null;
- }
- }
- if (getter != null) {
- if (getter.invoke(config) == null) {
- if (config.getId() != null && config.getId().length() > 0) {
- value = ConfigUtils.getProperty(prefix + config.getId() + "." + property);
- }
- if (value == null || value.length() == 0) {
- value = ConfigUtils.getProperty(prefix + property);
- }
- if (value == null || value.length() == 0) {
- String legacyKey = legacyProperties.get(prefix + property);
- if (legacyKey != null && legacyKey.length() > 0) {
- value = convertLegacyValue(legacyKey, ConfigUtils.getProperty(legacyKey));
- }
- }
-
- }
- }
- }
- if (value != null && value.length() > 0) {
- method.invoke(config, convertPrimitive(method.getParameterTypes()[0], value));
- }
- }
- } catch (Exception e) {
- logger.error(e.getMessage(), e);
- }
- }
- }
-
+ private static String getTagName(Class<?> cls) {
+ String tag = cls.getSimpleName();
+ for (String suffix : SUFFIXES) {
+ if (tag.endsWith(suffix)) {
+ tag = tag.substring(0, tag.length() - suffix.length());
+ break;
+ }
+ }
- tag = tag.toLowerCase();
- return tag;
++ return tag.substring(0, 1).toLowerCase() + tag.substring(1);
+ }
+
+ protected static void appendParameters(Map<String, String> parameters, Object config) {
+ appendParameters(parameters, config, null);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected static void appendParameters(Map<String, String> parameters, Object config, String prefix) {
+ if (config == null) {
+ return;
+ }
+ Method[] methods = config.getClass().getMethods();
+ for (Method method : methods) {
+ try {
+ String name = method.getName();
- if ((name.startsWith("get") || name.startsWith("is"))
- && !"getClass".equals(name)
- && Modifier.isPublic(method.getModifiers())
- && method.getParameterTypes().length == 0
- && isPrimitive(method.getReturnType())) {
++ if (ClassHelper.isGetter(method)) {
+ Parameter parameter = method.getAnnotation(Parameter.class);
+ if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
+ continue;
+ }
- int i = name.startsWith("get") ? 3 : 2;
- String prop = StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), ".");
+ String key;
+ if (parameter != null && parameter.key().length() > 0) {
+ key = parameter.key();
+ } else {
- key = prop;
++ key = calculatePropertyFromGetter(name);
+ }
+ Object value = method.invoke(config);
+ String str = String.valueOf(value).trim();
+ if (value != null && str.length() > 0) {
+ if (parameter != null && parameter.escaped()) {
+ str = URL.encode(str);
+ }
+ if (parameter != null && parameter.append()) {
+ String pre = parameters.get(Constants.DEFAULT_KEY + "." + key);
+ if (pre != null && pre.length() > 0) {
+ str = pre + "," + str;
+ }
+ pre = parameters.get(key);
+ if (pre != null && pre.length() > 0) {
+ str = pre + "," + str;
+ }
+ }
+ if (prefix != null && prefix.length() > 0) {
+ key = prefix + "." + key;
+ }
+ parameters.put(key, str);
+ } else if (parameter != null && parameter.required()) {
+ throw new IllegalStateException(config.getClass().getSimpleName() + "." + key + " == null");
+ }
+ } else if ("getParameters".equals(name)
+ && Modifier.isPublic(method.getModifiers())
+ && method.getParameterTypes().length == 0
+ && method.getReturnType() == Map.class) {
+ Map<String, String> map = (Map<String, String>) method.invoke(config, new Object[0]);
+ if (map != null && map.size() > 0) {
+ String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : "");
+ for (Map.Entry<String, String> entry : map.entrySet()) {
+ parameters.put(pre + entry.getKey().replace('-', '.'), entry.getValue());
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ }
+ }
+
+ protected static void appendAttributes(Map<String, Object> parameters, Object config) {
+ appendAttributes(parameters, config, null);
+ }
+
+ protected static void appendAttributes(Map<String, Object> parameters, Object config, String prefix) {
+ if (config == null) {
+ return;
+ }
+ Method[] methods = config.getClass().getMethods();
+ for (Method method : methods) {
+ try {
+ Parameter parameter = method.getAnnotation(Parameter.class);
+ if (parameter == null || !parameter.attribute()) {
+ continue;
+ }
+ String name = method.getName();
- if ((name.startsWith("get") || name.startsWith("is"))
- && !"getClass".equals(name)
- && Modifier.isPublic(method.getModifiers())
- && method.getParameterTypes().length == 0
- && isPrimitive(method.getReturnType())) {
++ if (ClassHelper.isGetter(method)) {
+ String key;
+ if (parameter.key().length() > 0) {
+ key = parameter.key();
+ } else {
- int i = name.startsWith("get") ? 3 : 2;
- key = name.substring(i, i + 1).toLowerCase() + name.substring(i + 1);
++ key = calculateAttributeFromGetter(name);
+ }
+ Object value = method.invoke(config);
+ if (value != null) {
+ if (prefix != null && prefix.length() > 0) {
+ key = prefix + "." + key;
+ }
+ parameters.put(key, value);
+ }
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ }
+ }
+
+ protected static ConsumerMethodModel.AsyncMethodInfo convertMethodConfig2AyncInfo(MethodConfig methodConfig) {
+ if (methodConfig == null || (methodConfig.getOninvoke() == null && methodConfig.getOnreturn() == null && methodConfig.getOnthrow() == null)) {
+ return null;
+ }
+
+ //check config conflict
+ if (Boolean.FALSE.equals(methodConfig.isReturn()) && (methodConfig.getOnreturn() != null || methodConfig.getOnthrow() != null)) {
+ throw new IllegalStateException("method config error : return attribute must be set true when onreturn or onthrow has been set.");
+ }
+
+ ConsumerMethodModel.AsyncMethodInfo asyncMethodInfo = new ConsumerMethodModel.AsyncMethodInfo();
+
+ asyncMethodInfo.setOninvokeInstance(methodConfig.getOninvoke());
+ asyncMethodInfo.setOnreturnInstance(methodConfig.getOnreturn());
+ asyncMethodInfo.setOnthrowInstance(methodConfig.getOnthrow());
+
+ try {
+ String oninvokeMethod = methodConfig.getOninvokeMethod();
+ if (StringUtils.isNotEmpty(oninvokeMethod)) {
+ asyncMethodInfo.setOninvokeMethod(getMethodByName(methodConfig.getOninvoke().getClass(), oninvokeMethod));
+ }
+
+ String onreturnMethod = methodConfig.getOnreturnMethod();
+ if (StringUtils.isNotEmpty(onreturnMethod)) {
+ asyncMethodInfo.setOnreturnMethod(getMethodByName(methodConfig.getOnreturn().getClass(), onreturnMethod));
+ }
+
+ String onthrowMethod = methodConfig.getOnthrowMethod();
+ if (StringUtils.isNotEmpty(onthrowMethod)) {
+ asyncMethodInfo.setOnthrowMethod(getMethodByName(methodConfig.getOnthrow().getClass(), onthrowMethod));
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+
+ return asyncMethodInfo;
+ }
+
+ private static Method getMethodByName(Class<?> clazz, String methodName) {
+ try {
+ return ReflectUtils.findMethodByMethodName(clazz, methodName);
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
- private static boolean isPrimitive(Class<?> type) {
- return type.isPrimitive()
- || type == String.class
- || type == Character.class
- || type == Boolean.class
- || type == Byte.class
- || type == Short.class
- || type == Integer.class
- || type == Long.class
- || type == Float.class
- || type == Double.class
- || type == Object.class;
- }
-
- private static Object convertPrimitive(Class<?> type, String value) {
- if (type == char.class || type == Character.class) {
- return value.length() > 0 ? value.charAt(0) : '\0';
- } else if (type == boolean.class || type == Boolean.class) {
- return Boolean.valueOf(value);
- } else if (type == byte.class || type == Byte.class) {
- return Byte.valueOf(value);
- } else if (type == short.class || type == Short.class) {
- return Short.valueOf(value);
- } else if (type == int.class || type == Integer.class) {
- return Integer.valueOf(value);
- } else if (type == long.class || type == Long.class) {
- return Long.valueOf(value);
- } else if (type == float.class || type == Float.class) {
- return Float.valueOf(value);
- } else if (type == double.class || type == Double.class) {
- return Double.valueOf(value);
++ /**
++ * We only check boolean value at this moment.
++ *
++ * @param type
++ * @param value
++ * @return
++ */
++ private static boolean isTypeMatch(Class<?> type, String value) {
++ if ((type == boolean.class || type == Boolean.class)
++ && !("true".equals(value) || "false".equals(value))) {
++ return false;
+ }
- return value;
++ return true;
+ }
+
+ protected static void checkExtension(Class<?> type, String property, String value) {
+ checkName(property, value);
+ if (value != null && value.length() > 0
+ && !ExtensionLoader.getExtensionLoader(type).hasExtension(value)) {
+ throw new IllegalStateException("No such extension " + value + " for " + property + "/" + type.getName());
+ }
+ }
+
+ protected static void checkMultiExtension(Class<?> type, String property, String value) {
+ checkMultiName(property, value);
+ if (value != null && value.length() > 0) {
+ String[] values = value.split("\\s*[,]+\\s*");
+ for (String v : values) {
+ if (v.startsWith(Constants.REMOVE_VALUE_PREFIX)) {
+ v = v.substring(1);
+ }
+ if (Constants.DEFAULT_KEY.equals(v)) {
+ continue;
+ }
+ if (!ExtensionLoader.getExtensionLoader(type).hasExtension(v)) {
+ throw new IllegalStateException("No such extension " + v + " for " + property + "/" + type.getName());
+ }
+ }
+ }
+ }
+
+ protected static void checkLength(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, null);
+ }
+
+ protected static void checkPathLength(String property, String value) {
+ checkProperty(property, value, MAX_PATH_LENGTH, null);
+ }
+
+ protected static void checkName(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_NAME);
+ }
+
+ protected static void checkNameHasSymbol(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_NAME_HAS_SYMBOL);
+ }
+
+ protected static void checkKey(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_KEY);
+ }
+
+ protected static void checkMultiName(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_MULTI_NAME);
+ }
+
+ protected static void checkPathName(String property, String value) {
+ checkProperty(property, value, MAX_PATH_LENGTH, PATTERN_PATH);
+ }
+
+ protected static void checkMethodName(String property, String value) {
+ checkProperty(property, value, MAX_LENGTH, PATTERN_METHOD_NAME);
+ }
+
+ protected static void checkParameterName(Map<String, String> parameters) {
+ if (parameters == null || parameters.size() == 0) {
+ return;
+ }
+ for (Map.Entry<String, String> entry : parameters.entrySet()) {
+ checkNameHasSymbol(entry.getKey(), entry.getValue());
+ }
+ }
+
+ protected static void checkProperty(String property, String value, int maxlength, Pattern pattern) {
+ if (value == null || value.length() == 0) {
+ return;
+ }
+ if (value.length() > maxlength) {
+ throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" is longer than " + maxlength);
+ }
+ if (pattern != null) {
+ Matcher matcher = pattern.matcher(value);
+ if (!matcher.matches()) {
+ throw new IllegalStateException("Invalid " + property + "=\"" + value + "\" contains illegal " +
+ "character, only digit, letter, '-', '_' or '.' is legal.");
+ }
+ }
+ }
+
++ protected static Set<String> getSubProperties(Map<String, String> properties, String prefix) {
++ return properties.keySet().stream().filter(k -> k.contains(prefix)).map(k -> {
++ k = k.substring(prefix.length());
++ return k.substring(0, k.indexOf("."));
++ }).collect(Collectors.toSet());
++ }
++
++ private static String extractPropertyName(Class<?> clazz, Method setter) throws Exception {
++ String propertyName = setter.getName().substring("set".length());
++ Method getter = null;
++ try {
++ getter = clazz.getMethod("get" + propertyName);
++ } catch (NoSuchMethodException e) {
++ getter = clazz.getMethod("is" + propertyName);
++ }
++ Parameter parameter = getter.getAnnotation(Parameter.class);
++ if (parameter != null && StringUtils.isNotEmpty(parameter.key()) && parameter.useKeyAsProperty()) {
++ propertyName = parameter.key();
++ } else {
++ propertyName = propertyName.substring(0, 1).toLowerCase() + propertyName.substring(1);
++ }
++ return propertyName;
++ }
++
++ private static String calculatePropertyFromGetter(String name) {
++ int i = name.startsWith("get") ? 3 : 2;
++ return StringUtils.camelToSplitName(name.substring(i, i + 1).toLowerCase() + name.substring(i + 1), ".");
++ }
++
++ private static String calculateAttributeFromGetter(String getter) {
++ int i = getter.startsWith("get") ? 3 : 2;
++ return getter.substring(i, i + 1).toLowerCase() + getter.substring(i + 1);
++ }
++
+ @Parameter(excluded = true)
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
++ public void updateIdIfAbsent(String value) {
++ if (StringUtils.isNotEmpty(value) && StringUtils.isEmpty(id)) {
++ this.id = value;
++ }
++ }
++
+ protected void appendAnnotation(Class<?> annotationClass, Object annotation) {
+ Method[] methods = annotationClass.getMethods();
+ for (Method method : methods) {
+ if (method.getDeclaringClass() != Object.class
+ && method.getReturnType() != void.class
+ && method.getParameterTypes().length == 0
+ && Modifier.isPublic(method.getModifiers())
+ && !Modifier.isStatic(method.getModifiers())) {
+ try {
+ String property = method.getName();
+ if ("interfaceClass".equals(property) || "interfaceName".equals(property)) {
+ property = "interface";
+ }
+ String setter = "set" + property.substring(0, 1).toUpperCase() + property.substring(1);
+ Object value = method.invoke(annotation);
+ if (value != null && !value.equals(method.getDefaultValue())) {
+ Class<?> parameterType = ReflectUtils.getBoxedClass(method.getReturnType());
+ if ("filter".equals(property) || "listener".equals(property)) {
+ parameterType = String.class;
+ value = StringUtils.join((String[]) value, ",");
+ } else if ("parameters".equals(property)) {
+ parameterType = Map.class;
+ value = CollectionUtils.toStringMap((String[]) value);
+ }
+ try {
+ Method setterMethod = getClass().getMethod(setter, parameterType);
+ setterMethod.invoke(this, value);
+ } catch (NoSuchMethodException e) {
+ // ignore
+ }
+ }
+ } catch (Throwable e) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ }
+ }
+
++ /**
++ * Should be called after Config was fully initialized.
++ * // FIXME: this method should be completely replaced by appendParameters
++ *
++ * @return
++ * @see AbstractConfig#appendParameters(Map, Object, String)
++ * <p>
++ * Notice! This method should include all properties in the returning map, treat @Parameter differently compared to appendParameters.
++ */
++ public Map<String, String> getMetaData() {
++ Map<String, String> metaData = new HashMap<>();
++ Method[] methods = this.getClass().getMethods();
++ for (Method method : methods) {
++ try {
++ String name = method.getName();
++ if ((name.startsWith("get") || name.startsWith("is"))
++ && !name.equals("get")
++ && !"getClass".equals(name)
++ && Modifier.isPublic(method.getModifiers())
++ && method.getParameterTypes().length == 0
++ && ClassHelper.isPrimitive(method.getReturnType())) {
++ String prop = calculateAttributeFromGetter(name);
++ String key;
++ Parameter parameter = method.getAnnotation(Parameter.class);
++ if (parameter != null && parameter.key().length() > 0 && parameter.useKeyAsProperty()) {
++ key = parameter.key();
++ } else {
++ key = prop;
++ }
++ // treat url and configuration differently, the value should always present in configuration though it may not need to present in url.
++ //if (method.getReturnType() == Object.class || parameter != null && parameter.excluded()) {
++ if (method.getReturnType() == Object.class) {
++ metaData.put(key, null);
++ continue;
++ }
++ Object value = method.invoke(this);
++ String str = String.valueOf(value).trim();
++ if (value != null && str.length() > 0) {
++ // ignore escape, keep the original value.
++ /*if (parameter != null && parameter.escaped()) {
++ str = URL.encode(str);
++ }*/
++ if (parameter != null && parameter.append()) {
++ String pre = String.valueOf(metaData.get(Constants.DEFAULT_KEY + "." + key));
++ if (pre != null && pre.length() > 0) {
++ str = pre + "," + str;
++ }
++ pre = String.valueOf(metaData.get(key));
++ if (pre != null && pre.length() > 0) {
++ str = pre + "," + str;
++ }
++ }
++ /* if (prefix != null && prefix.length() > 0) {
++ key = prefix + "." + key;
++ }*/
++ metaData.put(key, str);
++ } else {
++ metaData.put(key, null);
++ }
++ // TODO check required somewhere else.
++ /*else if (parameter != null && parameter.required()) {
++ throw new IllegalStateException(this.getClass().getSimpleName() + "." + key + " == null");
++ }*/
++ } else if ("getParameters".equals(name)
++ && Modifier.isPublic(method.getModifiers())
++ && method.getParameterTypes().length == 0
++ && method.getReturnType() == Map.class) {
++ Map<String, String> map = (Map<String, String>) method.invoke(this, new Object[0]);
++ if (map != null && map.size() > 0) {
++// String pre = (prefix != null && prefix.length() > 0 ? prefix + "." : "");
++ for (Map.Entry<String, String> entry : map.entrySet()) {
++ metaData.put(entry.getKey().replace('-', '.'), entry.getValue());
++ }
++ }
++ }
++ } catch (Exception e) {
++ throw new IllegalStateException(e.getMessage(), e);
++ }
++ }
++ return metaData;
++ }
++
++ @Parameter(excluded = true)
++ public String getPrefix() {
++ return StringUtils.isNotEmpty(prefix) ? prefix : (Constants.DUBBO + "." + getTagName(this.getClass()));
++ }
++
++ public void setPrefix(String prefix) {
++ this.prefix = prefix;
++ }
++
++ /**
++ * TODO: Currently, only support overriding of properties explicitly defined in Config class, doesn't support
++ * overriding of customized parameters stored in 'parameters'.
++ */
++ public void refresh() {
++ try {
++ Environment env = Environment.getInstance();
++ env.addAppConfig(getPrefix(), getId(), getMetaData());
++ Configuration configuration = env.getConfiguration(getPrefix(), getId());
++
++ // loop methods, get override value and set the new value back to method
++ Method[] methods = getClass().getMethods();
++ for (Method method : methods) {
++ if (ClassHelper.isSetter(method)) {
++ try {
++ String value = configuration.getString(extractPropertyName(getClass(), method));
++ // isTypeMatch() is called to avoid duplicate and incorrect update, for example, we have two 'setGeneric' methods in ReferenceConfig.
++ if (value != null && ClassHelper.isTypeMatch(method.getParameterTypes()[0], value)) {
++ method.invoke(this, ClassHelper.convertPrimitive(method.getParameterTypes()[0], value));
++ }
++ } catch (NoSuchMethodException e) {
++ logger.info("Failed to override the property " + method.getName() + " in " +
++ this.getClass().getSimpleName() +
++ ", please make sure every property has getter/setter method provided.");
++ }
++ }
++ }
++ } catch (Exception e) {
++ logger.error("Failed to override ", e);
++ }
++ }
++
+ @Override
+ public String toString() {
+ try {
+ StringBuilder buf = new StringBuilder();
+ buf.append("<dubbo:");
+ buf.append(getTagName(getClass()));
+ Method[] methods = getClass().getMethods();
+ for (Method method : methods) {
+ try {
- String name = method.getName();
- if ((name.startsWith("get") || name.startsWith("is"))
- && !"get".equals(name) && !"is".equals(name)
- && !"getClass".equals(name) && !"getObject".equals(name)
- && Modifier.isPublic(method.getModifiers())
- && method.getParameterTypes().length == 0
- && isPrimitive(method.getReturnType())) {
- int i = name.startsWith("get") ? 3 : 2;
- String key = name.substring(i, i + 1).toLowerCase() + name.substring(i + 1);
++ if (ClassHelper.isGetter(method)) {
++ String name = method.getName();
++ String key = calculateAttributeFromGetter(name);
+ Object value = method.invoke(this);
+ if (value != null) {
+ buf.append(" ");
+ buf.append(key);
+ buf.append("=\"");
+ buf.append(value);
+ buf.append("\"");
+ }
+ }
+ } catch (Exception e) {
+ logger.warn(e.getMessage(), e);
+ }
+ }
+ buf.append(" />");
+ return buf.toString();
+ } catch (Throwable t) {
+ logger.warn(t.getMessage(), t);
+ return super.toString();
+ }
+ }
+
++ /**
++ * FIXME check @Parameter(required=true) and any conditions that need to match.
++ */
++ @Parameter(excluded = true)
++ public boolean isValid() {
++ return true;
++ }
++
+}
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
index 57535ac,06c9e12..22d50dd
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/DubboShutdownHook.java
@@@ -35,24 -35,20 +35,23 @@@ public class DubboShutdownHook extends
private static final Logger logger = LoggerFactory.getLogger(DubboShutdownHook.class);
private static final DubboShutdownHook dubboShutdownHook = new DubboShutdownHook("DubboShutdownHook");
-
- public static DubboShutdownHook getDubboShutdownHook() {
- return dubboShutdownHook;
- }
-
/**
+ * Has it already been registered or not?
+ */
+ private final AtomicBoolean registered = new AtomicBoolean(false);
+ /**
* Has it already been destroyed or not?
*/
- private final AtomicBoolean destroyed;
+ private final AtomicBoolean destroyed= new AtomicBoolean(false);
private DubboShutdownHook(String name) {
super(name);
- this.destroyed = new AtomicBoolean(false);
}
+ public static DubboShutdownHook getDubboShutdownHook() {
+ return dubboShutdownHook;
+ }
+
@Override
public void run() {
if (logger.isInfoEnabled()) {
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index 7ec277d,2389b33..5144fc2
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@@ -490,46 -552,10 +513,52 @@@ public class ReferenceConfig<T> extend
return buf.toString();
}
+ @Override
+ @Parameter(excluded = true)
+ public String getPrefix() {
+ return Constants.DUBBO + ".reference." + interfaceName;
+ }
+
+ private void resolveFile() {
+ String resolve = System.getProperty(interfaceName);
+ String resolveFile = null;
+ if (resolve == null || resolve.length() == 0) {
+ resolveFile = System.getProperty("dubbo.resolve.file");
+ if (resolveFile == null || resolveFile.length() == 0) {
+ File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");
+ if (userResolveFile.exists()) {
+ resolveFile = userResolveFile.getAbsolutePath();
+ }
+ }
+ if (resolveFile != null && resolveFile.length() > 0) {
+ Properties properties = new Properties();
+ FileInputStream fis = null;
+ try {
+ fis = new FileInputStream(new File(resolveFile));
+ properties.load(fis);
+ } catch (IOException e) {
+ throw new IllegalStateException("Unload " + resolveFile + ", cause: " + e.getMessage(), e);
+ } finally {
+ try {
+ if (null != fis) {
+ fis.close();
+ }
+ } catch (IOException e) {
+ logger.warn(e.getMessage(), e);
+ }
+ }
+ resolve = properties.getProperty(interfaceName);
+ }
+ }
+ if (resolve != null && resolve.length() > 0) {
+ url = resolve;
+ if (logger.isWarnEnabled()) {
+ if (resolveFile != null) {
+ logger.warn("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service.");
+ } else {
+ logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service.");
+ }
+ }
+ }
+ }
}
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index 37539eb,fc5d251..1d20a57
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@@ -301,12 -285,46 +286,41 @@@ public class ServiceConfig<T> extends A
throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + interfaceName);
}
}
- checkApplication();
- checkRegistry();
- checkProtocol();
- appendProperties(this);
checkStub(interfaceClass);
checkMock(interfaceClass);
+ }
+
+ public synchronized void export() {
+ checkAndUpdateSubConfigs();
+
+ if (provider != null) {
+ if (export == null) {
+ export = provider.getExport();
+ }
+ if (delay == null) {
+ delay = provider.getDelay();
+ }
+ }
+ if (export != null && !export) {
+ return;
+ }
+
+ if (delay != null && delay > 0) {
- delayExportExecutor.schedule(new Runnable() {
- @Override
- public void run() {
- doExport();
- }
- }, delay, TimeUnit.MILLISECONDS);
++ delayExportExecutor.schedule(this::doExport, delay, TimeUnit.MILLISECONDS);
+ } else {
+ doExport();
+ }
+ }
+
+ protected synchronized void doExport() {
+ if (unexported) {
+ throw new IllegalStateException("Already unexported!");
+ }
+ if (exported) {
+ return;
+ }
+ exported = true;
+
if (path == null || path.length() == 0) {
path = interfaceName;
}
diff --cc dubbo-config/dubbo-config-api/src/test/resources/log4j.xml
index 5007dd1,8607f5d..bfc37a8
--- a/dubbo-config/dubbo-config-api/src/test/resources/log4j.xml
+++ b/dubbo-config/dubbo-config-api/src/test/resources/log4j.xml
@@@ -1,28 -1,28 +1,28 @@@
- <!--
- 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.
- -->
- <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
- <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
- <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
- <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n"/>
- </layout>
- </appender>
- <root>
- <level value="INFO"/>
- <appender-ref ref="CONSOLE"/>
- </root>
+ <!--
+ 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.
+ -->
+ <!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
+ <log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/" debug="false">
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <layout class="org.apache.log4j.PatternLayout">
- <param name="ConversionPattern" value="[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n"/>
++ <param name="ConversionPattern" value="[%d{dd/MM/yy HH:mm:ss:SSS z}] %t %5p %c{2}: %m%n"/>
+ </layout>
+ </appender>
+ <root>
+ <level value="INFO"/>
+ <appender-ref ref="CONSOLE"/>
+ </root>
</log4j:configuration>
diff --cc dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderConsumerRegTable.java
index 5149760,3f3f018..620c534
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderConsumerRegTable.java
+++ b/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/support/ProviderConsumerRegTable.java
@@@ -23,10 -22,10 +22,12 @@@ import org.apache.dubbo.registry.integr
import org.apache.dubbo.rpc.Invoker;
import java.util.Collections;
+import java.util.Map;
+import java.util.Objects;
+ import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+ import java.util.concurrent.ConcurrentMap;
/**
* @date 2017/11/23
diff --cc dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/RegistryDirectoryTest.java
index 8c8b8ea,3a65eb9..b271773
--- a/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/RegistryDirectoryTest.java
+++ b/dubbo-registry/dubbo-registry-default/src/test/java/org/apache/dubbo/registry/dubbo/RegistryDirectoryTest.java
@@@ -29,12 -29,10 +29,10 @@@ import org.apache.dubbo.rpc.Invoker
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.RpcException;
import org.apache.dubbo.rpc.RpcInvocation;
- import org.apache.dubbo.rpc.cluster.Router;
import org.apache.dubbo.rpc.cluster.loadbalance.LeastActiveLoadBalance;
import org.apache.dubbo.rpc.cluster.loadbalance.RoundRobinLoadBalance;
- import org.apache.dubbo.rpc.cluster.router.script.ScriptRouter;
import org.apache.dubbo.rpc.cluster.router.script.ScriptRouterFactory;
-
+import org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
diff --cc dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
index 26669ce,7c63bc7..cfad21c
--- a/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
+++ b/dubbo-rpc/dubbo-rpc-api/src/main/java/org/apache/dubbo/rpc/model/ApplicationModel.java
@@@ -73,11 -75,11 +75,19 @@@ public class ApplicationModel
}
}
+ public static String getApplication() {
+ return application;
+ }
+
+ public static void setApplication(String application) {
+ ApplicationModel.application = application;
+ }
++
+ /**
+ * For unit test
+ */
+ public static void reset() {
+ providedServices.clear();
+ consumedServices.clear();
+ }
}
diff --cc dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
index 14ab124,4addbf3..08444f7
--- a/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
+++ b/dubbo-rpc/dubbo-rpc-dubbo/src/test/java/org/apache/dubbo/rpc/protocol/dubbo/DubboInvokerAvilableTest.java
@@@ -97,7 -92,7 +97,6 @@@ public class DubboInvokerAvilableTest
try{
System.setProperty(Constants.SHUTDOWN_WAIT_KEY, "2000");
- System.out.println("------------ConfigUtils.getServerShutdownTimeout(): " + ConfigUtils.getServerShutdownTimeout());
- System.out.println("------------ConfigUtils.getServerShutdownTimeout(): " + ConfigurationUtils.getServerShutdownTimeout());
protocol.destroy();
}finally {
System.getProperties().remove(Constants.SHUTDOWN_WAIT_KEY);