You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by me...@apache.org on 2020/07/02 09:08:38 UTC
[dubbo] branch master updated: 2.7.8 Rlease (#6398)
This is an automated email from the ASF dual-hosted git repository.
mercyblitz pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo.git
The following commit(s) were added to refs/heads/master by this push:
new 4aaaea4 2.7.8 Rlease (#6398)
4aaaea4 is described below
commit 4aaaea43ae75bee99837183c5be37ca2cb942741
Author: Mercy Ma <me...@gmail.com>
AuthorDate: Thu Jul 2 17:08:09 2020 +0800
2.7.8 Rlease (#6398)
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService
* 2.7.8 service introspection (#6300)
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService
* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* 2.7.8 service introspection update (#6308)
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert the MetadataReport
* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event
* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure
Deprecated List :
- NacosMetadataReport
- ZookeeperMetadataReport
* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Bugfix
* 2.7.8 service introspection (#6317)
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert the MetadataReport
* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure
Deprecated List :
- NacosMetadataReport
- ZookeeperMetadataReport
* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Correct words
* Polish apache/dubbo#6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event
* Polish apache/dubbo#6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping
* 2.7.8 service introspection (#6337)
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert the MetadataReport
* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure
Deprecated List :
- NacosMetadataReport
- ZookeeperMetadataReport
* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Correct words
* Polish apache/dubbo#6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event
* Polish apache/dubbo#6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping
* Polish apache/dubbo#6170 : [Feature] Introducing the externalized configuration for ServiceNameMapping
* Polish apache/dubbo#6342 : [Enhancement] Introducing the composite ServiceNameMapping
* Refactor
* Polish apache/dubbo#6172 : [Feature] Adding the "services" attribute methods into @DubboReference
* Polish apache/dubbo#6173 : [Feature] Adding the "services" attribute into <dubbo:reference> element
* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services
* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services
* Polish apache/dubbo#6252
* Polish apache/dubbo#6356 & apache/dubbo#6171
* Polish apache/dubbo#6356 & apache/dubbo#6171
* Polish apache/dubbo#6224 : Filter chain was not invoked with local calls since v2.7.6
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* 2.7.8 service introspection (#6366)
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert the MetadataReport
* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure
Deprecated List :
- NacosMetadataReport
- ZookeeperMetadataReport
* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Correct words
* Polish apache/dubbo#6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event
* Polish apache/dubbo#6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping
* Polish apache/dubbo#6170 : [Feature] Introducing the externalized configuration for ServiceNameMapping
* Polish apache/dubbo#6342 : [Enhancement] Introducing the composite ServiceNameMapping
* Refactor
* Polish apache/dubbo#6172 : [Feature] Adding the "services" attribute methods into @DubboReference
* Polish apache/dubbo#6173 : [Feature] Adding the "services" attribute into <dubbo:reference> element
* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services
* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services
* Polish apache/dubbo#6252
* Polish apache/dubbo#6356 & apache/dubbo#6171
* Polish apache/dubbo#6356 & apache/dubbo#6171
* Polish apache/dubbo#6224 : Filter chain was not invoked with local calls since v2.7.6
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : Adding META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* 2.7.8 Test Cases (#6384)
* Polish apache/dubbo#6152
* Polish apache/dubbo#6174 : [Enhancement] Registering the common beans for Spring XML meta-configuration
* Polish apache/dubbo#6174 : Fixing the test-cases
* Polish apache/dubbo#6174 : Fixing the test-cases
* Add the test-case for multiple services with MethodConfigs
* Fixed the test-cases
* 2.7.8 Dev (#6386)
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6296 : Adding the new methods into MetadataReport to manipulate the exported URLs for service introspection
* Polish apache/dubbo#6171 : [Feature] Introducing the composite implementation of MetadataService
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert "fix wrong check of InvokerListener when export a service (fix issue_6269) (#6271)"
This reverts commit 91989cae508f8482f31ac335879da4a5975661c8.
* Revert the MetadataReport
* Polish apache/dubbo#6305 : [Refactor] ServiceConfig and ReferenceConfig publish the ServiceDefinition based on the Dubbo Event
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6310 : Refactoring MetadataReport's methods
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6198 : [Issue] Fixing NacosDynamicConfiguration#publishConfig bug
* Polish apache/dubbo#6315 : [Refactor] Refactoring the implementation of MetadataReport based on The Config-Center infrastructure
Deprecated List :
- NacosMetadataReport
- ZookeeperMetadataReport
* Polish apache/dubbo#6315 : Refactoring by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Refactoring ConsulDynamicConfiguration by TreePathDynamicConfiguration
* Polish apache/dubbo#6315 : Reset the config base path to be "metadata" for ConfigCenterBasedMetadataReportFactory
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Bugfix
* Polish apache/dubbo#6315 : Correct words
* sync wait netty server to finish shutdown (#6281)
* Polish apache/dubbo#6333 : [Refactor] Using mandatory implementation of Service Instance registration instead of the event
* maybe we can remove null judge in this case (#6321)
* update
* update
* Polish apache/dubbo#6336 : [Refactor] org.apache.dubbo.metadata.ServiceNameMapping
* Polish apache/dubbo#6170 : [Feature] Introducing the externalized configuration for ServiceNameMapping
* Polish apache/dubbo#6342 : [Enhancement] Introducing the composite ServiceNameMapping
* Refactor
* fix method name typo in JValidator.java (#6344)
* [Dubbo-6340]fix application cannot exit when use consul registry (#6341)
* fix application cannot exit when use consul registry
* make consul registry suppor ACL (#6313)
* make consul registry suppor ACL
* Polish apache/dubbo#6172 : [Feature] Adding the "services" attribute methods into @DubboReference
* Polish apache/dubbo#6173 : [Feature] Adding the "services" attribute into <dubbo:reference> element
* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services
* Polish apache/dubbo#6346 : [Issue] Merging all subscribied URLs from the multiple services
* fix publish null value when use consul config center (#6351)
* fix publish null value when use consul config center
* Polish apache/dubbo#6252
* Polish apache/dubbo#6356 & apache/dubbo#6171
* Polish apache/dubbo#6356 & apache/dubbo#6171
* Polish apache/dubbo#6224 : Filter chain was not invoked with local calls since v2.7.6
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : Adding META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
* fix the priority of ListenableRouter were not effective (#6148)
fixes #4822
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* when the url is generic, the log level should be info (#6363)
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* fix NPE when check=false is set and provider is empty. (#6376)
fixes #6228
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* fix #6306. support TypeBuilder sort (#6365)
* fix #6306. support TypeBuilder sort
* fix #6306. support TypeBuilder sort
* fix #6306. support TypeBuilder sort
* remove unused import
* add license for test file
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* enhance ClusterInvoker & ExtensionLoader (#6343)
- Introduce ClusterInvoker to better support multiple registries subscription
- Wrapper sort and enable/disable
- some small fixes
* Polish apache/dubbo#6322 : [Enhancement] Fix the issues of test-cases after refactoring
* Fixed the test-cases
Co-authored-by: tswstarplanet <ts...@apache.org>
Co-authored-by: Nine <ni...@gmail.com>
Co-authored-by: 陈哈哈 <ch...@outlook.com>
Co-authored-by: luoning810 <18...@163.com>
Co-authored-by: cvictory <sh...@gmail.com>
Co-authored-by: ken.lj <ke...@gmail.com>
* Fixes the issue of merging code in Github
* Polish apache/dubbo#6389 : [Issue] Resolving the issues with ConsulServiceDiscovery
* Fixes the test-cases
* Fixes the test-cases
* Fixes the test-cases
Co-authored-by: tswstarplanet <ts...@apache.org>
Co-authored-by: Nine <ni...@gmail.com>
Co-authored-by: 陈哈哈 <ch...@outlook.com>
Co-authored-by: luoning810 <18...@163.com>
Co-authored-by: cvictory <sh...@gmail.com>
Co-authored-by: ken.lj <ke...@gmail.com>
---
dubbo-all/pom.xml | 8 +
.../org/apache/dubbo/rpc/cluster/Configurator.java | 2 +-
.../src/main/java/org/apache/dubbo/common/URL.java | 59 +-
.../configcenter/AbstractDynamicConfiguration.java | 103 +-
.../AbstractDynamicConfigurationFactory.java | 2 +-
.../config/configcenter/DynamicConfiguration.java | 10 +
.../configcenter/TreePathDynamicConfiguration.java | 171 ++
.../file/FileSystemDynamicConfiguration.java | 150 +-
.../dubbo/common/constants/CommonConstants.java | 29 +
.../dubbo/common/constants/RegistryConstants.java | 2 +
.../org/apache/dubbo/common/convert/Converter.java | 17 +
.../convert/multiple/MultiValueConverter.java | 28 +
.../org/apache/dubbo/common/utils/PathUtils.java | 7 +-
.../utils/StringConstantFieldValuePredicate.java | 67 +
.../org/apache/dubbo/common/utils/StringUtils.java | 57 +-
.../dubbo/config/annotation/DubboReference.java | 9 +
.../apache/dubbo/config/context/ConfigManager.java | 13 +-
.../java/org/apache/dubbo/event/EventListener.java | 2 +-
.../test/java/org/apache/dubbo/common/URLTest.java | 1777 ++++++++++----------
.../AbstractDynamicConfigurationTest.java | 60 +-
.../file/FileSystemDynamicConfigurationTest.java | 45 +-
.../common/constants/CommonConstantsTest.java | 32 +-
.../convert/ConverterTest.java} | 40 +-
.../convert/StringToBooleanConverterTest.java | 5 +-
.../convert/StringToCharArrayConverterTest.java | 5 +-
.../convert/StringToCharacterConverterTest.java | 5 +-
.../convert/StringToDoubleConverterTest.java | 5 +-
.../convert/StringToFloatConverterTest.java | 5 +-
.../convert/StringToIntegerConverterTest.java | 5 +-
.../convert/StringToLongConverterTest.java | 5 +-
.../convert/StringToOptionalConverterTest.java | 5 +-
.../convert/StringToShortConverterTest.java | 5 +-
.../convert/StringToStringConverterTest.java | 5 +-
.../convert/multiple/MultiValueConverterTest.java | 72 +
.../multiple/StringToArrayConverterTest.java | 4 +-
.../StringToBlockingDequeConverterTest.java | 4 +-
.../StringToBlockingQueueConverterTest.java | 4 +-
.../multiple/StringToCollectionConverterTest.java | 5 +-
.../multiple/StringToDequeConverterTest.java | 4 +-
.../multiple/StringToListConverterTest.java | 4 +-
.../StringToNavigableSetConverterTest.java | 6 +-
.../multiple/StringToQueueConverterTest.java | 3 +-
.../convert/multiple/StringToSetConverterTest.java | 3 +-
.../multiple/StringToSortedSetConverterTest.java | 6 +-
.../StringToTransferQueueConverterTest.java | 6 +-
.../apache/dubbo/common/utils/PojoUtilsTest.java | 2 +-
.../StringConstantFieldValuePredicateTest.java | 37 +-
.../apache/dubbo/common/utils/StringUtilsTest.java | 73 +-
.../dubbo/config/context/ConfigManagerTest.java | 7 +-
.../org/apache/dubbo/event/EchoEventListener2.java | 2 +-
.../java/org/apache/dubbo/config/ConfigTest.java | 4 +-
.../apache/dubbo/config/ReferenceConfigTest.java | 4 +-
dubbo-config/dubbo-config-api/pom.xml | 31 +
.../org/apache/dubbo/config/ReferenceConfig.java | 68 +-
.../org/apache/dubbo/config/ServiceConfig.java | 18 +-
.../dubbo/config/bootstrap/DubboBootstrap.java | 196 ++-
.../bootstrap/builders/ReferenceBuilder.java | 22 +
.../config/bootstrap/builders/RegistryBuilder.java | 10 +
.../PublishingServiceDefinitionListener.java | 74 +
.../event/listener/ServiceNameMappingListener.java | 8 +-
.../metadata/AbstractMetadataServiceExporter.java | 150 ++
.../ConfigurableMetadataServiceExporter.java | 69 +-
.../metadata/RemoteMetadataServiceExporter.java | 79 +
.../dubbo/config/utils/ConfigValidationUtils.java | 7 +-
.../internal/org.apache.dubbo.event.EventListener | 4 +-
...g.apache.dubbo.metadata.MetadataServiceExporter | 3 +
.../apache/dubbo/config/ReferenceConfigTest.java | 5 +-
...va => ConsulDubboServiceConsumerBootstrap.java} | 10 +-
...va => ConsulDubboServiceProviderBootstrap.java} | 10 +-
.../NacosDubboServiceConsumerBootstrap.java | 21 +-
.../NacosDubboServiceProviderBootstrap.java | 20 +-
.../ZookeeperDubboServiceConsumerBootstrap.java | 13 +-
.../ZookeeperDubboServiceProviderBootstrap.java | 11 +-
.../bootstrap/builders/ReferenceBuilderTest.java | 15 +-
.../bootstrap/builders/RegistryBuilderTest.java | 2 +-
.../PublishingServiceDefinitionListenerTest.java | 94 ++
.../RemoteMetadataServiceExporterTest.java | 106 ++
.../config/url/ExporterSideConfigUrlTest.java | 5 +-
.../metadata/MetadataServiceExporterTest.java | 38 +-
dubbo-config/dubbo-config-spring/pom.xml | 21 +
.../ReferenceAnnotationBeanPostProcessor.java | 92 +-
.../schema/AnnotationBeanDefinitionParser.java | 10 +-
.../spring/schema/DubboBeanDefinitionParser.java | 45 +-
.../src/main/resources/META-INF/dubbo.xsd | 17 +-
.../ReferenceAnnotationBeanPostProcessorTest.java | 13 +
.../annotation/ReferenceBeanBuilderTest.java | 29 +-
.../ServiceAnnotationBeanPostProcessorTest.java | 13 +
.../annotation/ServiceClassPostProcessorTest.java | 13 +
.../MultipleServicesWithMethodConfigsTest.java} | 30 +-
.../DubboComponentScanRegistrarTest.java | 4 +-
.../spring/context/annotation/EnableDubboTest.java | 4 +-
.../consumer/test/TestConsumerConfiguration.java | 5 +-
.../properties/DefaultDubboConfigBinderTest.java | 13 +
.../dubbo/config/spring/issues/Issue6252Test.java | 50 +
.../ZookeeperDubboSpringConsumerBootstrap.java | 53 +
.../ZookeeperDubboSpringConsumerXmlBootstrap.java | 32 +-
.../ZookeeperDubboSpringProviderBootstrap.java | 60 +
.../spring/schema/DubboNamespaceHandlerTest.java | 4 +-
.../config/spring/schema/GenericServiceTest.java | 13 +
.../resources/META-INF/issue-6252-test.properties | 11 +
.../zookeeper-dubbb-consumer.properties | 14 +
.../zookeeper-dubbb-provider.properties | 10 +
.../zookeeper-dubbo-consumer.xml | 34 +
.../spring/multiple-services-with-methods.xml | 45 +
.../consul/ConsulDynamicConfiguration.java | 123 +-
.../consul/ConsulDynamicConfigurationTest.java | 26 +-
.../support/nacos/NacosDynamicConfiguration.java | 64 +-
.../zookeeper/ZookeeperDynamicConfiguration.java | 68 +-
.../ZookeeperDynamicConfigurationTest.java | 4 +-
.../metadata/CompositeServiceNameMapping.java | 96 ++
.../DynamicConfigurationServiceNameMapping.java | 41 +-
.../apache/dubbo/metadata/MetadataConstants.java | 25 +-
.../org/apache/dubbo/metadata/MetadataService.java | 7 +-
.../dubbo/metadata/MetadataServiceExporter.java | 41 +-
.../apache/dubbo/metadata/MetadataServiceType.java | 72 +
.../org/apache/dubbo/metadata/MetadataUtil.java | 49 -
.../metadata/ParameterizedServiceNameMapping.java} | 31 +-
.../metadata/PropertiesFileServiceNameMapping.java | 148 ++
.../metadata/ReadOnlyServiceNameMapping.java} | 31 +-
.../apache/dubbo/metadata/ServiceNameMapping.java | 34 +-
.../dubbo}/metadata/URLRevisionResolver.java | 69 +-
.../dubbo/metadata/WritableMetadataService.java | 8 +-
.../dubbo/metadata/report/MetadataReport.java | 132 +-
.../BaseApplicationMetadataIdentifier.java | 9 +-
.../metadata/report/identifier/KeyTypeEnum.java | 40 +-
.../report/support/AbstractMetadataReport.java | 133 +-
.../support/ConfigCenterBasedMetadataReport.java | 162 ++
.../ConfigCenterBasedMetadataReportFactory.java | 86 +
.../file/FileSystemMetadataReportFactory.java} | 21 +-
.../AbstractAbstractWritableMetadataService.java | 100 ++
.../store/BaseWritableMetadataService.java | 73 -
.../store/InMemoryWritableMetadataService.java | 62 +-
.../store/RemoteWritableMetadataService.java | 173 +-
.../RemoteWritableMetadataServiceDelegate.java | 100 --
.../org.apache.dubbo.metadata.ServiceNameMapping | 10 +-
...g.apache.dubbo.metadata.WritableMetadataService | 2 +-
...che.dubbo.metadata.report.MetadataReportFactory | 1 +
.../metadata/CompositeServiceNameMappingTest.java | 107 ++
...DynamicConfigurationServiceNameMappingTest.java | 25 +-
.../InMemoryWritableMetadataServiceTest.java | 16 +-
.../dubbo/metadata/MetadataConstantsTest.java} | 23 +-
.../dubbo/metadata/MetadataServiceTypeTest.java | 37 +-
.../ParameterizedServiceNameMappingTest.java | 67 +
.../PropertiesFileServiceNameMappingTest.java | 60 +
.../dubbo/metadata/ServiceNameMappingTest.java | 121 ++
.../dubbo}/metadata/URLRevisionResolverTest.java | 21 +-
.../report/identifier/KeyTypeEnumTest.java} | 20 +-
.../support/AbstractMetadataReportFactoryTest.java | 9 +-
.../report/support/AbstractMetadataReportTest.java | 121 +-
.../ConfigCenterBasedMetadataReportTest.java | 155 ++
.../store/InMemoryWritableMetadataServiceTest.java | 20 +-
.../RemoteWritableMetadataServiceDelegateTest.java | 216 ---
...java => RemoteWritableMetadataServiceTest.java} | 24 +-
.../META-INF/dubbo/service-name-mapping.properties | 3 +
.../dubbo-metadata-report-consul/pom.xml | 8 +-
.../store/consul/ConsulMetadataReport.java | 4 +
.../store/consul/ConsulMetadataReportFactory.java | 13 +-
dubbo-metadata/dubbo-metadata-report-nacos/pom.xml | 9 +-
.../metadata/store/nacos/NacosMetadataReport.java | 131 +-
.../store/nacos/NacosMetadataReportFactory.java | 13 +-
.../store/nacos/NacosMetadataReportTest.java | 247 ---
.../dubbo-metadata-report-zookeeper/pom.xml | 2 +-
.../store/zookeeper/ZookeeperMetadataReport.java | 29 +
.../zookeeper/ZookeeperMetadataReportFactory.java | 22 +-
.../zookeeper/ZookeeperMetadataReportTest.java | 553 +++---
.../registry/client/ServiceDiscoveryRegistry.java | 143 +-
.../dubbo/registry/client/ServiceInstance.java | 22 +
.../CustomizableServiceInstanceListener.java | 2 +
...ExportedServicesRevisionMetadataCustomizer.java | 1 +
.../metadata/RefreshServiceMetadataCustomizer.java | 47 -
.../metadata/ServiceInstanceMetadataUtils.java | 4 +-
.../StandardMetadataServiceURLBuilder.java | 1 +
...bscribedServicesRevisionMetadataCustomizer.java | 1 +
.../proxy/BaseMetadataServiceProxyFactory.java | 32 +-
.../CompositeMetadataServiceProxyFactory.java | 133 ++
.../proxy/MetadataServiceProxyFactory.java | 1 -
.../metadata/proxy/RemoteMetadataServiceProxy.java | 52 +-
.../internal/org.apache.dubbo.event.EventListener | 6 +-
...dubbo.registry.client.ServiceInstanceCustomizer | 3 +-
...ient.metadata.proxy.MetadataServiceProxyFactory | 3 +-
.../client/DefaultServiceInstanceTest.java | 9 +
.../proxy/BaseMetadataServiceProxyFactoryTest.java | 78 +
.../CompositeMetadataServiceProxyFactoryTest.java | 96 ++
.../proxy/MetadataServiceProxyFactoryTest.java | 49 +
.../proxy/MyMetadataServiceProxyFactory.java | 17 +-
...ient.metadata.proxy.MetadataServiceProxyFactory | 2 +
.../dubbo/registry/consul/ConsulParameter.java | 87 +
.../registry/consul/ConsulServiceDiscovery.java | 89 +-
.../consul/ConsulServiceDiscoveryTest.java | 16 +-
.../registry/eureka/EurekaServiceDiscovery.java | 5 +-
.../remoting/transport/netty4/NettyServer.java | 2 +-
.../java/org/apache/dubbo/rpc/RpcContextTest.java | 2 -
.../rpc/protocol/dubbo/ArgumentCallbackTest.java | 19 +-
193 files changed, 6424 insertions(+), 3329 deletions(-)
diff --git a/dubbo-all/pom.xml b/dubbo-all/pom.xml
index 5c2936e..050ae24 100644
--- a/dubbo-all/pom.xml
+++ b/dubbo-all/pom.xml
@@ -981,6 +981,14 @@
</resource>
</transformer>
+ <!-- @since 2.7.8 -->
+ <transformer
+ implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+ <resource>
+ META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
+ </resource>
+ </transformer>
+
</transformers>
<filters>
<filter>
diff --git a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java
index 436f0dc..2a69f6e 100644
--- a/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java
+++ b/dubbo-cluster/src/main/java/org/apache/dubbo/rpc/cluster/Configurator.java
@@ -27,9 +27,9 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
-import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.EMPTY_PROTOCOL;
+import static org.apache.dubbo.rpc.cluster.Constants.PRIORITY_KEY;
/**
* Configurator. (SPI, Prototype, ThreadSafe)
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
index e605643..6ab3a89 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/URL.java
@@ -35,10 +35,12 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.function.Predicate;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_VALUE;
@@ -55,6 +57,8 @@ import static org.apache.dubbo.common.constants.CommonConstants.PORT_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.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.common.convert.Converter.convertIfPossible;
+import static org.apache.dubbo.common.utils.StringUtils.isBlank;
/**
* URL - Uniform Resource Locator (Immutable, ThreadSafe)
@@ -566,6 +570,24 @@ class URL implements Serializable {
return parameters;
}
+ /**
+ * Get the parameters to be selected(filtered)
+ *
+ * @param nameToSelect the {@link Predicate} to select the parameter name
+ * @return non-null {@link Map}
+ * @since 2.7.8
+ */
+ public Map<String, String> getParameters(Predicate<String> nameToSelect) {
+ Map<String, String> selectedParameters = new LinkedHashMap<>();
+ for (Map.Entry<String, String> entry : getParameters().entrySet()) {
+ String name = entry.getKey();
+ if (nameToSelect.test(name)) {
+ selectedParameters.put(name, entry.getValue());
+ }
+ }
+ return Collections.unmodifiableMap(selectedParameters);
+ }
+
public Map<String, Map<String, String>> getMethodParameters() {
return methodParameters;
}
@@ -601,6 +623,41 @@ class URL implements Serializable {
return Arrays.asList(strArray);
}
+ /**
+ * Get parameter
+ *
+ * @param key the key of parameter
+ * @param valueType the type of parameter value
+ * @param <T> the type of parameter value
+ * @return get the parameter if present, or <code>null</code>
+ * @since 2.7.8
+ */
+ public <T> T getParameter(String key, Class<T> valueType) {
+ return getParameter(key, valueType, null);
+ }
+
+ /**
+ * Get parameter
+ *
+ * @param key the key of parameter
+ * @param valueType the type of parameter value
+ * @param defaultValue the default value if parameter is absent
+ * @param <T> the type of parameter value
+ * @return get the parameter if present, or <code>defaultValue</code> will be used.
+ * @since 2.7.8
+ */
+ public <T> T getParameter(String key, Class<T> valueType, T defaultValue) {
+ String value = getParameter(key);
+ T result = null;
+ if (!isBlank(value)) {
+ result = convertIfPossible(value, valueType);
+ }
+ if (result == null) {
+ result = defaultValue;
+ }
+ return result;
+ }
+
private Map<String, Number> getNumbers() {
// concurrent initialization is tolerant
if (numbers == null) {
@@ -1415,7 +1472,7 @@ class URL implements Serializable {
private void append(StringBuilder target, String parameterName, boolean first) {
String parameterValue = this.getParameter(parameterName);
- if (!StringUtils.isBlank(parameterValue)) {
+ if (!isBlank(parameterValue)) {
if (!first) {
target.append(":");
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfiguration.java
index 6e85982..31c3684 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfiguration.java
@@ -20,6 +20,7 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.NamedThreadFactory;
+import org.apache.dubbo.common.utils.StringUtils;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@@ -27,6 +28,9 @@ import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.TIMEOUT_KEY;
+
/**
* The abstract implementation of {@link DynamicConfiguration}
*
@@ -47,6 +51,20 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
*/
public static final String THREAD_POOL_KEEP_ALIVE_TIME_PARAM_NAME = PARAM_NAME_PREFIX + "thread-pool.keep-alive-time";
+ /**
+ * The parameter name of group for config-center
+ *
+ * @since 2.7.8
+ */
+ public static final String GROUP_PARAM_NAME = PARAM_NAME_PREFIX + GROUP_KEY;
+
+ /**
+ * The parameter name of timeout for config-center
+ *
+ * @since 2.7.8
+ */
+ public static final String TIMEOUT_PARAM_NAME = PARAM_NAME_PREFIX + TIMEOUT_KEY;
+
public static final int DEFAULT_THREAD_POOL_SIZE = 1;
/**
@@ -64,28 +82,31 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
*/
private final ThreadPoolExecutor workersThreadPool;
- public AbstractDynamicConfiguration() {
- this(DEFAULT_THREAD_POOL_PREFIX, DEFAULT_THREAD_POOL_SIZE, DEFAULT_THREAD_POOL_KEEP_ALIVE_TIME);
- }
+ private final String group;
+
+ private final long timeout;
public AbstractDynamicConfiguration(URL url) {
- this(getThreadPoolPrefixName(url), getThreadPoolSize(url), getThreadPoolKeepAliveTime(url));
+ this(getThreadPoolPrefixName(url), getThreadPoolSize(url), getThreadPoolKeepAliveTime(url), getGroup(url),
+ getTimeout(url));
}
public AbstractDynamicConfiguration(String threadPoolPrefixName,
int threadPoolSize,
- long keepAliveTime) {
+ long keepAliveTime,
+ String group,
+ long timeout) {
this.workersThreadPool = initWorkersThreadPool(threadPoolPrefixName, threadPoolSize, keepAliveTime);
+ this.group = group;
+ this.timeout = timeout;
}
@Override
public void addListener(String key, String group, ConfigurationListener listener) {
-
}
@Override
public void removeListener(String key, String group, ConfigurationListener listener) {
-
}
@Override
@@ -107,6 +128,29 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
}
}
+ @Override
+ public boolean removeConfig(String key, String group) {
+ return execute(() -> doRemoveConfig(key, group), -1L);
+ }
+
+ /**
+ * @return the default group
+ * @since 2.7.8
+ */
+ @Override
+ public String getDefaultGroup() {
+ return getGroup();
+ }
+
+ /**
+ * @return the default timeout
+ * @since 2.7.8
+ */
+ @Override
+ public long getDefaultTimeout() {
+ return getTimeout();
+ }
+
/**
* Get the content of configuration in the specified key and group
*
@@ -125,6 +169,17 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
protected abstract void doClose() throws Exception;
/**
+ * Remove the config in the specified key and group
+ *
+ * @param key the key
+ * @param group the group
+ * @return If successful, return <code>true</code>, or <code>false</code>
+ * @throws Exception
+ * @since 2.7.8
+ */
+ protected abstract boolean doRemoveConfig(String key, String group) throws Exception;
+
+ /**
* Executes the {@link Runnable} with the specified timeout
*
* @param task the {@link Runnable task}
@@ -181,7 +236,7 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
int threadPoolSize,
long keepAliveTime) {
return new ThreadPoolExecutor(threadPoolSize, threadPoolSize, keepAliveTime,
- TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory(threadPoolPrefixName));
+ TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new NamedThreadFactory(threadPoolPrefixName, true));
}
protected static String getThreadPoolPrefixName(URL url) {
@@ -216,4 +271,36 @@ public abstract class AbstractDynamicConfiguration implements DynamicConfigurati
}
return defaultValue;
}
+
+
+ protected String getGroup() {
+ return group;
+ }
+
+ protected long getTimeout() {
+ return timeout;
+ }
+
+ /**
+ * Get the group from {@link URL the specified connection URL}
+ *
+ * @param url {@link URL the specified connection URL}
+ * @return non-null
+ * @since 2.7.8
+ */
+ protected static String getGroup(URL url) {
+ String group = getParameter(url, GROUP_PARAM_NAME, null);
+ return StringUtils.isBlank(group) ? getParameter(url, GROUP_KEY, DEFAULT_GROUP) : group;
+ }
+
+ /**
+ * Get the timeout from {@link URL the specified connection URL}
+ *
+ * @param url {@link URL the specified connection URL}
+ * @return non-null
+ * @since 2.7.8
+ */
+ protected static long getTimeout(URL url) {
+ return getParameter(url, TIMEOUT_PARAM_NAME, -1L);
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationFactory.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationFactory.java
index eb35b9b..db53e73 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationFactory.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationFactory.java
@@ -35,7 +35,7 @@ public abstract class AbstractDynamicConfigurationFactory implements DynamicConf
@Override
public final DynamicConfiguration getDynamicConfiguration(URL url) {
- String key = url == null ? DEFAULT_KEY : url.getAddress();
+ String key = url == null ? DEFAULT_KEY : url.toServiceString();
return dynamicConfigurations.computeIfAbsent(key, k -> createDynamicConfiguration(url));
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
index 5cda5bf..0b57396 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
@@ -232,4 +232,14 @@ public interface DynamicConfiguration extends Configuration, AutoCloseable {
static String getRuleKey(URL url) {
return url.getColonSeparatedKey();
}
+
+ /**
+ * @param key the key to represent a configuration
+ * @param group the group where the key belongs to
+ * @return <code>true</code> if success, or <code>false</code>
+ * @since 2.7.8
+ */
+ default boolean removeConfig(String key, String group) {
+ return true;
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java
new file mode 100644
index 0000000..cbcb3a2
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/TreePathDynamicConfiguration.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.config.configcenter;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration;
+import org.apache.dubbo.common.utils.PathUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+
+import java.util.Collection;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import static java.util.Collections.emptySortedSet;
+import static java.util.Collections.unmodifiableSortedSet;
+import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
+import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
+import static org.apache.dubbo.common.utils.PathUtils.buildPath;
+
+/**
+ * An abstract implementation of {@link DynamicConfiguration} is like "tree-structure" path :
+ * <ul>
+ * <li>{@link FileSystemDynamicConfiguration "file"}</li>
+ * <li>{@link org.apache.dubbo.configcenter.support.zookeeper.ZookeeperDynamicConfiguration "zookeeper"}</li>
+ * <li>{@link org.apache.dubbo.configcenter.consul.ConsulDynamicConfiguration "consul"}</li>
+ * </ul>
+ *
+ * @see DynamicConfiguration
+ * @see AbstractDynamicConfiguration
+ * @since 2.7.8
+ */
+public abstract class TreePathDynamicConfiguration extends AbstractDynamicConfiguration {
+
+ /**
+ * The parameter name of URL for the config base path
+ */
+ public static final String CONFIG_BASE_PATH_PARAM_NAME = PARAM_NAME_PREFIX + "base-path";
+
+ /**
+ * The default value of parameter of URL for the config base path
+ */
+ public static final String DEFAULT_CONFIG_BASE_PATH = "/config";
+
+ private final String rootPath;
+
+ public TreePathDynamicConfiguration(URL url) {
+ super(url);
+ this.rootPath = getRootPath(url);
+ }
+
+ public TreePathDynamicConfiguration(String rootPath,
+ String threadPoolPrefixName,
+ int threadPoolSize,
+ long keepAliveTime,
+ String group,
+ long timeout) {
+ super(threadPoolPrefixName, threadPoolSize, keepAliveTime, group, timeout);
+ this.rootPath = rootPath;
+ }
+
+ @Override
+ protected final String doGetConfig(String key, String group) throws Exception {
+ String pathKey = buildPathKey(group, key);
+ return doGetConfig(pathKey);
+ }
+
+ @Override
+ public final boolean publishConfig(String key, String group, String content) {
+ String pathKey = buildPathKey(group, key);
+ return execute(() -> doPublishConfig(pathKey, content), getDefaultTimeout());
+ }
+
+ @Override
+ protected final boolean doRemoveConfig(String key, String group) throws Exception {
+ String pathKey = buildPathKey(group, key);
+ return doRemoveConfig(pathKey);
+ }
+
+ @Override
+ public final void addListener(String key, String group, ConfigurationListener listener) {
+ String pathKey = buildPathKey(group, key);
+ doAddListener(pathKey, listener);
+ }
+
+ @Override
+ public final void removeListener(String key, String group, ConfigurationListener listener) {
+ String pathKey = buildPathKey(group, key);
+ doRemoveListener(pathKey, listener);
+ }
+
+ @Override
+ public final SortedSet<String> getConfigKeys(String group) throws UnsupportedOperationException {
+ String groupPath = buildGroupPath(group);
+ Collection<String> configKeys = doGetConfigKeys(groupPath);
+ return isEmpty(configKeys) ? emptySortedSet() : unmodifiableSortedSet(new TreeSet<>(configKeys));
+ }
+
+ protected abstract boolean doPublishConfig(String pathKey, String content) throws Exception;
+
+ protected abstract String doGetConfig(String pathKey) throws Exception;
+
+ protected abstract boolean doRemoveConfig(String pathKey) throws Exception;
+
+ protected abstract Collection<String> doGetConfigKeys(String groupPath);
+
+ protected abstract void doAddListener(String pathKey, ConfigurationListener listener);
+
+ protected abstract void doRemoveListener(String pathKey, ConfigurationListener listener);
+
+ protected String buildGroupPath(String group) {
+ return buildPath(rootPath, group);
+ }
+
+ protected String buildPathKey(String group, String key) {
+ return buildPath(buildGroupPath(group), key);
+ }
+
+ /**
+ * Get the root path from the specified {@link URL connection URl}
+ *
+ * @param url the specified {@link URL connection URl}
+ * @return non-null
+ */
+ protected String getRootPath(URL url) {
+ String rootPath = PATH_SEPARATOR + getConfigNamespace(url) + getConfigBasePath(url);
+ rootPath = PathUtils.normalize(rootPath);
+ if (rootPath.endsWith(PATH_SEPARATOR)) {
+ rootPath = rootPath.substring(0, rootPath.length() - 1);
+ }
+ return rootPath;
+ }
+
+ /**
+ * Get the namespace from the specified {@link URL connection URl}
+ *
+ * @param url the specified {@link URL connection URl}
+ * @return non-null
+ */
+ protected String getConfigNamespace(URL url) {
+ return url.getParameter(CONFIG_NAMESPACE_KEY, DEFAULT_GROUP);
+ }
+
+ /**
+ * Get the config base path from the specified {@link URL connection URl}
+ *
+ * @param url the specified {@link URL connection URl}
+ * @return non-null
+ */
+ protected String getConfigBasePath(URL url) {
+ String configBasePath = url.getParameter(CONFIG_BASE_PATH_PARAM_NAME, DEFAULT_CONFIG_BASE_PATH);
+ if (StringUtils.isNotEmpty(configBasePath) && !configBasePath.startsWith(PATH_SEPARATOR)) {
+ configBasePath = PATH_SEPARATOR + configBasePath;
+ }
+ return configBasePath;
+ }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
index 36fb61f..0c9178f 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfiguration.java
@@ -17,13 +17,14 @@
package org.apache.dubbo.common.config.configcenter.file;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.TreePathDynamicConfiguration;
import org.apache.dubbo.common.function.ThrowableConsumer;
import org.apache.dubbo.common.function.ThrowableFunction;
+import org.apache.dubbo.common.lang.ShutdownHookCallbacks;
import org.apache.dubbo.common.utils.NamedThreadFactory;
import org.apache.dubbo.common.utils.StringUtils;
@@ -39,6 +40,7 @@ import java.nio.file.Path;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
@@ -48,7 +50,6 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.Callable;
import java.util.concurrent.SynchronousQueue;
@@ -67,14 +68,13 @@ import static java.util.Collections.unmodifiableMap;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.apache.commons.io.FileUtils.readFileToString;
-import static org.apache.dubbo.common.utils.StringUtils.isBlank;
/**
* File-System based {@link DynamicConfiguration} implementation
*
* @since 2.7.5
*/
-public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration {
+public class FileSystemDynamicConfiguration extends TreePathDynamicConfiguration {
public static final String CONFIG_CENTER_DIR_PARAM_NAME = PARAM_NAME_PREFIX + "dir";
@@ -147,6 +147,7 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
MODIFIERS = initWatchEventModifiers();
DELAY = initDelay(MODIFIERS);
WATCH_EVENTS_LOOP_THREAD_POOL = newWatchEventsLoopThreadPool();
+ registerDubboShutdownHook();
}
/**
@@ -193,7 +194,7 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
String threadPoolPrefixName,
int threadPoolSize,
long keepAliveTime) {
- super(threadPoolPrefixName, threadPoolSize, keepAliveTime);
+ super(rootDirectory.getAbsolutePath(), threadPoolPrefixName, threadPoolSize, keepAliveTime, DEFAULT_GROUP, -1L);
this.rootDirectory = rootDirectory;
this.encoding = encoding;
this.processingDirectories = initProcessingDirectories();
@@ -209,47 +210,13 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
return isBasedPoolingWatchService() ? new LinkedHashSet<>() : emptySet();
}
- @Override
- public void addListener(String key, String group, ConfigurationListener listener) {
- doInListener(key, group, (configFilePath, listeners) -> {
-
- if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before
- ThrowableConsumer.execute(configFilePath, configFile -> {
- FileUtils.forceMkdirParent(configFile);
- // A rootDirectory to be watched
- File configDirectory = configFile.getParentFile();
- if (configDirectory != null) {
- // Register the configDirectory
- configDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, MODIFIERS);
- }
- });
- }
-
- // Add into cache
- listeners.add(listener);
- });
- }
-
- @Override
- public void removeListener(String key, String group, ConfigurationListener listener) {
- doInListener(key, group, (file, listeners) -> {
- // Remove into cache
- listeners.remove(listener);
- });
- }
-
- public File groupDirectory(String group) {
- String actualGroup = isBlank(group) ? DEFAULT_GROUP : group;
- return new File(rootDirectory, actualGroup);
- }
-
public File configFile(String key, String group) {
- return new File(groupDirectory(group), key);
+ return new File(buildPathKey(group, key));
}
- private void doInListener(String key, String group, BiConsumer<File, List<ConfigurationListener>> consumer) {
+ private void doInListener(String configFilePath, BiConsumer<File, List<ConfigurationListener>> consumer) {
watchService.ifPresent(watchService -> {
- File configFile = configFile(key, group);
+ File configFile = new File(configFilePath);
executeMutually(configFile.getParentFile(), () -> {
// process the WatchEvents if not start
if (!isProcessingWatchEvents()) {
@@ -265,6 +232,24 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
});
}
+ /**
+ * Register the Dubbo ShutdownHook
+ *
+ * @since 2.7.8
+ */
+ private static void registerDubboShutdownHook() {
+ ShutdownHookCallbacks.INSTANCE.addCallback(() -> {
+ watchService.ifPresent(w -> {
+ try {
+ w.close();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ getWatchEventsLoopThreadPool().shutdown();
+ });
+ }
+
private static boolean isProcessingWatchEvents() {
return getWatchEventsLoopThreadPool().getActiveCount() > 0;
}
@@ -359,47 +344,78 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
}
@Override
- public boolean publishConfig(String key, String group, String content) {
- return delay(key, group, configFile -> {
+ protected boolean doPublishConfig(String pathKey, String content) throws Exception {
+ return delay(pathKey, configFile -> {
FileUtils.write(configFile, content, getEncoding());
return true;
});
}
@Override
- public SortedSet<String> getConfigKeys(String group) {
- File[] files = groupDirectory(group).listFiles(File::isFile);
+ protected String doGetConfig(String pathKey) throws Exception {
+ File configFile = new File(pathKey);
+ return getConfig(configFile);
+ }
+
+ @Override
+ protected boolean doRemoveConfig(String pathKey) throws Exception {
+ delay(pathKey, configFile -> {
+ String content = getConfig(configFile);
+ FileUtils.deleteQuietly(configFile);
+ return content;
+ });
+ return true;
+ }
+
+ @Override
+ protected Collection<String> doGetConfigKeys(String groupPath) {
+ File[] files = new File(groupPath).listFiles(File::isFile);
if (files == null) {
return new TreeSet<>();
} else {
return Stream.of(files)
.map(File::getName)
- .collect(TreeSet::new, Set::add, Set::addAll);
+ .collect(Collectors.toList());
}
}
- public String removeConfig(String key, String group) {
- return delay(key, group, configFile -> {
-
- String content = getConfig(configFile);
-
- FileUtils.deleteQuietly(configFile);
+ @Override
+ protected void doAddListener(String pathKey, ConfigurationListener listener) {
+ doInListener(pathKey, (configFilePath, listeners) -> {
+ if (listeners.isEmpty()) { // If no element, it indicates watchService was registered before
+ ThrowableConsumer.execute(configFilePath, configFile -> {
+ FileUtils.forceMkdirParent(configFile);
+ // A rootDirectory to be watched
+ File configDirectory = configFile.getParentFile();
+ if (configDirectory != null) {
+ // Register the configDirectory
+ configDirectory.toPath().register(watchService.get(), INTEREST_PATH_KINDS, MODIFIERS);
+ }
+ });
+ }
+ // Add into cache
+ listeners.add(listener);
+ });
+ }
- return content;
+ @Override
+ protected void doRemoveListener(String pathKey, ConfigurationListener listener) {
+ doInListener(pathKey, (file, listeners) -> {
+ // Remove into cache
+ listeners.remove(listener);
});
}
/**
* Delay action for {@link #configFile(String, String) config file}
*
- * @param key the key to represent a configuration
- * @param group the group where the key belongs to
- * @param function the customized {@link Function function} with {@link File}
- * @param <V> the computed value
+ * @param configFilePath the key to represent a configuration
+ * @param function the customized {@link Function function} with {@link File}
+ * @param <V> the computed value
* @return
*/
- protected <V> V delay(String key, String group, ThrowableFunction<File, V> function) {
- File configFile = configFile(key, group);
+ protected <V> V delay(String configFilePath, ThrowableFunction<File, V> function) {
+ File configFile = new File(configFilePath);
// Must be based on PoolingWatchService and has listeners under config file
if (isBasedPoolingWatchService()) {
File configDirectory = configFile.getParentFile();
@@ -410,8 +426,8 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
// wait for delay in seconds
long timeout = SECONDS.toMillis(delay);
if (logger.isDebugEnabled()) {
- logger.debug(format("The config[key : %s, group : %s] is about to delay in %d ms.",
- key, group, timeout));
+ logger.debug(format("The config[path : %s] is about to delay in %d ms.",
+ configFilePath, timeout));
}
configDirectory.wait(timeout);
}
@@ -439,9 +455,9 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
}
/**
- * Is processing on {@link #groupDirectory(String) config rootDirectory}
+ * Is processing on {@link #buildGroupPath(String) config rootDirectory}
*
- * @param configDirectory {@link #groupDirectory(String) config rootDirectory}
+ * @param configDirectory {@link #buildGroupPath(String) config rootDirectory}
* @return if processing , return <code>true</code>, or <code>false</code>
*/
private boolean isProcessing(File configDirectory) {
@@ -459,12 +475,6 @@ public class FileSystemDynamicConfiguration extends AbstractDynamicConfiguration
.collect(Collectors.toSet());
}
- @Override
- protected String doGetConfig(String key, String group) throws Exception {
- File configFile = configFile(key, group);
- return getConfig(configFile);
- }
-
protected String getConfig(File configFile) {
return ThrowableFunction.execute(configFile,
file -> canRead(configFile) ? readFileToString(configFile, getEncoding()) : null);
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
index eca3495..657c1ab 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/CommonConstants.java
@@ -20,6 +20,7 @@ package org.apache.dubbo.common.constants;
import org.apache.dubbo.common.URL;
import java.net.NetworkInterface;
+import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.regex.Pattern;
@@ -44,6 +45,11 @@ public interface CommonConstants {
String ANY_VALUE = "*";
+ /**
+ * @since 2.7.8
+ */
+ char COMMA_SEPARATOR_CHAR = ',';
+
String COMMA_SEPARATOR = ",";
String DOT_SEPARATOR = ".";
@@ -188,6 +194,14 @@ public interface CommonConstants {
String REMOTE_METADATA_STORAGE_TYPE = "remote";
/**
+ * The composite metadata storage type includes {@link #DEFAULT_METADATA_STORAGE_TYPE "local"} and
+ * {@link #REMOTE_METADATA_STORAGE_TYPE "remote"}.
+ *
+ * @since 2.7.8
+ */
+ String COMPOSITE_METADATA_STORAGE_TYPE = "composite";
+
+ /**
* Consumer side 's proxy class
*/
String PROXY_CLASS_REF = "refClass";
@@ -315,4 +329,19 @@ public interface CommonConstants {
String SSL_ENABLED_KEY = "ssl-enabled";
+
+ /**
+ * The parameter key for the class path of the ServiceNameMapping {@link Properties} file
+ *
+ * @since 2.7.8
+ */
+ String SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY = "service-name-mapping.properties-path";
+
+ /**
+ * The default class path of the ServiceNameMapping {@link Properties} file
+ *
+ * @since 2.7.8
+ */
+ String DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH = "META-INF/dubbo/service-name-mapping.properties";
+
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java
index 465c7e3..ce83136 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/constants/RegistryConstants.java
@@ -76,6 +76,8 @@ public interface RegistryConstants {
/**
* The parameter key of the subscribed service names for Service-Oriented Registry
+ * <p>
+ * If there is a multiple-values, the "comma" is the separator.
*
* @since 2.7.5
*/
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java
index 5bc2d4d..e36fdf2 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/Converter.java
@@ -88,4 +88,21 @@ public interface Converter<S, T> extends Prioritized {
.findFirst()
.orElse(null);
}
+
+ /**
+ * Convert the value of source to target-type value if possible
+ *
+ * @param source the value of source
+ * @param targetType the target type
+ * @param <T> the target type
+ * @return <code>null</code> if can't be converted
+ * @since 2.7.8
+ */
+ static <T> T convertIfPossible(Object source, Class<T> targetType) {
+ Converter converter = getConverter(source.getClass(), targetType);
+ if (converter != null) {
+ return (T) converter.convert(source);
+ }
+ return null;
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java
index 298b459..637d1a8 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/convert/multiple/MultiValueConverter.java
@@ -16,11 +16,13 @@
*/
package org.apache.dubbo.common.convert.multiple;
+import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.common.lang.Prioritized;
import java.util.Collection;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.apache.dubbo.common.utils.TypeUtils.findActualTypeArgument;
/**
@@ -61,4 +63,30 @@ public interface MultiValueConverter<S> extends Prioritized {
return findActualTypeArgument(getClass(), MultiValueConverter.class, 0);
}
+ /**
+ * Find the {@link MultiValueConverter} instance from {@link ExtensionLoader} with the specified source and target type
+ *
+ * @param sourceType the source type
+ * @param targetType the target type
+ * @return <code>null</code> if not found
+ * @see ExtensionLoader#getSupportedExtensionInstances()
+ * @since 2.7.8
+ */
+ static MultiValueConverter<?> find(Class<?> sourceType, Class<?> targetType) {
+ return getExtensionLoader(MultiValueConverter.class)
+ .getSupportedExtensionInstances()
+ .stream()
+ .filter(converter -> converter.accept(sourceType, targetType))
+ .findFirst()
+ .orElse(null);
+ }
+
+ static <T> T convertIfPossible(Object source, Class<?> multiValueType, Class<?> elementType) {
+ Class<?> sourceType = source.getClass();
+ MultiValueConverter converter = find(sourceType, multiValueType);
+ if (converter != null) {
+ return (T) converter.convert(source, multiValueType, elementType);
+ }
+ return null;
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PathUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PathUtils.java
index 3e38ce1..c291d79 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PathUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/PathUtils.java
@@ -63,7 +63,12 @@ public interface PathUtils {
if (index > -1) {
normalizedPath = normalizedPath.substring(0, index);
}
- return replace(normalizedPath, "//", "/");
+
+ while (normalizedPath.contains("//")) {
+ normalizedPath = replace(normalizedPath, "//", "/");
+ }
+
+ return normalizedPath;
}
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringConstantFieldValuePredicate.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringConstantFieldValuePredicate.java
new file mode 100644
index 0000000..534a612
--- /dev/null
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringConstantFieldValuePredicate.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.utils;
+
+import java.lang.reflect.Field;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static java.lang.reflect.Modifier.isFinal;
+import static java.lang.reflect.Modifier.isPublic;
+import static java.lang.reflect.Modifier.isStatic;
+import static org.apache.dubbo.common.utils.FieldUtils.getFieldValue;
+
+/**
+ * The constant field value {@link Predicate} for the specified {@link Class}
+ *
+ * @see Predicate
+ * @since 2.7.8
+ */
+public class StringConstantFieldValuePredicate implements Predicate<String> {
+
+ private final Set<String> constantFieldValues;
+
+ public StringConstantFieldValuePredicate(Class<?> targetClass) {
+ this.constantFieldValues = getConstantFieldValues(targetClass);
+ }
+
+ public static Predicate<String> of(Class<?> targetClass) {
+ return new StringConstantFieldValuePredicate(targetClass);
+ }
+
+ private Set<String> getConstantFieldValues(Class<?> targetClass) {
+ return Stream.of(targetClass.getFields())
+ .filter(f -> isStatic(f.getModifiers())) // static
+ .filter(f -> isPublic(f.getModifiers())) // public
+ .filter(f -> isFinal(f.getModifiers())) // final
+ .map(this::getConstantValue)
+ .filter(v -> v instanceof String) // filters String type
+ .map(String.class::cast) // Casts String type
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public boolean test(String s) {
+ return constantFieldValues.contains(s);
+ }
+
+ private Object getConstantValue(Field field) {
+ return getFieldValue(null, field);
+ }
+}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
index 42ee05b..fc44475 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/utils/StringUtils.java
@@ -28,13 +28,17 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.lang.String.valueOf;
+import static java.util.Collections.emptySet;
+import static java.util.Collections.unmodifiableSet;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.DOT_REGEX;
@@ -700,6 +704,45 @@ public final class StringUtils {
}
/**
+ * Split the specified value to be a {@link Set}
+ *
+ * @param value the content to be split
+ * @param separatorChar a char to separate
+ * @return non-null read-only {@link Set}
+ * @since 2.7.8
+ */
+ public static Set<String> splitToSet(String value, char separatorChar) {
+ return splitToSet(value, separatorChar, false);
+ }
+
+ /**
+ * Split the specified value to be a {@link Set}
+ *
+ * @param value the content to be split
+ * @param separatorChar a char to separate
+ * @param trimElements require to trim the elements or not
+ * @return non-null read-only {@link Set}
+ * @since 2.7.8
+ */
+ public static Set<String> splitToSet(String value, char separatorChar, boolean trimElements) {
+ List<String> values = splitToList(value, separatorChar);
+ int size = values.size();
+
+ if (size < 1) { // empty condition
+ return emptySet();
+ }
+
+ if (!trimElements) { // Do not require to trim the elements
+ return new LinkedHashSet(values);
+ }
+
+ return unmodifiableSet(values
+ .stream()
+ .map(String::trim)
+ .collect(LinkedHashSet::new, Set::add, Set::addAll));
+ }
+
+ /**
* join string.
*
* @param array String array.
@@ -797,7 +840,7 @@ public final class StringUtils {
}
public static String getQueryStringValue(String qs, String key) {
- Map<String, String> map = StringUtils.parseQueryString(qs);
+ Map<String, String> map = parseQueryString(qs);
return map.get(key);
}
@@ -1051,4 +1094,16 @@ public final class StringUtils {
return (byte) ((hi << 4) + lo);
}
+ /**
+ * Create the common-delimited {@link String} by one or more {@link String} members
+ *
+ * @param one one {@link String}
+ * @param others others {@link String}
+ * @return <code>null</code> if <code>one</code> or <code>others</code> is <code>null</code>
+ * @since 2.7.8
+ */
+ public static String toCommaDelimitedString(String one, String... others) {
+ String another = arrayToDelimitedString(others, COMMA_SEPARATOR);
+ return isEmpty(another) ? one : one + COMMA_SEPARATOR + another;
+ }
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboReference.java b/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboReference.java
index eb1a2e6..5492ac0 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboReference.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/annotation/DubboReference.java
@@ -16,6 +16,8 @@
*/
package org.apache.dubbo.config.annotation;
+import org.apache.dubbo.common.constants.RegistryConstants;
+
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
@@ -279,4 +281,11 @@ public @interface DubboReference {
* @since 2.7.3
*/
String id() default "";
+
+ /**
+ * @return The service names that the Dubbo interface subscribed
+ * @see RegistryConstants#SUBSCRIBED_SERVICE_NAMES_KEY
+ * @since 2.7.8
+ */
+ String[] services() default {};
}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
index ed0188a..868fadc 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/config/context/ConfigManager.java
@@ -67,10 +67,10 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
public static final String NAME = "config";
- private final Map<String, Map<String, AbstractConfig>> configsCache = newMap();
-
private final ReadWriteLock lock = new ReentrantReadWriteLock();
+ final Map<String, Map<String, AbstractConfig>> configsCache = newMap();
+
public ConfigManager() {
}
@@ -372,6 +372,15 @@ public class ConfigManager extends LifecycleAdapter implements FrameworkExt {
}
/**
+ * @throws IllegalStateException
+ * @since 2.7.8
+ */
+ @Override
+ public void destroy() throws IllegalStateException {
+ clear();
+ }
+
+ /**
* Add the dubbo {@link AbstractConfig config}
*
* @param config the dubbo {@link AbstractConfig config}
diff --git a/dubbo-common/src/main/java/org/apache/dubbo/event/EventListener.java b/dubbo-common/src/main/java/org/apache/dubbo/event/EventListener.java
index 06c6f6a..bb36c77 100644
--- a/dubbo-common/src/main/java/org/apache/dubbo/event/EventListener.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/event/EventListener.java
@@ -56,7 +56,7 @@ public interface EventListener<E extends Event> extends java.util.EventListener,
* The comparison rule , refer to {@link #compareTo}.
*/
default int getPriority() {
- return MIN_PRIORITY;
+ return NORMAL_PRIORITY;
}
/**
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java
index db5f57b..5ba606d 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/URLTest.java
@@ -1,877 +1,900 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.common;
-
-import org.apache.dubbo.common.utils.CollectionUtils;
-
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.hamcrest.CoreMatchers.anyOf;
-import static org.hamcrest.CoreMatchers.equalTo;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertSame;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.junit.jupiter.api.Assertions.fail;
-
-public class URLTest {
-
- @Test
- public void test_valueOf_noProtocolAndHost() throws Exception {
- URL url = URL.valueOf("/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertNull(url.getHost());
- assertNull(url.getAddress());
- assertEquals(0, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
-
- url = URL.valueOf("context/path?version=1.0.0&application=morgan");
- // ^^^^^^^ Caution , parse as host
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertEquals("context", url.getHost());
- assertEquals(0, url.getPort());
- assertEquals("path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
- }
-
- private void assertURLStrDecoder(URL url) {
- String fullURLStr = url.toFullString();
- URL newUrl = URLStrParser.parseEncodedStr(URL.encode(fullURLStr));
- assertEquals(URL.valueOf(fullURLStr), newUrl);
-
- URL newUrl2 = URLStrParser.parseDecodedStr(fullURLStr);
- assertEquals(URL.valueOf(fullURLStr), newUrl2);
- }
-
- @Test
- public void test_valueOf_noProtocol() throws Exception {
- URL url = URL.valueOf("10.20.130.230");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230", url.getAddress());
- assertEquals(0, url.getPort());
- assertNull(url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("10.20.130.230:20880");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertNull(url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("10.20.130.230/context/path");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230", url.getAddress());
- assertEquals(0, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("10.20.130.230:20880/context/path");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
- }
-
- @Test
- public void test_valueOf_noHost() throws Exception {
- URL url = URL.valueOf("file:///home/user1/router.js");
- assertURLStrDecoder(url);
- assertEquals("file", url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertNull(url.getHost());
- assertNull(url.getAddress());
- assertEquals(0, url.getPort());
- assertEquals("home/user1/router.js", url.getPath());
- assertEquals(0, url.getParameters().size());
-
- // Caution!!
- url = URL.valueOf("file://home/user1/router.js");
- // ^^ only tow slash!
- assertURLStrDecoder(url);
- assertEquals("file", url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertEquals("home", url.getHost());
- assertEquals(0, url.getPort());
- assertEquals("user1/router.js", url.getPath());
- assertEquals(0, url.getParameters().size());
-
-
- url = URL.valueOf("file:/home/user1/router.js");
- assertURLStrDecoder(url);
- assertEquals("file", url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertNull(url.getHost());
- assertNull(url.getAddress());
- assertEquals(0, url.getPort());
- assertEquals("home/user1/router.js", url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("file:///d:/home/user1/router.js");
- assertURLStrDecoder(url);
- assertEquals("file", url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertNull(url.getHost());
- assertNull(url.getAddress());
- assertEquals(0, url.getPort());
- assertEquals("d:/home/user1/router.js", url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("file:///home/user1/router.js?p1=v1&p2=v2");
- assertURLStrDecoder(url);
- assertEquals("file", url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertNull(url.getHost());
- assertNull(url.getAddress());
- assertEquals(0, url.getPort());
- assertEquals("home/user1/router.js", url.getPath());
- assertEquals(2, url.getParameters().size());
- Map<String, String> params = new HashMap<String, String>();
- params.put("p1", "v1");
- params.put("p2", "v2");
- assertEquals(params, url.getParameters());
-
- url = URL.valueOf("file:/home/user1/router.js?p1=v1&p2=v2");
- assertURLStrDecoder(url);
- assertEquals("file", url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertNull(url.getHost());
- assertNull(url.getAddress());
- assertEquals(0, url.getPort());
- assertEquals("home/user1/router.js", url.getPath());
- assertEquals(2, url.getParameters().size());
- params = new HashMap<String, String>();
- params.put("p1", "v1");
- params.put("p2", "v2");
- assertEquals(params, url.getParameters());
- }
-
- @Test
- public void test_valueOf_WithProtocolHost() throws Exception {
- URL url = URL.valueOf("dubbo://10.20.130.230");
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230", url.getAddress());
- assertEquals(0, url.getPort());
- assertNull(url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("dubbo://10.20.130.230:20880/context/path");
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertNull(url.getUsername());
- assertNull(url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880");
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertNull(url.getPath());
- assertEquals(0, url.getParameters().size());
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880?version=1.0.0");
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertNull(url.getPath());
- assertEquals(1, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&noValue");
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(3, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
- assertEquals("noValue", url.getParameter("noValue"));
- }
-
- // TODO Do not want to use spaces? See: DUBBO-502, URL class handles special conventions for special characters.
- @Test
- public void test_valueOf_spaceSafe() throws Exception {
- URL url = URL.valueOf("http://1.2.3.4:8080/path?key=value1 value2");
- assertURLStrDecoder(url);
- assertEquals("http://1.2.3.4:8080/path?key=value1 value2", url.toString());
- assertEquals("value1 value2", url.getParameter("key"));
- }
-
- @Test
- public void test_noValueKey() throws Exception {
- URL url = URL.valueOf("http://1.2.3.4:8080/path?k0&k1=v1");
-
- assertURLStrDecoder(url);
- assertTrue(url.hasParameter("k0"));
-
- // If a Key has no corresponding Value, then the Key also used as the Value.
- assertEquals("k0", url.getParameter("k0"));
- }
-
- @Test
- public void test_valueOf_Exception_noProtocol() throws Exception {
- try {
- URL.valueOf("://1.2.3.4:8080/path");
- fail();
- } catch (IllegalStateException expected) {
- assertEquals("url missing protocol: \"://1.2.3.4:8080/path\"", expected.getMessage());
- }
-
- try {
- String encodedURLStr = URL.encode("://1.2.3.4:8080/path");
- URLStrParser.parseEncodedStr(encodedURLStr);
- fail();
- } catch (IllegalStateException expected) {
- assertEquals("url missing protocol: \"://1.2.3.4:8080/path\"", URL.decode(expected.getMessage()));
- }
-
- try {
- URLStrParser.parseDecodedStr("://1.2.3.4:8080/path");
- fail();
- } catch (IllegalStateException expected) {
- assertEquals("url missing protocol: \"://1.2.3.4:8080/path\"", expected.getMessage());
- }
- }
-
- @Test
- public void test_getAddress() throws Exception {
- URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url1);
- assertEquals("10.20.130.230:20880", url1.getAddress());
- }
-
- @Test
- public void test_getAbsolutePath() throws Exception {
- URL url = new URL("p1", "1.2.2.2", 33);
- assertURLStrDecoder(url);
- assertNull(url.getAbsolutePath());
-
- url = new URL("file", null, 90, "/home/user1/route.js");
- assertURLStrDecoder(url);
- assertEquals("/home/user1/route.js", url.getAbsolutePath());
- }
-
- @Test
- public void test_equals() throws Exception {
- URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url1);
-
- Map<String, String> params = new HashMap<String, String>();
- params.put("version", "1.0.0");
- params.put("application", "morgan");
- URL url2 = new URL("dubbo", "admin", "hello1234", "10.20.130.230", 20880, "context/path", params);
-
- assertURLStrDecoder(url2);
- assertEquals(url1, url2);
- }
-
- @Test
- public void test_toString() throws Exception {
- URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url1);
- assertThat(url1.toString(), anyOf(
- equalTo("dubbo://10.20.130.230:20880/context/path?version=1.0.0&application=morgan"),
- equalTo("dubbo://10.20.130.230:20880/context/path?application=morgan&version=1.0.0"))
- );
- }
-
- @Test
- public void test_toFullString() throws Exception {
- URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url1);
- assertThat(url1.toFullString(), anyOf(
- equalTo("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"),
- equalTo("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&version=1.0.0"))
- );
- }
-
- @Test
- public void test_set_methods() throws Exception {
- URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url);
-
- url = url.setHost("host");
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("host", url.getHost());
- assertEquals("host:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
-
- url = url.setPort(1);
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("host", url.getHost());
- assertEquals("host:1", url.getAddress());
- assertEquals(1, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
-
- url = url.setPath("path");
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("host", url.getHost());
- assertEquals("host:1", url.getAddress());
- assertEquals(1, url.getPort());
- assertEquals("path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
-
- url = url.setProtocol("protocol");
-
- assertURLStrDecoder(url);
- assertEquals("protocol", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("host", url.getHost());
- assertEquals("host:1", url.getAddress());
- assertEquals(1, url.getPort());
- assertEquals("path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
-
- url = url.setUsername("username");
-
- assertURLStrDecoder(url);
- assertEquals("protocol", url.getProtocol());
- assertEquals("username", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("host", url.getHost());
- assertEquals("host:1", url.getAddress());
- assertEquals(1, url.getPort());
- assertEquals("path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
-
- url = url.setPassword("password");
-
- assertURLStrDecoder(url);
- assertEquals("protocol", url.getProtocol());
- assertEquals("username", url.getUsername());
- assertEquals("password", url.getPassword());
- assertEquals("host", url.getHost());
- assertEquals("host:1", url.getAddress());
- assertEquals(1, url.getPort());
- assertEquals("path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
- }
-
- @Test
- public void test_removeParameters() throws Exception {
- URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&k1=v1&k2=v2");
- assertURLStrDecoder(url);
-
- url = url.removeParameter("version");
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(3, url.getParameters().size());
- assertEquals("morgan", url.getParameter("application"));
- assertEquals("v1", url.getParameter("k1"));
- assertEquals("v2", url.getParameter("k2"));
- assertNull(url.getParameter("version"));
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&k1=v1&k2=v2");
- url = url.removeParameters("version", "application", "NotExistedKey");
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("v1", url.getParameter("k1"));
- assertEquals("v2", url.getParameter("k2"));
- assertNull(url.getParameter("version"));
- assertNull(url.getParameter("application"));
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&k1=v1&k2=v2");
- url = url.removeParameters(Arrays.asList("version", "application"));
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("v1", url.getParameter("k1"));
- assertEquals("v2", url.getParameter("k2"));
- assertNull(url.getParameter("version"));
- assertNull(url.getParameter("application"));
- }
-
- @Test
- public void test_addParameter() throws Exception {
- URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
- url = url.addParameter("k1", "v1");
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("morgan", url.getParameter("application"));
- assertEquals("v1", url.getParameter("k1"));
- }
-
- @Test
- public void test_addParameter_sameKv() throws Exception {
- URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&k1=v1");
- URL newUrl = url.addParameter("k1", "v1");
-
- assertURLStrDecoder(url);
- assertSame(newUrl, url);
- }
-
-
- @Test
- public void test_addParameters() throws Exception {
- URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
- url = url.addParameters(CollectionUtils.toStringMap("k1", "v1", "k2", "v2"));
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(3, url.getParameters().size());
- assertEquals("morgan", url.getParameter("application"));
- assertEquals("v1", url.getParameter("k1"));
- assertEquals("v2", url.getParameter("k2"));
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
- url = url.addParameters("k1", "v1", "k2", "v2", "application", "xxx");
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(3, url.getParameters().size());
- assertEquals("xxx", url.getParameter("application"));
- assertEquals("v1", url.getParameter("k1"));
- assertEquals("v2", url.getParameter("k2"));
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
- url = url.addParametersIfAbsent(CollectionUtils.toStringMap("k1", "v1", "k2", "v2", "application", "xxx"));
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(3, url.getParameters().size());
- assertEquals("morgan", url.getParameter("application"));
- assertEquals("v1", url.getParameter("k1"));
- assertEquals("v2", url.getParameter("k2"));
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
- url = url.addParameter("k1", "v1");
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("morgan", url.getParameter("application"));
- assertEquals("v1", url.getParameter("k1"));
-
- url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
- url = url.addParameter("application", "xxx");
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(1, url.getParameters().size());
- assertEquals("xxx", url.getParameter("application"));
- }
-
- @Test
- public void test_addParameters_SameKv() throws Exception {
- {
- URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&k1=v1");
- URL newUrl = url.addParameters(CollectionUtils.toStringMap("k1", "v1"));
-
- assertURLStrDecoder(url);
- assertSame(url, newUrl);
- }
- {
- URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&k1=v1&k2=v2");
- URL newUrl = url.addParameters(CollectionUtils.toStringMap("k1", "v1", "k2", "v2"));
-
- assertURLStrDecoder(url);
- assertSame(newUrl, url);
- }
- }
-
- @Test
- public void test_addParameterIfAbsent() throws Exception {
- URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
- url = url.addParameterIfAbsent("application", "xxx");
-
- assertURLStrDecoder(url);
- assertEquals("dubbo", url.getProtocol());
- assertEquals("admin", url.getUsername());
- assertEquals("hello1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(1, url.getParameters().size());
- assertEquals("morgan", url.getParameter("application"));
- }
-
- @Test
- public void test_windowAbsolutePathBeginWithSlashIsValid() throws Exception {
- final String osProperty = System.getProperties().getProperty("os.name");
- if (!osProperty.toLowerCase().contains("windows")) return;
-
- System.out.println("Test Windows valid path string.");
-
- File f0 = new File("C:/Windows");
- File f1 = new File("/C:/Windows");
-
- File f2 = new File("C:\\Windows");
- File f3 = new File("/C:\\Windows");
- File f4 = new File("\\C:\\Windows");
-
- assertEquals(f0, f1);
- assertEquals(f0, f2);
- assertEquals(f0, f3);
- assertEquals(f0, f4);
- }
-
- @Test
- public void test_javaNetUrl() throws Exception {
- java.net.URL url = new java.net.URL("http://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan#anchor1");
-
- assertEquals("http", url.getProtocol());
- assertEquals("admin:hello1234", url.getUserInfo());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals(20880, url.getPort());
- assertEquals("/context/path", url.getPath());
- assertEquals("version=1.0.0&application=morgan", url.getQuery());
- assertEquals("anchor1", url.getRef());
-
- assertEquals("admin:hello1234@10.20.130.230:20880", url.getAuthority());
- assertEquals("/context/path?version=1.0.0&application=morgan", url.getFile());
- }
-
- @Test
- public void test_Anyhost() throws Exception {
- URL url = URL.valueOf("dubbo://0.0.0.0:20880");
- assertURLStrDecoder(url);
- assertEquals("0.0.0.0", url.getHost());
- assertTrue(url.isAnyHost());
- }
-
- @Test
- public void test_Localhost() throws Exception {
- URL url = URL.valueOf("dubbo://127.0.0.1:20880");
- assertURLStrDecoder(url);
- assertEquals("127.0.0.1", url.getHost());
- assertEquals("127.0.0.1:20880", url.getAddress());
- assertTrue(url.isLocalHost());
-
- url = URL.valueOf("dubbo://127.0.1.1:20880");
- assertURLStrDecoder(url);
- assertEquals("127.0.1.1", url.getHost());
- assertEquals("127.0.1.1:20880", url.getAddress());
- assertTrue(url.isLocalHost());
-
- url = URL.valueOf("dubbo://localhost:20880");
- assertURLStrDecoder(url);
- assertEquals("localhost", url.getHost());
- assertEquals("localhost:20880", url.getAddress());
- assertTrue(url.isLocalHost());
- }
-
- @Test
- public void test_Path() throws Exception {
- URL url = new URL("dubbo", "localhost", 20880, "////path");
- assertURLStrDecoder(url);
- assertEquals("path", url.getPath());
- }
-
- @Test
- public void testAddParameters() throws Exception {
- URL url = URL.valueOf("dubbo://127.0.0.1:20880");
- assertURLStrDecoder(url);
-
- Map<String, String> parameters = new HashMap<String, String>();
- parameters.put("version", null);
- url.addParameters(parameters);
- assertURLStrDecoder(url);
- }
-
- @Test
- public void testUserNamePasswordContainsAt() {
- // Test username or password contains "@"
- URL url = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertEquals("ad@min", url.getUsername());
- assertEquals("hello@1234", url.getPassword());
- assertEquals("10.20.130.230", url.getHost());
- assertEquals("10.20.130.230:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
- }
-
-
- @Test
- public void testIpV6Address() {
- // Test username or password contains "@"
- URL url = URL.valueOf("ad@min111:haha@1234@2001:0db8:85a3:08d3:1319:8a2e:0370:7344:20880/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertEquals("ad@min111", url.getUsername());
- assertEquals("haha@1234", url.getPassword());
- assertEquals("2001:0db8:85a3:08d3:1319:8a2e:0370:7344", url.getHost());
- assertEquals("2001:0db8:85a3:08d3:1319:8a2e:0370:7344:20880", url.getAddress());
- assertEquals(20880, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
- }
-
- @Test
- public void testIpV6AddressWithScopeId() {
- URL url = URL.valueOf("2001:0db8:85a3:08d3:1319:8a2e:0370:7344%5/context/path?version=1.0.0&application=morgan");
- assertURLStrDecoder(url);
- assertNull(url.getProtocol());
- assertEquals("2001:0db8:85a3:08d3:1319:8a2e:0370:7344%5", url.getHost());
- assertEquals("2001:0db8:85a3:08d3:1319:8a2e:0370:7344%5", url.getAddress());
- assertEquals(0, url.getPort());
- assertEquals("context/path", url.getPath());
- assertEquals(2, url.getParameters().size());
- assertEquals("1.0.0", url.getParameter("version"));
- assertEquals("morgan", url.getParameter("application"));
- }
-
- @Test
- public void testDefaultPort() {
- Assertions.assertEquals("10.20.153.10:2181", URL.appendDefaultPort("10.20.153.10:0", 2181));
- Assertions.assertEquals("10.20.153.10:2181", URL.appendDefaultPort("10.20.153.10", 2181));
- }
-
- @Test
- public void testGetServiceKey() {
- URL url1 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName");
- assertURLStrDecoder(url1);
- Assertions.assertEquals("org.apache.dubbo.test.interfaceName", url1.getServiceKey());
-
- URL url2 = URL.valueOf("10.20.130.230:20880/org.apache.dubbo.test.interfaceName?interface=org.apache.dubbo.test.interfaceName");
- assertURLStrDecoder(url2);
- Assertions.assertEquals("org.apache.dubbo.test.interfaceName", url2.getServiceKey());
-
- URL url3 = URL.valueOf("10.20.130.230:20880/org.apache.dubbo.test.interfaceName?interface=org.apache.dubbo.test.interfaceName&group=group1&version=1.0.0");
- assertURLStrDecoder(url3);
- Assertions.assertEquals("group1/org.apache.dubbo.test.interfaceName:1.0.0", url3.getServiceKey());
-
- URL url4 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName");
- assertURLStrDecoder(url4);
- Assertions.assertEquals("context/path", url4.getPathKey());
-
- URL url5 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&group=group1&version=1.0.0");
- assertURLStrDecoder(url5);
- Assertions.assertEquals("group1/context/path:1.0.0", url5.getPathKey());
- }
-
- @Test
- public void testGetColonSeparatedKey() {
- URL url1 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&group=group&version=1.0.0");
- assertURLStrDecoder(url1);
- Assertions.assertEquals("org.apache.dubbo.test.interfaceName:1.0.0:group", url1.getColonSeparatedKey());
-
- URL url2 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&version=1.0.0");
- assertURLStrDecoder(url2);
- Assertions.assertEquals("org.apache.dubbo.test.interfaceName:1.0.0:", url2.getColonSeparatedKey());
-
- URL url3 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&group=group");
- assertURLStrDecoder(url3);
- Assertions.assertEquals("org.apache.dubbo.test.interfaceName::group", url3.getColonSeparatedKey());
-
- URL url4 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName");
- assertURLStrDecoder(url4);
- Assertions.assertEquals("org.apache.dubbo.test.interfaceName::", url4.getColonSeparatedKey());
-
- URL url5 = URL.valueOf("10.20.130.230:20880/org.apache.dubbo.test.interfaceName");
- assertURLStrDecoder(url5);
- Assertions.assertEquals("org.apache.dubbo.test.interfaceName::", url5.getColonSeparatedKey());
-
- URL url6 = URL.valueOf("10.20.130.230:20880/org.apache.dubbo.test.interfaceName?interface=org.apache.dubbo.test.interfaceName1");
- assertURLStrDecoder(url6);
- Assertions.assertEquals("org.apache.dubbo.test.interfaceName1::", url6.getColonSeparatedKey());
- }
-
- @Test
- public void testValueOf() {
- URL url = URL.valueOf("10.20.130.230");
- assertURLStrDecoder(url);
-
- url = URL.valueOf("10.20.130.230:20880");
- assertURLStrDecoder(url);
-
- url = URL.valueOf("dubbo://10.20.130.230:20880");
- assertURLStrDecoder(url);
-
- url = URL.valueOf("dubbo://10.20.130.230:20880/path");
- assertURLStrDecoder(url);
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common;
+
+import org.apache.dubbo.common.utils.CollectionUtils;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.Predicate;
+
+import static org.hamcrest.CoreMatchers.anyOf;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
+public class URLTest {
+
+ @Test
+ public void test_valueOf_noProtocolAndHost() throws Exception {
+ URL url = URL.valueOf("/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertNull(url.getHost());
+ assertNull(url.getAddress());
+ assertEquals(0, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+
+ url = URL.valueOf("context/path?version=1.0.0&application=morgan");
+ // ^^^^^^^ Caution , parse as host
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertEquals("context", url.getHost());
+ assertEquals(0, url.getPort());
+ assertEquals("path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+ }
+
+ private void assertURLStrDecoder(URL url) {
+ String fullURLStr = url.toFullString();
+ URL newUrl = URLStrParser.parseEncodedStr(URL.encode(fullURLStr));
+ assertEquals(URL.valueOf(fullURLStr), newUrl);
+
+ URL newUrl2 = URLStrParser.parseDecodedStr(fullURLStr);
+ assertEquals(URL.valueOf(fullURLStr), newUrl2);
+ }
+
+ @Test
+ public void test_valueOf_noProtocol() throws Exception {
+ URL url = URL.valueOf("10.20.130.230");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230", url.getAddress());
+ assertEquals(0, url.getPort());
+ assertNull(url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("10.20.130.230:20880");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertNull(url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("10.20.130.230/context/path");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230", url.getAddress());
+ assertEquals(0, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("10.20.130.230:20880/context/path");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+ }
+
+ @Test
+ public void test_valueOf_noHost() throws Exception {
+ URL url = URL.valueOf("file:///home/user1/router.js");
+ assertURLStrDecoder(url);
+ assertEquals("file", url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertNull(url.getHost());
+ assertNull(url.getAddress());
+ assertEquals(0, url.getPort());
+ assertEquals("home/user1/router.js", url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ // Caution!!
+ url = URL.valueOf("file://home/user1/router.js");
+ // ^^ only tow slash!
+ assertURLStrDecoder(url);
+ assertEquals("file", url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertEquals("home", url.getHost());
+ assertEquals(0, url.getPort());
+ assertEquals("user1/router.js", url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+
+ url = URL.valueOf("file:/home/user1/router.js");
+ assertURLStrDecoder(url);
+ assertEquals("file", url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertNull(url.getHost());
+ assertNull(url.getAddress());
+ assertEquals(0, url.getPort());
+ assertEquals("home/user1/router.js", url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("file:///d:/home/user1/router.js");
+ assertURLStrDecoder(url);
+ assertEquals("file", url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertNull(url.getHost());
+ assertNull(url.getAddress());
+ assertEquals(0, url.getPort());
+ assertEquals("d:/home/user1/router.js", url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("file:///home/user1/router.js?p1=v1&p2=v2");
+ assertURLStrDecoder(url);
+ assertEquals("file", url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertNull(url.getHost());
+ assertNull(url.getAddress());
+ assertEquals(0, url.getPort());
+ assertEquals("home/user1/router.js", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("p1", "v1");
+ params.put("p2", "v2");
+ assertEquals(params, url.getParameters());
+
+ url = URL.valueOf("file:/home/user1/router.js?p1=v1&p2=v2");
+ assertURLStrDecoder(url);
+ assertEquals("file", url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertNull(url.getHost());
+ assertNull(url.getAddress());
+ assertEquals(0, url.getPort());
+ assertEquals("home/user1/router.js", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ params = new HashMap<String, String>();
+ params.put("p1", "v1");
+ params.put("p2", "v2");
+ assertEquals(params, url.getParameters());
+ }
+
+ @Test
+ public void test_valueOf_WithProtocolHost() throws Exception {
+ URL url = URL.valueOf("dubbo://10.20.130.230");
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230", url.getAddress());
+ assertEquals(0, url.getPort());
+ assertNull(url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("dubbo://10.20.130.230:20880/context/path");
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertNull(url.getUsername());
+ assertNull(url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880");
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertNull(url.getPath());
+ assertEquals(0, url.getParameters().size());
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880?version=1.0.0");
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertNull(url.getPath());
+ assertEquals(1, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&noValue");
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(3, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+ assertEquals("noValue", url.getParameter("noValue"));
+ }
+
+ // TODO Do not want to use spaces? See: DUBBO-502, URL class handles special conventions for special characters.
+ @Test
+ public void test_valueOf_spaceSafe() throws Exception {
+ URL url = URL.valueOf("http://1.2.3.4:8080/path?key=value1 value2");
+ assertURLStrDecoder(url);
+ assertEquals("http://1.2.3.4:8080/path?key=value1 value2", url.toString());
+ assertEquals("value1 value2", url.getParameter("key"));
+ }
+
+ @Test
+ public void test_noValueKey() throws Exception {
+ URL url = URL.valueOf("http://1.2.3.4:8080/path?k0&k1=v1");
+
+ assertURLStrDecoder(url);
+ assertTrue(url.hasParameter("k0"));
+
+ // If a Key has no corresponding Value, then the Key also used as the Value.
+ assertEquals("k0", url.getParameter("k0"));
+ }
+
+ @Test
+ public void test_valueOf_Exception_noProtocol() throws Exception {
+ try {
+ URL.valueOf("://1.2.3.4:8080/path");
+ fail();
+ } catch (IllegalStateException expected) {
+ assertEquals("url missing protocol: \"://1.2.3.4:8080/path\"", expected.getMessage());
+ }
+
+ try {
+ String encodedURLStr = URL.encode("://1.2.3.4:8080/path");
+ URLStrParser.parseEncodedStr(encodedURLStr);
+ fail();
+ } catch (IllegalStateException expected) {
+ assertEquals("url missing protocol: \"://1.2.3.4:8080/path\"", URL.decode(expected.getMessage()));
+ }
+
+ try {
+ URLStrParser.parseDecodedStr("://1.2.3.4:8080/path");
+ fail();
+ } catch (IllegalStateException expected) {
+ assertEquals("url missing protocol: \"://1.2.3.4:8080/path\"", expected.getMessage());
+ }
+ }
+
+ @Test
+ public void test_getAddress() throws Exception {
+ URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url1);
+ assertEquals("10.20.130.230:20880", url1.getAddress());
+ }
+
+ @Test
+ public void test_getAbsolutePath() throws Exception {
+ URL url = new URL("p1", "1.2.2.2", 33);
+ assertURLStrDecoder(url);
+ assertNull(url.getAbsolutePath());
+
+ url = new URL("file", null, 90, "/home/user1/route.js");
+ assertURLStrDecoder(url);
+ assertEquals("/home/user1/route.js", url.getAbsolutePath());
+ }
+
+ @Test
+ public void test_equals() throws Exception {
+ URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url1);
+
+ Map<String, String> params = new HashMap<String, String>();
+ params.put("version", "1.0.0");
+ params.put("application", "morgan");
+ URL url2 = new URL("dubbo", "admin", "hello1234", "10.20.130.230", 20880, "context/path", params);
+
+ assertURLStrDecoder(url2);
+ assertEquals(url1, url2);
+ }
+
+ @Test
+ public void test_toString() throws Exception {
+ URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url1);
+ assertThat(url1.toString(), anyOf(
+ equalTo("dubbo://10.20.130.230:20880/context/path?version=1.0.0&application=morgan"),
+ equalTo("dubbo://10.20.130.230:20880/context/path?application=morgan&version=1.0.0"))
+ );
+ }
+
+ @Test
+ public void test_toFullString() throws Exception {
+ URL url1 = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url1);
+ assertThat(url1.toFullString(), anyOf(
+ equalTo("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan"),
+ equalTo("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&version=1.0.0"))
+ );
+ }
+
+ @Test
+ public void test_set_methods() throws Exception {
+ URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url);
+
+ url = url.setHost("host");
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("host", url.getHost());
+ assertEquals("host:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+
+ url = url.setPort(1);
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("host", url.getHost());
+ assertEquals("host:1", url.getAddress());
+ assertEquals(1, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+
+ url = url.setPath("path");
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("host", url.getHost());
+ assertEquals("host:1", url.getAddress());
+ assertEquals(1, url.getPort());
+ assertEquals("path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+
+ url = url.setProtocol("protocol");
+
+ assertURLStrDecoder(url);
+ assertEquals("protocol", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("host", url.getHost());
+ assertEquals("host:1", url.getAddress());
+ assertEquals(1, url.getPort());
+ assertEquals("path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+
+ url = url.setUsername("username");
+
+ assertURLStrDecoder(url);
+ assertEquals("protocol", url.getProtocol());
+ assertEquals("username", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("host", url.getHost());
+ assertEquals("host:1", url.getAddress());
+ assertEquals(1, url.getPort());
+ assertEquals("path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+
+ url = url.setPassword("password");
+
+ assertURLStrDecoder(url);
+ assertEquals("protocol", url.getProtocol());
+ assertEquals("username", url.getUsername());
+ assertEquals("password", url.getPassword());
+ assertEquals("host", url.getHost());
+ assertEquals("host:1", url.getAddress());
+ assertEquals(1, url.getPort());
+ assertEquals("path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+ }
+
+ @Test
+ public void test_removeParameters() throws Exception {
+ URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&k1=v1&k2=v2");
+ assertURLStrDecoder(url);
+
+ url = url.removeParameter("version");
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(3, url.getParameters().size());
+ assertEquals("morgan", url.getParameter("application"));
+ assertEquals("v1", url.getParameter("k1"));
+ assertEquals("v2", url.getParameter("k2"));
+ assertNull(url.getParameter("version"));
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&k1=v1&k2=v2");
+ url = url.removeParameters("version", "application", "NotExistedKey");
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("v1", url.getParameter("k1"));
+ assertEquals("v2", url.getParameter("k2"));
+ assertNull(url.getParameter("version"));
+ assertNull(url.getParameter("application"));
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan&k1=v1&k2=v2");
+ url = url.removeParameters(Arrays.asList("version", "application"));
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("v1", url.getParameter("k1"));
+ assertEquals("v2", url.getParameter("k2"));
+ assertNull(url.getParameter("version"));
+ assertNull(url.getParameter("application"));
+ }
+
+ @Test
+ public void test_addParameter() throws Exception {
+ URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
+ url = url.addParameter("k1", "v1");
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("morgan", url.getParameter("application"));
+ assertEquals("v1", url.getParameter("k1"));
+ }
+
+ @Test
+ public void test_addParameter_sameKv() throws Exception {
+ URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&k1=v1");
+ URL newUrl = url.addParameter("k1", "v1");
+
+ assertURLStrDecoder(url);
+ assertSame(newUrl, url);
+ }
+
+
+ @Test
+ public void test_addParameters() throws Exception {
+ URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
+ url = url.addParameters(CollectionUtils.toStringMap("k1", "v1", "k2", "v2"));
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(3, url.getParameters().size());
+ assertEquals("morgan", url.getParameter("application"));
+ assertEquals("v1", url.getParameter("k1"));
+ assertEquals("v2", url.getParameter("k2"));
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
+ url = url.addParameters("k1", "v1", "k2", "v2", "application", "xxx");
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(3, url.getParameters().size());
+ assertEquals("xxx", url.getParameter("application"));
+ assertEquals("v1", url.getParameter("k1"));
+ assertEquals("v2", url.getParameter("k2"));
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
+ url = url.addParametersIfAbsent(CollectionUtils.toStringMap("k1", "v1", "k2", "v2", "application", "xxx"));
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(3, url.getParameters().size());
+ assertEquals("morgan", url.getParameter("application"));
+ assertEquals("v1", url.getParameter("k1"));
+ assertEquals("v2", url.getParameter("k2"));
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
+ url = url.addParameter("k1", "v1");
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("morgan", url.getParameter("application"));
+ assertEquals("v1", url.getParameter("k1"));
+
+ url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
+ url = url.addParameter("application", "xxx");
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(1, url.getParameters().size());
+ assertEquals("xxx", url.getParameter("application"));
+ }
+
+ @Test
+ public void test_addParameters_SameKv() throws Exception {
+ {
+ URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&k1=v1");
+ URL newUrl = url.addParameters(CollectionUtils.toStringMap("k1", "v1"));
+
+ assertURLStrDecoder(url);
+ assertSame(url, newUrl);
+ }
+ {
+ URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan&k1=v1&k2=v2");
+ URL newUrl = url.addParameters(CollectionUtils.toStringMap("k1", "v1", "k2", "v2"));
+
+ assertURLStrDecoder(url);
+ assertSame(newUrl, url);
+ }
+ }
+
+ @Test
+ public void test_addParameterIfAbsent() throws Exception {
+ URL url = URL.valueOf("dubbo://admin:hello1234@10.20.130.230:20880/context/path?application=morgan");
+ url = url.addParameterIfAbsent("application", "xxx");
+
+ assertURLStrDecoder(url);
+ assertEquals("dubbo", url.getProtocol());
+ assertEquals("admin", url.getUsername());
+ assertEquals("hello1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(1, url.getParameters().size());
+ assertEquals("morgan", url.getParameter("application"));
+ }
+
+ @Test
+ public void test_windowAbsolutePathBeginWithSlashIsValid() throws Exception {
+ final String osProperty = System.getProperties().getProperty("os.name");
+ if (!osProperty.toLowerCase().contains("windows")) return;
+
+ System.out.println("Test Windows valid path string.");
+
+ File f0 = new File("C:/Windows");
+ File f1 = new File("/C:/Windows");
+
+ File f2 = new File("C:\\Windows");
+ File f3 = new File("/C:\\Windows");
+ File f4 = new File("\\C:\\Windows");
+
+ assertEquals(f0, f1);
+ assertEquals(f0, f2);
+ assertEquals(f0, f3);
+ assertEquals(f0, f4);
+ }
+
+ @Test
+ public void test_javaNetUrl() throws Exception {
+ java.net.URL url = new java.net.URL("http://admin:hello1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan#anchor1");
+
+ assertEquals("http", url.getProtocol());
+ assertEquals("admin:hello1234", url.getUserInfo());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals(20880, url.getPort());
+ assertEquals("/context/path", url.getPath());
+ assertEquals("version=1.0.0&application=morgan", url.getQuery());
+ assertEquals("anchor1", url.getRef());
+
+ assertEquals("admin:hello1234@10.20.130.230:20880", url.getAuthority());
+ assertEquals("/context/path?version=1.0.0&application=morgan", url.getFile());
+ }
+
+ @Test
+ public void test_Anyhost() throws Exception {
+ URL url = URL.valueOf("dubbo://0.0.0.0:20880");
+ assertURLStrDecoder(url);
+ assertEquals("0.0.0.0", url.getHost());
+ assertTrue(url.isAnyHost());
+ }
+
+ @Test
+ public void test_Localhost() throws Exception {
+ URL url = URL.valueOf("dubbo://127.0.0.1:20880");
+ assertURLStrDecoder(url);
+ assertEquals("127.0.0.1", url.getHost());
+ assertEquals("127.0.0.1:20880", url.getAddress());
+ assertTrue(url.isLocalHost());
+
+ url = URL.valueOf("dubbo://127.0.1.1:20880");
+ assertURLStrDecoder(url);
+ assertEquals("127.0.1.1", url.getHost());
+ assertEquals("127.0.1.1:20880", url.getAddress());
+ assertTrue(url.isLocalHost());
+
+ url = URL.valueOf("dubbo://localhost:20880");
+ assertURLStrDecoder(url);
+ assertEquals("localhost", url.getHost());
+ assertEquals("localhost:20880", url.getAddress());
+ assertTrue(url.isLocalHost());
+ }
+
+ @Test
+ public void test_Path() throws Exception {
+ URL url = new URL("dubbo", "localhost", 20880, "////path");
+ assertURLStrDecoder(url);
+ assertEquals("path", url.getPath());
+ }
+
+ @Test
+ public void testAddParameters() throws Exception {
+ URL url = URL.valueOf("dubbo://127.0.0.1:20880");
+ assertURLStrDecoder(url);
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("version", null);
+ url.addParameters(parameters);
+ assertURLStrDecoder(url);
+ }
+
+ @Test
+ public void testUserNamePasswordContainsAt() {
+ // Test username or password contains "@"
+ URL url = URL.valueOf("ad@min:hello@1234@10.20.130.230:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertEquals("ad@min", url.getUsername());
+ assertEquals("hello@1234", url.getPassword());
+ assertEquals("10.20.130.230", url.getHost());
+ assertEquals("10.20.130.230:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+ }
+
+
+ @Test
+ public void testIpV6Address() {
+ // Test username or password contains "@"
+ URL url = URL.valueOf("ad@min111:haha@1234@2001:0db8:85a3:08d3:1319:8a2e:0370:7344:20880/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertEquals("ad@min111", url.getUsername());
+ assertEquals("haha@1234", url.getPassword());
+ assertEquals("2001:0db8:85a3:08d3:1319:8a2e:0370:7344", url.getHost());
+ assertEquals("2001:0db8:85a3:08d3:1319:8a2e:0370:7344:20880", url.getAddress());
+ assertEquals(20880, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+ }
+
+ @Test
+ public void testIpV6AddressWithScopeId() {
+ URL url = URL.valueOf("2001:0db8:85a3:08d3:1319:8a2e:0370:7344%5/context/path?version=1.0.0&application=morgan");
+ assertURLStrDecoder(url);
+ assertNull(url.getProtocol());
+ assertEquals("2001:0db8:85a3:08d3:1319:8a2e:0370:7344%5", url.getHost());
+ assertEquals("2001:0db8:85a3:08d3:1319:8a2e:0370:7344%5", url.getAddress());
+ assertEquals(0, url.getPort());
+ assertEquals("context/path", url.getPath());
+ assertEquals(2, url.getParameters().size());
+ assertEquals("1.0.0", url.getParameter("version"));
+ assertEquals("morgan", url.getParameter("application"));
+ }
+
+ @Test
+ public void testDefaultPort() {
+ Assertions.assertEquals("10.20.153.10:2181", URL.appendDefaultPort("10.20.153.10:0", 2181));
+ Assertions.assertEquals("10.20.153.10:2181", URL.appendDefaultPort("10.20.153.10", 2181));
+ }
+
+ @Test
+ public void testGetServiceKey() {
+ URL url1 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName");
+ assertURLStrDecoder(url1);
+ Assertions.assertEquals("org.apache.dubbo.test.interfaceName", url1.getServiceKey());
+
+ URL url2 = URL.valueOf("10.20.130.230:20880/org.apache.dubbo.test.interfaceName?interface=org.apache.dubbo.test.interfaceName");
+ assertURLStrDecoder(url2);
+ Assertions.assertEquals("org.apache.dubbo.test.interfaceName", url2.getServiceKey());
+
+ URL url3 = URL.valueOf("10.20.130.230:20880/org.apache.dubbo.test.interfaceName?interface=org.apache.dubbo.test.interfaceName&group=group1&version=1.0.0");
+ assertURLStrDecoder(url3);
+ Assertions.assertEquals("group1/org.apache.dubbo.test.interfaceName:1.0.0", url3.getServiceKey());
+
+ URL url4 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName");
+ assertURLStrDecoder(url4);
+ Assertions.assertEquals("context/path", url4.getPathKey());
+
+ URL url5 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&group=group1&version=1.0.0");
+ assertURLStrDecoder(url5);
+ Assertions.assertEquals("group1/context/path:1.0.0", url5.getPathKey());
+ }
+
+ @Test
+ public void testGetColonSeparatedKey() {
+ URL url1 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&group=group&version=1.0.0");
+ assertURLStrDecoder(url1);
+ Assertions.assertEquals("org.apache.dubbo.test.interfaceName:1.0.0:group", url1.getColonSeparatedKey());
+
+ URL url2 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&version=1.0.0");
+ assertURLStrDecoder(url2);
+ Assertions.assertEquals("org.apache.dubbo.test.interfaceName:1.0.0:", url2.getColonSeparatedKey());
+
+ URL url3 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&group=group");
+ assertURLStrDecoder(url3);
+ Assertions.assertEquals("org.apache.dubbo.test.interfaceName::group", url3.getColonSeparatedKey());
+
+ URL url4 = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName");
+ assertURLStrDecoder(url4);
+ Assertions.assertEquals("org.apache.dubbo.test.interfaceName::", url4.getColonSeparatedKey());
+
+ URL url5 = URL.valueOf("10.20.130.230:20880/org.apache.dubbo.test.interfaceName");
+ assertURLStrDecoder(url5);
+ Assertions.assertEquals("org.apache.dubbo.test.interfaceName::", url5.getColonSeparatedKey());
+
+ URL url6 = URL.valueOf("10.20.130.230:20880/org.apache.dubbo.test.interfaceName?interface=org.apache.dubbo.test.interfaceName1");
+ assertURLStrDecoder(url6);
+ Assertions.assertEquals("org.apache.dubbo.test.interfaceName1::", url6.getColonSeparatedKey());
+ }
+
+ @Test
+ public void testValueOf() {
+ URL url = URL.valueOf("10.20.130.230");
+ assertURLStrDecoder(url);
+
+ url = URL.valueOf("10.20.130.230:20880");
+ assertURLStrDecoder(url);
+
+ url = URL.valueOf("dubbo://10.20.130.230:20880");
+ assertURLStrDecoder(url);
+
+ url = URL.valueOf("dubbo://10.20.130.230:20880/path");
+ assertURLStrDecoder(url);
+ }
+
+
+ /**
+ * Test {@link URL#getParameters(Predicate)} method
+ *
+ * @since 2.7.8
+ */
+ @Test
+ public void testGetParameters() {
+ URL url = URL.valueOf("10.20.130.230:20880/context/path?interface=org.apache.dubbo.test.interfaceName&group=group&version=1.0.0");
+ Map<String, String> parameters = url.getParameters(i -> "version".equals(i));
+ String version = parameters.get("version");
+ assertEquals(1, parameters.size());
+ assertEquals("1.0.0", version);
+ }
+
+ @Test
+ public void testGetParameter() {
+ URL url = URL.valueOf("http://127.0.0.1:8080/path?i=1&b=false");
+ assertEquals(Integer.valueOf(1), url.getParameter("i", Integer.class));
+ assertEquals(Boolean.FALSE, url.getParameter("b", Boolean.class));
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationTest.java
index 4f2f700..7605a3c 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/AbstractDynamicConfigurationTest.java
@@ -28,15 +28,17 @@ import java.util.concurrent.TimeUnit;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.DEFAULT_THREAD_POOL_KEEP_ALIVE_TIME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.DEFAULT_THREAD_POOL_PREFIX;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.DEFAULT_THREAD_POOL_SIZE;
+import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.GROUP_PARAM_NAME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.PARAM_NAME_PREFIX;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.THREAD_POOL_KEEP_ALIVE_TIME_PARAM_NAME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.THREAD_POOL_PREFIX_PARAM_NAME;
import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.THREAD_POOL_SIZE_PARAM_NAME;
+import static org.apache.dubbo.common.config.configcenter.AbstractDynamicConfiguration.TIMEOUT_PARAM_NAME;
+import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_GROUP;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* {@link AbstractDynamicConfiguration} Test
@@ -49,7 +51,7 @@ public class AbstractDynamicConfigurationTest {
@BeforeEach
public void init() {
- configuration = new AbstractDynamicConfiguration() {
+ configuration = new AbstractDynamicConfiguration(null) {
@Override
protected String doGetConfig(String key, String group) throws Exception {
return null;
@@ -59,6 +61,11 @@ public class AbstractDynamicConfigurationTest {
protected void doClose() throws Exception {
}
+
+ @Override
+ protected boolean doRemoveConfig(String key, String group) throws Exception {
+ return false;
+ }
};
}
@@ -71,6 +78,10 @@ public class AbstractDynamicConfigurationTest {
assertEquals("dubbo.config-center.thread-pool.keep-alive-time", THREAD_POOL_KEEP_ALIVE_TIME_PARAM_NAME);
assertEquals(1, DEFAULT_THREAD_POOL_SIZE);
assertEquals(60 * 1000, DEFAULT_THREAD_POOL_KEEP_ALIVE_TIME);
+
+ // @since 2.7.8
+ assertEquals("dubbo.config-center.group", GROUP_PARAM_NAME);
+ assertEquals("dubbo.config-center.timeout", TIMEOUT_PARAM_NAME);
}
@Test
@@ -91,6 +102,11 @@ public class AbstractDynamicConfigurationTest {
protected void doClose() throws Exception {
}
+
+ @Override
+ protected boolean doRemoveConfig(String key, String group) throws Exception {
+ return false;
+ }
};
ThreadPoolExecutor threadPoolExecutor = configuration.getWorkersThreadPool();
@@ -149,4 +165,42 @@ public class AbstractDynamicConfigurationTest {
public void testClose() throws Exception {
configuration.close();
}
+
+ /**
+ * Test {@link AbstractDynamicConfiguration#getGroup()} and
+ * {@link AbstractDynamicConfiguration#getDefaultGroup()} methods
+ *
+ * @since 2.7.8
+ */
+ @Test
+ public void testGetGroupAndGetDefaultGroup() {
+ assertEquals(configuration.getGroup(), configuration.getDefaultGroup());
+ assertEquals(DEFAULT_GROUP, configuration.getDefaultGroup());
+ }
+
+ /**
+ * Test {@link AbstractDynamicConfiguration#getTimeout()} and
+ * {@link AbstractDynamicConfiguration#getDefaultTimeout()} methods
+ *
+ * @since 2.7.8
+ */
+ @Test
+ public void testGetTimeoutAndGetDefaultTimeout() {
+ assertEquals(configuration.getTimeout(), configuration.getDefaultTimeout());
+ assertEquals(-1L, configuration.getDefaultTimeout());
+ }
+
+ /**
+ * Test {@link AbstractDynamicConfiguration#removeConfig(String, String)} and
+ * {@link AbstractDynamicConfiguration#doRemoveConfig(String, String)} methods
+ *
+ * @since 2.7.8
+ */
+ @Test
+ public void testRemoveConfigAndDoRemoveConfig() throws Exception {
+ String key = null;
+ String group = null;
+ assertEquals(configuration.removeConfig(key, group), configuration.doRemoveConfig(key, group));
+ assertFalse(configuration.removeConfig(key, group));
+ }
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java
index 1422ba6..80282c1 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/config/configcenter/file/FileSystemDynamicConfigurationTest.java
@@ -17,6 +17,8 @@
package org.apache.dubbo.common.config.configcenter.file;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.commons.io.FileUtils;
import org.junit.jupiter.api.AfterEach;
@@ -24,15 +26,17 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.File;
+import java.util.TreeSet;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.atomic.AtomicBoolean;
+import static java.util.Arrays.asList;
import static org.apache.commons.io.FileUtils.deleteQuietly;
import static org.apache.dubbo.common.URL.valueOf;
import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.DEFAULT_GROUP;
import static org.apache.dubbo.common.config.configcenter.file.FileSystemDynamicConfiguration.CONFIG_CENTER_DIR_PARAM_NAME;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -41,6 +45,8 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
*/
public class FileSystemDynamicConfigurationTest {
+ private final Logger logger = LoggerFactory.getLogger(getClass());
+
private FileSystemDynamicConfiguration configuration;
private static final String KEY = "abc-def-ghi";
@@ -53,11 +59,11 @@ public class FileSystemDynamicConfigurationTest {
rootDirectory.mkdirs();
URL url = valueOf("dubbo://127.0.0.1:20880").addParameter(CONFIG_CENTER_DIR_PARAM_NAME, rootDirectory.getAbsolutePath());
configuration = new FileSystemDynamicConfiguration(url);
- deleteQuietly(configuration.getRootDirectory());
}
@AfterEach
public void destroy() throws Exception {
+ deleteQuietly(configuration.getRootDirectory());
configuration.close();
}
@@ -73,9 +79,6 @@ public class FileSystemDynamicConfigurationTest {
assertEquals(ThreadPoolExecutor.class, configuration.getWorkersThreadPool().getClass());
assertEquals(1, (configuration.getWorkersThreadPool()).getCorePoolSize());
assertEquals(1, (configuration.getWorkersThreadPool()).getMaximumPoolSize());
- assertNotNull(configuration.getWatchEventsLoopThreadPool());
- assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getCorePoolSize());
- assertEquals(1, (configuration.getWatchEventsLoopThreadPool()).getMaximumPoolSize());
if (configuration.isBasedPoolingWatchService()) {
assertEquals(2, configuration.getDelay());
@@ -103,7 +106,7 @@ public class FileSystemDynamicConfigurationTest {
processedEvent.set(true);
assertEquals(KEY, event.getKey());
- System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
+ logger.info(String.format("[%s] " + event + "\n", Thread.currentThread().getName()));
});
@@ -127,7 +130,7 @@ public class FileSystemDynamicConfigurationTest {
configuration.addListener("test", "test", event -> {
processedEvent.set(true);
assertEquals("test", event.getKey());
- System.out.printf("[%s] " + event + "\n", Thread.currentThread().getName());
+ logger.info(String.format("[%s] " + event + "\n", Thread.currentThread().getName()));
});
processedEvent.set(false);
configuration.publishConfig("test", "test", "TEST");
@@ -141,10 +144,36 @@ public class FileSystemDynamicConfigurationTest {
processedEvent.set(false);
- File keyFile = configuration.configFile(KEY, DEFAULT_GROUP);
+ configuration.getRootDirectory();
+ File keyFile = new File(KEY, DEFAULT_GROUP);
FileUtils.deleteQuietly(keyFile);
while (!processedEvent.get()) {
Thread.sleep(1 * 1000L);
}
}
+
+ @Test
+ public void testRemoveConfig() throws Exception {
+
+ assertTrue(configuration.publishConfig(KEY, DEFAULT_GROUP, "A"));
+
+ assertEquals("A", FileUtils.readFileToString(configuration.configFile(KEY, DEFAULT_GROUP), configuration.getEncoding()));
+
+ assertTrue(configuration.removeConfig(KEY, DEFAULT_GROUP));
+
+ assertFalse(configuration.configFile(KEY, DEFAULT_GROUP).exists());
+
+ }
+
+ @Test
+ public void testGetConfigKeys() throws Exception {
+
+ assertTrue(configuration.publishConfig("A", DEFAULT_GROUP, "A"));
+
+ assertTrue(configuration.publishConfig("B", DEFAULT_GROUP, "B"));
+
+ assertTrue(configuration.publishConfig("C", DEFAULT_GROUP, "C"));
+
+ assertEquals(new TreeSet(asList("A", "B", "C")), configuration.getConfigKeys(DEFAULT_GROUP));
+ }
}
diff --git a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/URLRevisionResolverTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/constants/CommonConstantsTest.java
similarity index 50%
copy from dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/URLRevisionResolverTest.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/constants/CommonConstantsTest.java
index 3386bba..bc85dfb 100644
--- a/dubbo-registry/dubbo-registry-api/src/test/java/org/apache/dubbo/registry/client/metadata/URLRevisionResolverTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/constants/CommonConstantsTest.java
@@ -14,34 +14,28 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry.client.metadata;
+package org.apache.dubbo.common.constants;
import org.junit.jupiter.api.Test;
-import static java.util.Arrays.asList;
-import static org.apache.dubbo.registry.client.metadata.URLRevisionResolver.NO_REVISION;
+import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR_CHAR;
+import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH;
+import static org.apache.dubbo.common.constants.CommonConstants.SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
- * {@link URLRevisionResolver} Test
+ * {@link CommonConstants} Test-Cases
*
- * @since 2.7.5
+ * @since 2.7.8
*/
-public class URLRevisionResolverTest {
-
- private static final String URL = "dubbo://192.168.0.102:20881/org.apache.dubbo.registry.client.metadata.URLRevisionResolverTest";
-
- private final URLRevisionResolver resolver = new URLRevisionResolver();
+public class CommonConstantsTest {
@Test
- public void testResolve() {
- String revision = resolver.resolve(asList());
- assertEquals(NO_REVISION, revision);
-
- revision = resolver.resolve(null);
- assertEquals(NO_REVISION, revision);
-
- revision = resolver.resolve(asList(URL));
- assertEquals("7960327984321481979", revision);
+ public void test() {
+ assertEquals(',', COMMA_SEPARATOR_CHAR);
+ assertEquals("composite", COMPOSITE_METADATA_STORAGE_TYPE);
+ assertEquals("service-name-mapping.properties-path", SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY);
+ assertEquals("META-INF/dubbo/service-name-mapping.properties", DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH);
}
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/ConverterTest.java
similarity index 53%
copy from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/convert/ConverterTest.java
index 242ae60..1f5a36c 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/ConverterTest.java
@@ -14,42 +14,36 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
+package org.apache.dubbo.common.convert;
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToOptionalConverter;
-
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import java.util.Optional;
-
+import static org.apache.dubbo.common.convert.Converter.convertIfPossible;
+import static org.apache.dubbo.common.convert.Converter.getConverter;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertSame;
/**
- * {@link StringToOptionalConverter} Test
+ * {@link Converter} Test-Cases
*
- * @since 2.7.6
+ * @since 2.7.8
*/
-public class StringToOptionalConverterTest {
-
- private StringToOptionalConverter converter;
-
- @BeforeEach
- public void init() {
- converter = (StringToOptionalConverter) getExtensionLoader(Converter.class).getExtension("string-to-optional");
- }
+public class ConverterTest {
@Test
- public void testAccept() {
- assertTrue(converter.accept(String.class, Optional.class));
+ public void testGetConverter() {
+ getExtensionLoader(Converter.class)
+ .getSupportedExtensionInstances()
+ .forEach(converter -> {
+ assertSame(converter, getConverter(converter.getSourceType(), converter.getTargetType()));
+ });
}
@Test
- public void testConvert() {
- assertEquals(Optional.of("1"), converter.convert("1"));
- assertEquals(Optional.empty(), converter.convert(null));
+ public void testConvertIfPossible() {
+ assertEquals(Integer.valueOf(2), convertIfPossible("2", Integer.class));
+ assertEquals(Boolean.FALSE, convertIfPossible("false", Boolean.class));
+ assertEquals(Double.valueOf(1), convertIfPossible("1", Double.class));
}
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToBooleanConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToBooleanConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToBooleanConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToBooleanConverterTest.java
index 3b1d75b..e955fa9 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToBooleanConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToBooleanConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToBooleanConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharArrayConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToCharArrayConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharArrayConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToCharArrayConverterTest.java
index 492a129..bc3a606 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharArrayConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToCharArrayConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToCharArrayConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharacterConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToCharacterConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharacterConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToCharacterConverterTest.java
index c9e88c2..87f3367 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToCharacterConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToCharacterConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToCharacterConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToDoubleConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToDoubleConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToDoubleConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToDoubleConverterTest.java
index 668f3e6..2c74736 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToDoubleConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToDoubleConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToDoubleConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToFloatConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToFloatConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToFloatConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToFloatConverterTest.java
index aa17499..b4b36f3 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToFloatConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToFloatConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToFloatConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToIntegerConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToIntegerConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToIntegerConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToIntegerConverterTest.java
index 9c7d24b..1ccebfd 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToIntegerConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToIntegerConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToIntegerConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToLongConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToLongConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToLongConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToLongConverterTest.java
index e14424a..c7cd926 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToLongConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToLongConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToLongConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToOptionalConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToOptionalConverterTest.java
index 242ae60..9cb79e2 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToOptionalConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToOptionalConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToOptionalConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToShortConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToShortConverterTest.java
similarity index 92%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToShortConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToShortConverterTest.java
index 3f1d493..9ecdc20 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToShortConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToShortConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToShortConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToStringConverterTest.java
similarity index 92%
copy from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToStringConverterTest.java
index 57806c3..517585d 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/StringToStringConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
-
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToStringConverter;
+package org.apache.dubbo.common.convert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/MultiValueConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/MultiValueConverterTest.java
new file mode 100644
index 0000000..ea64628
--- /dev/null
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/MultiValueConverterTest.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.common.convert.multiple;
+
+import org.junit.jupiter.api.Test;
+
+import java.util.Collection;
+import java.util.Deque;
+import java.util.List;
+import java.util.NavigableSet;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.TransferQueue;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * {@link MultiValueConverter} Test
+ *
+ * @since 2.7.8
+ */
+public class MultiValueConverterTest {
+
+ @Test
+ public void testFind() {
+ MultiValueConverter converter = MultiValueConverter.find(String.class, String[].class);
+ assertEquals(StringToArrayConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, BlockingDeque.class);
+ assertEquals(StringToBlockingDequeConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, BlockingQueue.class);
+ assertEquals(StringToBlockingQueueConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, Collection.class);
+ assertEquals(StringToCollectionConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, Deque.class);
+ assertEquals(StringToDequeConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, List.class);
+ assertEquals(StringToListConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, NavigableSet.class);
+ assertEquals(StringToNavigableSetConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, Queue.class);
+ assertEquals(StringToQueueConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, Set.class);
+ assertEquals(StringToSetConverter.class, converter.getClass());
+
+ converter = MultiValueConverter.find(String.class, TransferQueue.class);
+ assertEquals(StringToTransferQueueConverter.class, converter.getClass());
+ }
+}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToArrayConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToArrayConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToArrayConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToArrayConverterTest.java
index 1781356..8279e07 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToArrayConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToArrayConverterTest.java
@@ -14,9 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
-
-import org.apache.dubbo.common.convert.multiple.StringToArrayConverter;
+package org.apache.dubbo.common.convert.multiple;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingDequeConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToBlockingDequeConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingDequeConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToBlockingDequeConverterTest.java
index 6f9597d..f0975ad 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingDequeConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToBlockingDequeConverterTest.java
@@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
-import org.apache.dubbo.common.convert.multiple.StringToBlockingDequeConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingQueueConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToBlockingQueueConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingQueueConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToBlockingQueueConverterTest.java
index 4fa7532..f1d8cb8 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToBlockingQueueConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToBlockingQueueConverterTest.java
@@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
-import org.apache.dubbo.common.convert.multiple.StringToBlockingQueueConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToCollectionConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToCollectionConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToCollectionConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToCollectionConverterTest.java
index f0b06ec..564ece3 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToCollectionConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToCollectionConverterTest.java
@@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
-
-import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
-import org.apache.dubbo.common.convert.multiple.StringToCollectionConverter;
+package org.apache.dubbo.common.convert.multiple;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToDequeConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToDequeConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToDequeConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToDequeConverterTest.java
index e810092..3d4b785 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToDequeConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToDequeConverterTest.java
@@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
-import org.apache.dubbo.common.convert.multiple.StringToDequeConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToListConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToListConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToListConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToListConverterTest.java
index af9ee91..4258199 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToListConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToListConverterTest.java
@@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
-import org.apache.dubbo.common.convert.multiple.StringToListConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToNavigableSetConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToNavigableSetConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToNavigableSetConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToNavigableSetConverterTest.java
index face60d..e7e1660 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToNavigableSetConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToNavigableSetConverterTest.java
@@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
-import org.apache.dubbo.common.convert.multiple.StringToListConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
@@ -47,7 +45,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
- * {@link StringToListConverter} Test
+ * {@link StringToNavigableSetConverter} Test
*
* @since 2.7.6
*/
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToQueueConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToQueueConverterTest.java
similarity index 97%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToQueueConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToQueueConverterTest.java
index 539693a..2933d04 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToQueueConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToQueueConverterTest.java
@@ -14,9 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.StringToQueueConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSetConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToSetConverterTest.java
similarity index 97%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSetConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToSetConverterTest.java
index 269d709..5925cec 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSetConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToSetConverterTest.java
@@ -14,9 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.StringToSetConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSortedSetConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToSortedSetConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSortedSetConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToSortedSetConverterTest.java
index 6af8f9d..2ed1252 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToSortedSetConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToSortedSetConverterTest.java
@@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
-import org.apache.dubbo.common.convert.multiple.StringToListConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
@@ -47,7 +45,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
- * {@link StringToListConverter} Test
+ * {@link StringToSortedSetConverter} Test
*
* @since 2.7.6
*/
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToTransferQueueConverterTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToTransferQueueConverterTest.java
similarity index 95%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToTransferQueueConverterTest.java
rename to dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToTransferQueueConverterTest.java
index 4d8d66b..e4cc101 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/multiple/StringToTransferQueueConverterTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/convert/multiple/StringToTransferQueueConverterTest.java
@@ -14,10 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert.multiple;
+package org.apache.dubbo.common.convert.multiple;
-import org.apache.dubbo.common.convert.multiple.MultiValueConverter;
-import org.apache.dubbo.common.convert.multiple.StringToListConverter;
import org.apache.dubbo.common.utils.CollectionUtils;
import org.junit.jupiter.api.BeforeEach;
@@ -48,7 +46,7 @@ import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
- * {@link StringToListConverter} Test
+ * {@link StringToTransferQueueConverter} Test
*
* @since 2.7.6
*/
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
index 0144059..24cb292 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/PojoUtilsTest.java
@@ -16,7 +16,6 @@
*/
package org.apache.dubbo.common.utils;
-import com.alibaba.fastjson.JSONObject;
import org.apache.dubbo.common.model.Person;
import org.apache.dubbo.common.model.SerializablePerson;
import org.apache.dubbo.common.model.User;
@@ -26,6 +25,7 @@ import org.apache.dubbo.common.model.person.PersonInfo;
import org.apache.dubbo.common.model.person.PersonStatus;
import org.apache.dubbo.common.model.person.Phone;
+import com.alibaba.fastjson.JSONObject;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --git a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringConstantFieldValuePredicateTest.java
similarity index 51%
copy from dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
copy to dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringConstantFieldValuePredicateTest.java
index 0ffed8d..0618542 100644
--- a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringConstantFieldValuePredicateTest.java
@@ -14,27 +14,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.metadata.store.zookeeper;
+package org.apache.dubbo.common.utils;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.report.MetadataReport;
-import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
-import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
+import org.junit.jupiter.api.Test;
+
+import java.util.function.Predicate;
+
+import static org.apache.dubbo.common.utils.StringConstantFieldValuePredicate.of;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
/**
- * ZookeeperRegistryFactory.
+ * {@link StringConstantFieldValuePredicate} Test
+ *
+ * @since 2.7.8
*/
-public class ZookeeperMetadataReportFactory extends AbstractMetadataReportFactory {
+public class StringConstantFieldValuePredicateTest {
- private ZookeeperTransporter zookeeperTransporter;
+ public static final String S1 = "1";
- public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
- this.zookeeperTransporter = zookeeperTransporter;
- }
+ public static final Object O1 = "2";
- @Override
- public MetadataReport createMetadataReport(URL url) {
- return new ZookeeperMetadataReport(url, zookeeperTransporter);
- }
+ public static final Object O2 = 3;
+ @Test
+ public void test() {
+ Predicate<String> predicate = of(getClass());
+ assertTrue(predicate.test("1"));
+ assertTrue(predicate.test("2"));
+ assertFalse(predicate.test("3"));
+ }
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java
index 736e9d8..0d38e6c 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/common/utils/StringUtilsTest.java
@@ -18,19 +18,33 @@ package org.apache.dubbo.common.utils;
import org.junit.jupiter.api.Test;
-import java.util.*;
-
+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.Set;
+
+import static java.util.Arrays.asList;
import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.INTERFACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
+import static org.apache.dubbo.common.utils.StringUtils.splitToList;
+import static org.apache.dubbo.common.utils.StringUtils.splitToSet;
+import static org.apache.dubbo.common.utils.StringUtils.toCommaDelimitedString;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.isEmptyOrNullString;
import static org.hamcrest.Matchers.nullValue;
-import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class StringUtilsTest {
@Test
@@ -234,16 +248,32 @@ public class StringUtilsTest {
public void testSplitToList() throws Exception {
String str = "d,1,2,4";
- assertEquals(4, StringUtils.splitToList(str, ',').size());
- assertEquals(Arrays.asList(str.split(",")), StringUtils.splitToList(str, ','));
+ assertEquals(4, splitToList(str, ',').size());
+ assertEquals(asList(str.split(",")), splitToList(str, ','));
- assertEquals(1, StringUtils.splitToList(str, 'a').size());
- assertEquals(Arrays.asList(str.split("a")), StringUtils.splitToList(str, 'a'));
+ assertEquals(1, splitToList(str, 'a').size());
+ assertEquals(asList(str.split("a")), splitToList(str, 'a'));
- assertEquals(0, StringUtils.splitToList("", 'a').size());
- assertEquals(0, StringUtils.splitToList(null, 'a').size());
+ assertEquals(0, splitToList("", 'a').size());
+ assertEquals(0, splitToList(null, 'a').size());
}
+ /**
+ * Test {@link StringUtils#splitToSet(String, char, boolean)}
+ *
+ * @since 2.7.8
+ */
+ @Test
+ public void testSplitToSet() {
+ String value = "1# 2#3 #4#3";
+ Set<String> values = splitToSet(value, '#', false);
+ assertEquals(ofSet("1", " 2", "3 ", "4", "3"), values);
+
+ values = splitToSet(value, '#', true);
+ assertEquals(ofSet("1", "2", "3", "4"), values);
+ }
+
+
@Test
public void testTranslate() throws Exception {
String s = "16314";
@@ -363,4 +393,29 @@ public class StringUtilsTest {
assertEquals(0, illegalMap.size());
}
+ /**
+ * Test {@link StringUtils#toCommaDelimitedString(String, String...)}
+ * @since 2.7.8
+ */
+ @Test
+ public void testToCommaDelimitedString() {
+ String value = toCommaDelimitedString(null);
+ assertNull(value);
+
+ value = toCommaDelimitedString(null, null);
+ assertNull(value);
+
+ value = toCommaDelimitedString("");
+ assertEquals("", value);
+
+ value = toCommaDelimitedString("one");
+ assertEquals("one", value);
+
+ value = toCommaDelimitedString("one", "two");
+ assertEquals("one,two", value);
+
+ value = toCommaDelimitedString("one", "two", "three");
+ assertEquals("one,two,three", value);
+ }
+
}
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java b/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
index 58fc3cc..24c4f00 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/config/context/ConfigManagerTest.java
@@ -49,7 +49,12 @@ public class ConfigManagerTest {
@BeforeEach
public void init() {
- configManager.clear();
+ configManager.destroy();
+ }
+
+ @Test
+ public void testDestroy() {
+ assertTrue(configManager.configsCache.isEmpty());
}
@Test
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/event/EchoEventListener2.java b/dubbo-common/src/test/java/org/apache/dubbo/event/EchoEventListener2.java
index 18e7cf9..0d27802 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/event/EchoEventListener2.java
+++ b/dubbo-common/src/test/java/org/apache/dubbo/event/EchoEventListener2.java
@@ -41,7 +41,7 @@ public class EchoEventListener2 extends Vector<EventListener<Event>> implements
@Override
public int getPriority() {
- return 0;
+ return -1;
}
public int getEventOccurs() {
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ConfigTest.java
index 95608d7..9ce2191 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ConfigTest.java
+++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ConfigTest.java
@@ -35,14 +35,14 @@ public class ConfigTest {
@AfterEach
public void tearDown() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@BeforeEach
public void setup() {
// In IDE env, make sure adding the following argument to VM options
System.setProperty("java.net.preferIPv4Stack", "true");
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@Test
diff --git a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
index d30f632..883dc12 100644
--- a/dubbo-compatible/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
+++ b/dubbo-compatible/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
@@ -38,12 +38,12 @@ public class ReferenceConfigTest {
@BeforeEach
public void setUp() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@AfterEach
public void tearDown() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@Test
diff --git a/dubbo-config/dubbo-config-api/pom.xml b/dubbo-config/dubbo-config-api/pom.xml
index 89580bd..4ccfd67 100644
--- a/dubbo-config/dubbo-config-api/pom.xml
+++ b/dubbo-config/dubbo-config-api/pom.xml
@@ -135,6 +135,12 @@
<artifactId>dubbo-registry-eureka</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
@@ -156,6 +162,12 @@
<artifactId>dubbo-metadata-report-zookeeper</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
@@ -170,6 +182,19 @@
<artifactId>dubbo-metadata-report-nacos</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metadata-report-consul</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
@@ -191,6 +216,12 @@
<artifactId>dubbo-configcenter-nacos</artifactId>
<version>${project.parent.version}</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index df9eed2..570f7a4 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.config;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.Version;
import org.apache.dubbo.common.bytecode.Wrapper;
+import org.apache.dubbo.common.constants.RegistryConstants;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@@ -31,10 +32,10 @@ import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.bootstrap.DubboBootstrap;
import org.apache.dubbo.config.event.ReferenceConfigDestroyedEvent;
import org.apache.dubbo.config.event.ReferenceConfigInitializedEvent;
+import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.event.Event;
import org.apache.dubbo.event.EventDispatcher;
-import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
import org.apache.dubbo.rpc.ProxyFactory;
@@ -57,25 +58,25 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
import static org.apache.dubbo.common.constants.CommonConstants.CLUSTER_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
+import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR_CHAR;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
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.METADATA_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PROXY_CLASS_REF;
-import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SEMICOLON_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.SUBSCRIBED_SERVICE_NAMES_KEY;
import static org.apache.dubbo.common.utils.NetUtils.isInvalidLocalHost;
+import static org.apache.dubbo.common.utils.StringUtils.splitToSet;
import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
-import static org.apache.dubbo.registry.Constants.CONSUMER_PROTOCOL;
import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
@@ -140,6 +141,13 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
private DubboBootstrap bootstrap;
+ /**
+ * The service names that the Dubbo interface subscribed.
+ *
+ * @since 2.7.8
+ */
+ private String services;
+
public ReferenceConfig() {
super();
this.repository = ApplicationModel.getServiceRepository();
@@ -150,6 +158,40 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
this.repository = ApplicationModel.getServiceRepository();
}
+ /**
+ * Get a string presenting the service names that the Dubbo interface subscribed.
+ * If it is a multiple-values, the content will be a comma-delimited String.
+ *
+ * @return non-null
+ * @see RegistryConstants#SUBSCRIBED_SERVICE_NAMES_KEY
+ * @since 2.7.8
+ */
+ @Parameter(key = SUBSCRIBED_SERVICE_NAMES_KEY)
+ public String getServices() {
+ return services;
+ }
+
+ /**
+ * It's an alias method for {@link #getServices()}, but the more convenient.
+ *
+ * @return the String {@link List} presenting the Dubbo interface subscribed
+ * @since 2.7.8
+ */
+ @Parameter(excluded = true)
+ public Set<String> getSubscribedServices() {
+ return splitToSet(getServices(), COMMA_SEPARATOR_CHAR);
+ }
+
+ /**
+ * Set the service names that the Dubbo interface subscribed.
+ *
+ * @param services If it is a multiple-values, the content will be a comma-delimited String.
+ * @since 2.7.8
+ */
+ public void setServices(String services) {
+ this.services = services;
+ }
+
public synchronized T get() {
if (destroyed) {
throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
@@ -221,10 +263,6 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
// appendParameters(map, consumer, Constants.DEFAULT_KEY);
AbstractConfig.appendParameters(map, consumer);
AbstractConfig.appendParameters(map, this);
- MetadataReportConfig metadataReportConfig = getMetadataReportConfig();
- if (metadataReportConfig != null && metadataReportConfig.isValid()) {
- map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE);
- }
Map<String, AsyncMethodInfo> attributes = null;
if (CollectionUtils.isNotEmpty(getMethods())) {
attributes = new HashMap<>();
@@ -355,16 +393,6 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
if (logger.isInfoEnabled()) {
logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
}
- /**
- * @since 2.7.0
- * ServiceData Store
- */
- String metadata = map.get(METADATA_KEY);
- WritableMetadataService metadataService = WritableMetadataService.getExtension(metadata == null ? DEFAULT_METADATA_STORAGE_TYPE : metadata);
- if (metadataService != null) {
- URL consumerURL = new URL(CONSUMER_PROTOCOL, map.remove(REGISTER_IP_KEY), 0, map.get(INTERFACE_KEY), map);
- metadataService.publishServiceDefinition(consumerURL);
- }
// create service proxy
return (T) PROXY_FACTORY.getProxy(invoker, ProtocolUtils.isGeneric(generic));
}
@@ -469,7 +497,7 @@ public class ReferenceConfig<T> extends ReferenceConfigBase<T> {
}
private void postProcessConfig() {
- List<ConfigPostProcessor> configPostProcessors =ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class)
+ List<ConfigPostProcessor> configPostProcessors = ExtensionLoader.getExtensionLoader(ConfigPostProcessor.class)
.getActivateExtension(URL.valueOf("configPostProcessor://"), (String[]) null);
configPostProcessors.forEach(component -> component.postProcessReferConfig(this));
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index 3ad4545..5173bf7 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
@@ -37,7 +37,6 @@ import org.apache.dubbo.config.support.Parameter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.event.Event;
import org.apache.dubbo.event.EventDispatcher;
-import org.apache.dubbo.metadata.WritableMetadataService;
import org.apache.dubbo.rpc.Exporter;
import org.apache.dubbo.rpc.Invoker;
import org.apache.dubbo.rpc.Protocol;
@@ -68,16 +67,13 @@ import java.util.concurrent.TimeUnit;
import static org.apache.dubbo.common.constants.CommonConstants.ANYHOST_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
-import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO_IP_TO_BIND;
import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
-import static org.apache.dubbo.common.constants.CommonConstants.METADATA_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTER_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REVISION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY;
@@ -187,7 +183,7 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
if (bootstrap == null) {
bootstrap = DubboBootstrap.getInstance();
- bootstrap.init();
+ bootstrap.initialize();
}
checkAndUpdateSubConfigs();
@@ -344,10 +340,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
AbstractConfig.appendParameters(map, provider);
AbstractConfig.appendParameters(map, protocolConfig);
AbstractConfig.appendParameters(map, this);
- MetadataReportConfig metadataReportConfig = getMetadataReportConfig();
- if (metadataReportConfig != null && metadataReportConfig.isValid()) {
- map.putIfAbsent(METADATA_KEY, REMOTE_METADATA_STORAGE_TYPE);
- }
if (CollectionUtils.isNotEmpty(getMethods())) {
for (MethodConfig method : getMethods()) {
AbstractConfig.appendParameters(map, method, method.getName());
@@ -502,14 +494,6 @@ public class ServiceConfig<T> extends ServiceConfigBase<T> {
Exporter<?> exporter = PROTOCOL.export(wrapperInvoker);
exporters.add(exporter);
}
- /**
- * @since 2.7.0
- * ServiceData Store
- */
- WritableMetadataService metadataService = WritableMetadataService.getExtension(url.getParameter(METADATA_KEY, DEFAULT_METADATA_STORAGE_TYPE));
- if (metadataService != null) {
- metadataService.publishServiceDefinition(url);
- }
}
}
this.urls.add(url);
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
index cd92fe5..10dd4f2 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/DubboBootstrap.java
@@ -52,7 +52,6 @@ import org.apache.dubbo.config.bootstrap.builders.ReferenceBuilder;
import org.apache.dubbo.config.bootstrap.builders.RegistryBuilder;
import org.apache.dubbo.config.bootstrap.builders.ServiceBuilder;
import org.apache.dubbo.config.context.ConfigManager;
-import org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter;
import org.apache.dubbo.config.utils.ConfigValidationUtils;
import org.apache.dubbo.config.utils.ReferenceConfigCache;
import org.apache.dubbo.event.EventDispatcher;
@@ -66,6 +65,7 @@ import org.apache.dubbo.registry.client.DefaultServiceInstance;
import org.apache.dubbo.registry.client.ServiceDiscovery;
import org.apache.dubbo.registry.client.ServiceDiscoveryRegistry;
import org.apache.dubbo.registry.client.ServiceInstance;
+import org.apache.dubbo.registry.client.ServiceInstanceCustomizer;
import org.apache.dubbo.registry.support.AbstractRegistryFactory;
import org.apache.dubbo.rpc.model.ApplicationModel;
@@ -93,17 +93,17 @@ import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.g
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.REGISTRY_SPLIT_PATTERN;
import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
import static org.apache.dubbo.common.function.ThrowableAction.execute;
import static org.apache.dubbo.common.utils.StringUtils.isNotEmpty;
-import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
import static org.apache.dubbo.registry.client.metadata.ServiceInstanceMetadataUtils.setMetadataStorageType;
import static org.apache.dubbo.remoting.Constants.CLIENT_KEY;
/**
* See {@link ApplicationModel} and {@link ExtensionLoader} for why this class is designed to be singleton.
- *
+ * <p>
* The bootstrap class of Dubbo
- *
+ * <p>
* Get singleton instance by calling static method {@link #getInstance()}.
* Designed as singleton because some classes inside Dubbo, such as ExtensionLoader, are designed only for one instance per process.
*
@@ -141,7 +141,7 @@ public class DubboBootstrap extends GenericEventListener {
private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();
- private final ExecutorRepository executorRepository = ExtensionLoader.getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
+ private final ExecutorRepository executorRepository = getExtensionLoader(ExecutorRepository.class).getDefaultExtension();
private final ConfigManager configManager;
@@ -165,7 +165,7 @@ public class DubboBootstrap extends GenericEventListener {
private volatile MetadataService metadataService;
- private volatile MetadataServiceExporter metadataServiceExporter;
+ private volatile Set<MetadataServiceExporter> metadataServiceExporters;
private List<ServiceConfigBase<?>> exportedServices = new ArrayList<>();
@@ -500,7 +500,7 @@ public class DubboBootstrap extends GenericEventListener {
/**
* Initialize
*/
- private void initialize() {
+ public void initialize() {
if (!initialized.compareAndSet(false, true)) {
return;
}
@@ -509,14 +509,17 @@ public class DubboBootstrap extends GenericEventListener {
startConfigCenter();
- useRegistryAsConfigCenterIfNecessary();
-
loadRemoteConfigs();
checkGlobalConfigs();
+ // @since 2.7.8
+ startMetadataCenter();
+
initMetadataService();
+ initMetadataServiceExports();
+
initEventListener();
if (logger.isInfoEnabled()) {
@@ -583,6 +586,9 @@ public class DubboBootstrap extends GenericEventListener {
}
private void startConfigCenter() {
+
+ useRegistryAsConfigCenterIfNecessary();
+
Collection<ConfigCenterConfig> configCenters = configManager.getConfigCenters();
// check Config Center
@@ -610,7 +616,10 @@ public class DubboBootstrap extends GenericEventListener {
configManager.refreshAll();
}
- private void startMetadataReport() {
+ private void startMetadataCenter() {
+
+ useRegistryAsMetadataCenterIfNecessary();
+
ApplicationConfig applicationConfig = getApplication();
String metadataType = applicationConfig.getMetadataType();
@@ -646,33 +655,87 @@ public class DubboBootstrap extends GenericEventListener {
return;
}
- configManager.getDefaultRegistries().stream()
- .filter(registryConfig -> registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter())
- .forEach(registryConfig -> {
- String protocol = registryConfig.getProtocol();
- String id = "config-center-" + protocol + "-" + registryConfig.getPort();
- ConfigCenterConfig cc = new ConfigCenterConfig();
- cc.setId(id);
- if (cc.getParameters() == null) {
- cc.setParameters(new HashMap<>());
- }
- if (registryConfig.getParameters() != null) {
- cc.getParameters().putAll(registryConfig.getParameters());
- }
- cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
- cc.setProtocol(registryConfig.getProtocol());
- cc.setPort(registryConfig.getPort());
- cc.setAddress(getRegistryCompatibleAddress(registryConfig.getAddress()));
- cc.setNamespace(registryConfig.getGroup());
- cc.setUsername(registryConfig.getUsername());
- cc.setPassword(registryConfig.getPassword());
- if (registryConfig.getTimeout() != null) {
- cc.setTimeout(registryConfig.getTimeout().longValue());
- }
- cc.setHighestPriority(false);
- configManager.addConfigCenter(cc);
- });
- startConfigCenter();
+ configManager
+ .getDefaultRegistries()
+ .stream()
+ .filter(this::isUsedRegistryAsConfigCenter)
+ .map(this::registryAsConfigCenter)
+ .forEach(configManager::addConfigCenter);
+ }
+
+ private boolean isUsedRegistryAsConfigCenter(RegistryConfig registryConfig) {
+ // TODO: confirm ? registryConfig.getUseAsConfigCenter() == null || registryConfig.getUseAsConfigCenter()
+ return Boolean.TRUE.equals(registryConfig.getUseAsConfigCenter());
+ }
+
+ private ConfigCenterConfig registryAsConfigCenter(RegistryConfig registryConfig) {
+ String protocol = registryConfig.getProtocol();
+ Integer port = registryConfig.getPort();
+ String id = "config-center-" + protocol + "-" + port;
+ ConfigCenterConfig cc = new ConfigCenterConfig();
+ cc.setId(id);
+ if (cc.getParameters() == null) {
+ cc.setParameters(new HashMap<>());
+ }
+ if (registryConfig.getParameters() != null) {
+ cc.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
+ }
+ cc.getParameters().put(CLIENT_KEY, registryConfig.getClient());
+ cc.setProtocol(protocol);
+ cc.setPort(port);
+ cc.setGroup(registryConfig.getGroup());
+ cc.setAddress(getRegistryCompatibleAddress(registryConfig.getAddress()));
+ cc.setNamespace(registryConfig.getGroup());
+ cc.setUsername(registryConfig.getUsername());
+ cc.setPassword(registryConfig.getPassword());
+ if (registryConfig.getTimeout() != null) {
+ cc.setTimeout(registryConfig.getTimeout().longValue());
+ }
+ cc.setHighestPriority(false);
+ return cc;
+ }
+
+ private void useRegistryAsMetadataCenterIfNecessary() {
+
+ Collection<MetadataReportConfig> metadataConfigs = configManager.getMetadataConfigs();
+
+ if (CollectionUtils.isNotEmpty(metadataConfigs)) {
+ return;
+ }
+
+ configManager
+ .getDefaultRegistries()
+ .stream()
+ .filter(this::isUsedRegistryAsMetadataCenter)
+ .map(this::registryAsMetadataCenter)
+ .forEach(configManager::addMetadataReport);
+
+ }
+
+ private boolean isUsedRegistryAsMetadataCenter(RegistryConfig registryConfig) {
+ // TODO: confirm ? registryConfig.getUseAsMetadataCenter() == null || registryConfig.getUseAsMetadataCenter()
+ return Boolean.TRUE.equals(registryConfig.getUseAsMetadataCenter());
+ }
+
+ private MetadataReportConfig registryAsMetadataCenter(RegistryConfig registryConfig) {
+ String protocol = registryConfig.getProtocol();
+ Integer port = registryConfig.getPort();
+ String id = "metadata-center-" + protocol + "-" + port;
+ MetadataReportConfig metadataReportConfig = new MetadataReportConfig();
+ metadataReportConfig.setId(id);
+ if (metadataReportConfig.getParameters() == null) {
+ metadataReportConfig.setParameters(new HashMap<>());
+ }
+ if (registryConfig.getParameters() != null) {
+ metadataReportConfig.getParameters().putAll(registryConfig.getParameters()); // copy the parameters
+ }
+ metadataReportConfig.getParameters().put(CLIENT_KEY, registryConfig.getClient());
+ metadataReportConfig.setGroup(registryConfig.getGroup());
+ metadataReportConfig.setAddress(getRegistryCompatibleAddress(registryConfig.getAddress()));
+ metadataReportConfig.setUsername(registryConfig.getUsername());
+ metadataReportConfig.setPassword(registryConfig.getPassword());
+ metadataReportConfig.setTimeout(registryConfig.getTimeout());
+ return metadataReportConfig;
}
private String getRegistryCompatibleAddress(String registryAddress) {
@@ -719,12 +782,17 @@ public class DubboBootstrap extends GenericEventListener {
/**
- * Initialize {@link MetadataService} from {@link WritableMetadataService}'s extension
+ * Initialize {@link #metadataService WritableMetadataService} from {@link WritableMetadataService}'s extension
*/
private void initMetadataService() {
- startMetadataReport();
- this.metadataService = getExtension(getMetadataType());
- this.metadataServiceExporter = new ConfigurableMetadataServiceExporter(metadataService);
+ this.metadataService = WritableMetadataService.getExtension(getMetadataType());
+ }
+
+ /**
+ * Initialize {@link #metadataServiceExporters MetadataServiceExporter}
+ */
+ private void initMetadataServiceExports() {
+ this.metadataServiceExporters = getExtensionLoader(MetadataServiceExporter.class).getSupportedExtensionInstances();
}
/**
@@ -926,13 +994,21 @@ public class DubboBootstrap extends GenericEventListener {
* export {@link MetadataService}
*/
private void exportMetadataService() {
- metadataServiceExporter.export();
+ metadataServiceExporters
+ .stream()
+ .filter(this::supports)
+ .forEach(MetadataServiceExporter::export);
}
private void unexportMetadataService() {
- if (metadataServiceExporter != null && metadataServiceExporter.isExported()) {
- metadataServiceExporter.unexport();
- }
+ metadataServiceExporters
+ .stream()
+ .filter(this::supports)
+ .forEach(MetadataServiceExporter::unexport);
+ }
+
+ private boolean supports(MetadataServiceExporter exporter) {
+ return exporter.supports(getMetadataType());
}
private void exportServices() {
@@ -1025,9 +1101,37 @@ public class DubboBootstrap extends GenericEventListener {
ServiceInstance serviceInstance = createServiceInstance(serviceName, host, port);
+ preRegisterServiceInstance(serviceInstance);
+
getServiceDiscoveries().forEach(serviceDiscovery -> serviceDiscovery.register(serviceInstance));
}
+ /**
+ * Pre-register {@link ServiceInstance the service instance}
+ *
+ * @param serviceInstance {@link ServiceInstance the service instance}
+ * @since 2.7.8
+ */
+ private void preRegisterServiceInstance(ServiceInstance serviceInstance) {
+ customizeServiceInstance(serviceInstance);
+ }
+
+ /**
+ * Customize {@link ServiceInstance the service instance}
+ *
+ * @param serviceInstance {@link ServiceInstance the service instance}
+ * @since 2.7.8
+ */
+ private void customizeServiceInstance(ServiceInstance serviceInstance) {
+ ExtensionLoader<ServiceInstanceCustomizer> loader =
+ getExtensionLoader(ServiceInstanceCustomizer.class);
+ // FIXME, sort customizer before apply
+ loader.getSupportedExtensionInstances().forEach(customizer -> {
+ // customizes
+ customizer.customize(serviceInstance);
+ });
+ }
+
private URL selectMetadataServiceExportedURL() {
URL selectedURL = null;
@@ -1118,7 +1222,7 @@ public class DubboBootstrap extends GenericEventListener {
}
private void clearConfigs() {
- configManager.clear();
+ configManager.destroy();
if (logger.isDebugEnabled()) {
logger.debug(NAME + "'s configs have been clear.");
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilder.java
index 69e7984..99af153 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilder.java
@@ -24,6 +24,8 @@ import org.apache.dubbo.config.ReferenceConfigBase;
import java.util.ArrayList;
import java.util.List;
+import static org.apache.dubbo.common.utils.StringUtils.toCommaDelimitedString;
+
/**
* This is a builder for build {@link ReferenceConfigBase}.
*
@@ -65,6 +67,13 @@ public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfi
*/
private String protocol;
+ /**
+ * The string presenting the service names that the Dubbo interface subscribed
+ *
+ * @since 2.7.8
+ */
+ private String services;
+
public static ReferenceBuilder newBuilder() {
return new ReferenceBuilder();
}
@@ -119,6 +128,17 @@ public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfi
return getThis();
}
+ /**
+ * @param service one service name
+ * @param otherServices other service names
+ * @return {@link ReferenceBuilder}
+ * @since 2.7.8
+ */
+ public ReferenceBuilder<T> services(String service, String... otherServices) {
+ this.services = toCommaDelimitedString(service, otherServices);
+ return getThis();
+ }
+
public ReferenceConfig<T> build() {
ReferenceConfig<T> reference = new ReferenceConfig<>();
super.build(reference);
@@ -132,6 +152,8 @@ public class ReferenceBuilder<T> extends AbstractReferenceBuilder<ReferenceConfi
reference.setMethods(methods);
reference.setConsumer(consumer);
reference.setProtocol(protocol);
+ // @since 2.7.8
+ reference.setServices(services);
return reference;
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/RegistryBuilder.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/RegistryBuilder.java
index f2ffab8..d717aaa 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/RegistryBuilder.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/bootstrap/builders/RegistryBuilder.java
@@ -285,6 +285,16 @@ public class RegistryBuilder extends AbstractBuilder<RegistryConfig, RegistryBui
return getThis();
}
+ /**
+ * @param name the parameter name
+ * @param value the parameter value
+ * @return {@link RegistryBuilder}
+ * @since 2.7.8
+ */
+ public RegistryBuilder parameter(String name, String value) {
+ return appendParameter(name, value);
+ }
+
public RegistryBuilder appendParameters(Map<String, String> appendParameters) {
this.parameters = appendParameters(parameters, appendParameters);
return getThis();
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListener.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListener.java
new file mode 100644
index 0000000..9731034
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListener.java
@@ -0,0 +1,74 @@
+/*
+ * 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.event.listener;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.AbstractInterfaceConfig;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.MetadataReportConfig;
+import org.apache.dubbo.config.event.ReferenceConfigInitializedEvent;
+import org.apache.dubbo.config.event.ServiceConfigExportedEvent;
+import org.apache.dubbo.event.EventListener;
+import org.apache.dubbo.event.GenericEventListener;
+import org.apache.dubbo.metadata.WritableMetadataService;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.metadata.WritableMetadataService.getExtension;
+
+/**
+ * An {@link EventListener} {@link WritableMetadataService#publishServiceDefinition(URL) publishs the service definition}
+ * when {@link ServiceConfigExportedEvent the event of the exported Dubbo service} and
+ * {@link ReferenceConfigInitializedEvent the event of the referenced Dubbo service} is raised.
+ *
+ * @see GenericEventListener
+ * @see ServiceConfigExportedEvent
+ * @see ReferenceConfigInitializedEvent
+ * @since 2.7.8
+ */
+public class PublishingServiceDefinitionListener extends GenericEventListener {
+
+ public void onEvent(ReferenceConfigInitializedEvent event) {
+ handleEvent(event.getReferenceConfig());
+ }
+
+ public void onEvent(ServiceConfigExportedEvent event) {
+ handleEvent(event.getServiceConfig());
+ }
+
+ private void handleEvent(AbstractInterfaceConfig config) {
+ String metadataType = getMetadataType(config);
+ for (URL exportedURL : config.getExportedUrls()) {
+ WritableMetadataService metadataService = getExtension(metadataType);
+ if (metadataService != null) {
+ metadataService.publishServiceDefinition(exportedURL);
+ }
+ }
+ }
+
+ private String getMetadataType(AbstractInterfaceConfig config) {
+ ApplicationConfig applicationConfig = config.getApplication();
+ String metadataType = applicationConfig.getMetadataType();
+ if (REMOTE_METADATA_STORAGE_TYPE.equals(metadataType)) {
+ MetadataReportConfig metadataReportConfig = config.getMetadataReportConfig();
+ if (metadataReportConfig == null || !metadataReportConfig.isValid()) {
+ metadataType = DEFAULT_METADATA_STORAGE_TYPE;
+ }
+ }
+ return metadataType;
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/ServiceNameMappingListener.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/ServiceNameMappingListener.java
index 4dcfde3..8607b51 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/ServiceNameMappingListener.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/event/listener/ServiceNameMappingListener.java
@@ -24,8 +24,6 @@ import org.apache.dubbo.metadata.ServiceNameMapping;
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.metadata.ServiceNameMapping.getDefaultExtension;
/**
@@ -45,11 +43,7 @@ public class ServiceNameMappingListener implements EventListener<ServiceConfigEx
ServiceConfig serviceConfig = event.getServiceConfig();
List<URL> exportedURLs = serviceConfig.getExportedUrls();
exportedURLs.forEach(url -> {
- String serviceInterface = url.getServiceInterface();
- String group = url.getParameter(GROUP_KEY);
- String version = url.getParameter(VERSION_KEY);
- String protocol = url.getProtocol();
- serviceNameMapping.map(serviceInterface, group, version, protocol);
+ serviceNameMapping.map(url);
});
}
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/AbstractMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/AbstractMetadataServiceExporter.java
new file mode 100644
index 0000000..ce2b389
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/AbstractMetadataServiceExporter.java
@@ -0,0 +1,150 @@
+/*
+ * 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.metadata;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.metadata.MetadataService;
+import org.apache.dubbo.metadata.MetadataServiceExporter;
+import org.apache.dubbo.metadata.MetadataServiceType;
+import org.apache.dubbo.metadata.WritableMetadataService;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import static java.util.EnumSet.of;
+import static org.apache.dubbo.metadata.MetadataServiceType.getOrDefault;
+
+/**
+ * The abstract implementation of {@link MetadataServiceExporter} to provider the commons features for sub-types
+ *
+ * @see MetadataServiceExporter
+ * @see MetadataService
+ * @since 2.7.8
+ */
+public abstract class AbstractMetadataServiceExporter implements MetadataServiceExporter {
+
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
+
+ protected final WritableMetadataService metadataService;
+
+ private final int priority;
+
+ private final Set<MetadataServiceType> supportedMetadataServiceTypes;
+
+ private volatile boolean exported = false;
+
+ public AbstractMetadataServiceExporter(String metadataType,
+ int priority,
+ MetadataServiceType supportMetadataServiceType,
+ MetadataServiceType... otherSupportMetadataServiceTypes) {
+ this(metadataType, priority, of(supportMetadataServiceType, otherSupportMetadataServiceTypes));
+ }
+
+ public AbstractMetadataServiceExporter(String metadataType,
+ int priority,
+ Set<MetadataServiceType> supportedMetadataServiceTypes) {
+ this.metadataService = WritableMetadataService.getExtension(metadataType);
+ this.priority = priority;
+ this.supportedMetadataServiceTypes = supportedMetadataServiceTypes;
+ }
+
+ @Override
+ public final MetadataServiceExporter export() {
+ if (!isExported()) {
+ try {
+ doExport();
+ exported = true;
+ } catch (Exception e) {
+ if (logger.isErrorEnabled()) {
+ logger.error("Exporting the MetadataService fails", e);
+ }
+ exported = false;
+ }
+ } else {
+ if (logger.isWarnEnabled()) {
+ logger.warn("The MetadataService has been exported : " + getExportedURLs());
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public final MetadataServiceExporter unexport() {
+ if (isExported()) {
+ try {
+ doUnexport();
+ exported = false;
+ } catch (Exception e) {
+ if (logger.isErrorEnabled()) {
+ logger.error("UnExporting the MetadataService fails", e);
+ }
+ }
+ }
+ return this;
+ }
+
+ @Override
+ public List<URL> getExportedURLs() {
+ return metadataService
+ .getExportedURLs()
+ .stream()
+ .map(URL::valueOf)
+ .collect(Collectors.toList());
+ }
+
+ @Override
+ public boolean isExported() {
+ return exported;
+ }
+
+ @Override
+ public final boolean supports(String metadataType) {
+ MetadataServiceType metadataServiceType = getOrDefault(metadataType);
+ return supportedMetadataServiceTypes.contains(metadataServiceType);
+ }
+
+ @Override
+ public int getPriority() {
+ return priority;
+ }
+
+ /**
+ * Exports the {@link MetadataService}
+ *
+ * @throws Exception If some exception occurs
+ */
+ protected abstract void doExport() throws Exception;
+
+ /**
+ * Unexports the {@link MetadataService}
+ *
+ * @throws Exception If some exception occurs
+ */
+ protected abstract void doUnexport() throws Exception;
+
+ /**
+ * Get the underlying of {@link MetadataService}
+ *
+ * @return non-null
+ */
+ public WritableMetadataService getMetadataService() {
+ return metadataService;
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
index fdb011f..d89fb77 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/ConfigurableMetadataServiceExporter.java
@@ -17,8 +17,6 @@
package org.apache.dubbo.config.metadata;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.logger.Logger;
-import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
@@ -26,12 +24,15 @@ import org.apache.dubbo.config.ServiceConfig;
import org.apache.dubbo.config.context.ConfigManager;
import org.apache.dubbo.metadata.MetadataService;
import org.apache.dubbo.metadata.MetadataServiceExporter;
+import org.apache.dubbo.metadata.MetadataServiceType;
import org.apache.dubbo.rpc.model.ApplicationModel;
import java.util.ArrayList;
import java.util.List;
import static java.util.Collections.emptyList;
+import static java.util.EnumSet.allOf;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
/**
@@ -49,56 +50,41 @@ import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
* @see ConfigManager
* @since 2.7.5
*/
-public class ConfigurableMetadataServiceExporter implements MetadataServiceExporter {
-
- private final Logger logger = LoggerFactory.getLogger(getClass());
-
- private final MetadataService metadataService;
+public class ConfigurableMetadataServiceExporter extends AbstractMetadataServiceExporter {
private volatile ServiceConfig<MetadataService> serviceConfig;
- public ConfigurableMetadataServiceExporter(MetadataService metadataService) {
- this.metadataService = metadataService;
+ public ConfigurableMetadataServiceExporter() {
+ super(DEFAULT_METADATA_STORAGE_TYPE, MAX_PRIORITY, allOf(MetadataServiceType.class));
}
@Override
- public ConfigurableMetadataServiceExporter export() {
-
- if (!isExported()) {
-
- ServiceConfig<MetadataService> serviceConfig = new ServiceConfig<>();
- serviceConfig.setApplication(getApplicationConfig());
- serviceConfig.setRegistries(getRegistries());
- serviceConfig.setProtocol(generateMetadataProtocol());
- serviceConfig.setInterface(MetadataService.class);
- serviceConfig.setRef(metadataService);
- serviceConfig.setGroup(getApplicationConfig().getName());
- serviceConfig.setVersion(metadataService.version());
-
- // export
- serviceConfig.export();
-
- if (logger.isInfoEnabled()) {
- logger.info("The MetadataService exports urls : " + serviceConfig.getExportedUrls());
- }
-
- this.serviceConfig = serviceConfig;
-
- } else {
- if (logger.isWarnEnabled()) {
- logger.warn("The MetadataService has been exported : " + serviceConfig.getExportedUrls());
- }
+ protected void doExport() throws Exception {
+
+ ServiceConfig<MetadataService> serviceConfig = new ServiceConfig<>();
+ serviceConfig.setApplication(getApplicationConfig());
+ serviceConfig.setRegistries(getRegistries());
+ serviceConfig.setProtocol(generateMetadataProtocol());
+ serviceConfig.setInterface(MetadataService.class);
+ serviceConfig.setRef(metadataService);
+ serviceConfig.setGroup(getApplicationConfig().getName());
+ serviceConfig.setVersion(metadataService.version());
+
+ // export
+ serviceConfig.export();
+
+ if (logger.isInfoEnabled()) {
+ logger.info("The MetadataService exports urls : " + serviceConfig.getExportedUrls());
}
- return this;
+ this.serviceConfig = serviceConfig;
}
@Override
- public ConfigurableMetadataServiceExporter unexport() {
- if (isExported()) {
+ protected void doUnexport() throws Exception {
+ if (serviceConfig != null) {
serviceConfig.unexport();
}
- return this;
}
@Override
@@ -110,6 +96,11 @@ public class ConfigurableMetadataServiceExporter implements MetadataServiceExpor
return serviceConfig != null && serviceConfig.isExported();
}
+ @Override
+ public int getPriority() {
+ return MAX_PRIORITY;
+ }
+
private ApplicationConfig getApplicationConfig() {
return ApplicationModel.getConfigManager().getApplication().get();
}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/RemoteMetadataServiceExporter.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/RemoteMetadataServiceExporter.java
new file mode 100644
index 0000000..6d48921
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/metadata/RemoteMetadataServiceExporter.java
@@ -0,0 +1,79 @@
+/*
+ * 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.metadata;
+
+import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.metadata.MetadataServiceExporter;
+import org.apache.dubbo.metadata.MetadataServiceType;
+import org.apache.dubbo.metadata.URLRevisionResolver;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.MetadataReportInstance;
+import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
+
+import java.util.SortedSet;
+
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+
+/**
+ * The implementation of {@link MetadataServiceExporter} for
+ * {@link CommonConstants#REMOTE_METADATA_STORAGE_TYPE "remote" metadata storage type}
+ *
+ * @see MetadataServiceExporter
+ * @since 2.7.8
+ */
+public class RemoteMetadataServiceExporter extends AbstractMetadataServiceExporter {
+
+ private final URLRevisionResolver urlRevisionResolver;
+
+ public RemoteMetadataServiceExporter() {
+ super(REMOTE_METADATA_STORAGE_TYPE, MIN_PRIORITY, MetadataServiceType.REMOTE, MetadataServiceType.COMPOSITE);
+ this.urlRevisionResolver = URLRevisionResolver.INSTANCE;
+ }
+
+ @Override
+ protected void doExport() throws Exception {
+ WritableMetadataService metadataServiceDelegate = WritableMetadataService.getDefaultExtension();
+ if (publishServiceMetadata(metadataServiceDelegate)) {
+ publicConsumerMetadata(metadataServiceDelegate);
+ }
+ }
+
+ private boolean publishServiceMetadata(WritableMetadataService metadataServiceDelegate) {
+ String serviceName = metadataServiceDelegate.serviceName();
+ SortedSet<String> exportedURLs = metadataServiceDelegate.getExportedURLs();
+ String revision = urlRevisionResolver.resolve(exportedURLs);
+ return getMetadataReport().saveExportedURLs(serviceName, revision, exportedURLs);
+ }
+
+ private boolean publicConsumerMetadata(WritableMetadataService metadataServiceDelegate) {
+ String serviceName = metadataServiceDelegate.serviceName();
+ SortedSet<String> subscribedURLs = metadataServiceDelegate.getSubscribedURLs();
+ String revision = urlRevisionResolver.resolve(subscribedURLs);
+ getMetadataReport().saveSubscribedData(new SubscriberMetadataIdentifier(serviceName, revision), subscribedURLs);
+ return true;
+ }
+
+ private MetadataReport getMetadataReport() {
+ return MetadataReportInstance.getMetadataReport(true);
+ }
+
+ @Override
+ protected void doUnexport() throws Exception {
+ // DOES NOTHING
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
index 2e46fa2..8a91d1c 100644
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/utils/ConfigValidationUtils.java
@@ -223,10 +223,12 @@ public class ConfigValidationUtils {
ApplicationConfig application = interfaceConfig.getApplication();
AbstractConfig.appendParameters(map, monitor);
AbstractConfig.appendParameters(map, application);
- String address = monitor.getAddress();
+ 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();
}
if (ConfigUtils.isNotEmpty(address)) {
if (!map.containsKey(PROTOCOL_KEY)) {
@@ -237,7 +239,8 @@ public class ConfigValidationUtils {
}
}
return UrlUtils.parseURL(address, map);
- } else if ((REGISTRY_PROTOCOL.equals(monitor.getProtocol()) || SERVICE_REGISTRY_PROTOCOL.equals(monitor.getProtocol()))
+ } else if (monitor != null &&
+ (REGISTRY_PROTOCOL.equals(monitor.getProtocol()) || SERVICE_REGISTRY_PROTOCOL.equals(monitor.getProtocol()))
&& registryURL != null) {
return URLBuilder.from(registryURL)
.setProtocol(DUBBO_PROTOCOL)
diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener
index db73041..b1946c0 100644
--- a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener
+++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.event.EventListener
@@ -1,2 +1,4 @@
service-mapping=org.apache.dubbo.config.event.listener.ServiceNameMappingListener
-config-logging=org.apache.dubbo.config.event.listener.LoggingEventListener
\ No newline at end of file
+config-logging=org.apache.dubbo.config.event.listener.LoggingEventListener
+# since 2.7.8
+publishing-service-definition=org.apache.dubbo.config.event.listener.PublishingServiceDefinitionListener
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
new file mode 100644
index 0000000..1b843b6
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/main/resources/META-INF/dubbo/internal/org.apache.dubbo.metadata.MetadataServiceExporter
@@ -0,0 +1,3 @@
+# since 2.7.8
+local = org.apache.dubbo.config.metadata.ConfigurableMetadataServiceExporter
+remote = org.apache.dubbo.config.metadata.RemoteMetadataServiceExporter
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
index c992e48..775596c 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
@@ -21,6 +21,7 @@ import org.apache.dubbo.config.annotation.Method;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.api.DemoService;
import org.apache.dubbo.config.provider.impl.DemoServiceImpl;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Assertions;
@@ -33,12 +34,12 @@ public class ReferenceConfigTest {
@BeforeEach
public void setUp() {
-// ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@AfterEach
public void tearDown() {
-// ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@Test
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceConsumerBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ConsulDubboServiceConsumerBootstrap.java
similarity index 80%
copy from dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceConsumerBootstrap.java
copy to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ConsulDubboServiceConsumerBootstrap.java
index 9b0d866..824de82 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceConsumerBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ConsulDubboServiceConsumerBootstrap.java
@@ -18,18 +18,22 @@ package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.bootstrap.rest.UserService;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+
/**
* Dubbo Provider Bootstrap
*
* @since 2.7.5
*/
-public class ZookeeperDubboServiceConsumerBootstrap {
+public class ConsulDubboServiceConsumerBootstrap {
public static void main(String[] args) throws Exception {
DubboBootstrap bootstrap = DubboBootstrap.getInstance()
- .application("zookeeper-dubbo-consumer")
- .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=zookeeper-dubbo-provider"))
+ .application("consul-dubbo-consumer", app -> app.metadata(DEFAULT_METADATA_STORAGE_TYPE))
+ .registry("zookeeper", builder -> builder.address("consul://127.0.0.1:8500?registry-type=service&subscribed-services=consul-dubbo-provider")
+ .useAsConfigCenter(true)
+ .useAsMetadataCenter(true))
.reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo"))
.reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
.start();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceProviderBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ConsulDubboServiceProviderBootstrap.java
similarity index 77%
copy from dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceProviderBootstrap.java
copy to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ConsulDubboServiceProviderBootstrap.java
index c653fe7..ef38944 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceProviderBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ConsulDubboServiceProviderBootstrap.java
@@ -19,15 +19,19 @@ package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import org.apache.dubbo.config.bootstrap.rest.UserServiceImpl;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+
/**
* TODO
*/
-public class ZookeeperDubboServiceProviderBootstrap {
+public class ConsulDubboServiceProviderBootstrap {
public static void main(String[] args) {
DubboBootstrap.getInstance()
- .application("zookeeper-dubbo-provider")
- .registry(builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service"))
+ .application("consul-dubbo-provider", app -> app.metadata(DEFAULT_METADATA_STORAGE_TYPE))
+ .registry(builder -> builder.address("consul://127.0.0.1:8500?registry-type=service")
+ .useAsConfigCenter(true)
+ .useAsMetadataCenter(true))
.protocol("dubbo", builder -> builder.port(-1).name("dubbo"))
.protocol("rest", builder -> builder.port(8081).name("rest"))
.service("echo", builder -> builder.interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo"))
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/NacosDubboServiceConsumerBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/NacosDubboServiceConsumerBootstrap.java
index b91659d..37262e2 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/NacosDubboServiceConsumerBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/NacosDubboServiceConsumerBootstrap.java
@@ -17,9 +17,10 @@
package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.bootstrap.rest.UserService;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+
/**
* Dubbo Provider Bootstrap
*
@@ -30,21 +31,25 @@ public class NacosDubboServiceConsumerBootstrap {
public static void main(String[] args) throws Exception {
ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-nacos-consumer-demo");
-// applicationConfig.setMetadataType("remote");
+ applicationConfig.setMetadataType(REMOTE_METADATA_STORAGE_TYPE);
DubboBootstrap bootstrap = DubboBootstrap.getInstance()
.application(applicationConfig)
- // Zookeeper
-// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service&subscribed.services=dubbo-nacos-provider-demo"))
-// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
- .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service&subscribed-services=dubbo-nacos-provider-demo"))
- .metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
+ // Nacos in service registry type
+ .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service")
+ .useAsConfigCenter(true)
+ .useAsMetadataCenter(true))
+ // Nacos in traditional registry type
+// .registry("nacos-traditional", builder -> builder.address("nacos://127.0.0.1:8848"))
+ .reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo"))
.reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
.start();
+ EchoService echoService = bootstrap.getCache().get(EchoService.class);
UserService userService = bootstrap.getCache().get(UserService.class);
- for (int i = 0; i < 500; i++) {
+ for (int i = 0; i < 5; i++) {
Thread.sleep(2000L);
+ System.out.println(echoService.echo("Hello,World"));
System.out.println(userService.getUser(i * 1L));
}
}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/NacosDubboServiceProviderBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/NacosDubboServiceProviderBootstrap.java
index 35ed723..f55790a 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/NacosDubboServiceProviderBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/NacosDubboServiceProviderBootstrap.java
@@ -17,10 +17,13 @@
package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.ApplicationConfig;
-import org.apache.dubbo.config.MetadataReportConfig;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import org.apache.dubbo.config.bootstrap.rest.UserServiceImpl;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;
+
/**
* Dubbo Provider Bootstrap
*
@@ -30,15 +33,16 @@ public class NacosDubboServiceProviderBootstrap {
public static void main(String[] args) {
ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-nacos-provider-demo");
-// applicationConfig.setMetadataType("remote");
+ applicationConfig.setMetadataType(REMOTE_METADATA_STORAGE_TYPE);
DubboBootstrap.getInstance()
.application(applicationConfig)
- // Zookeeper in service registry type
- .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry-type=service").useAsConfigCenter(true))
- // Nacos
-// .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848?registry.type=service"))
-// .registry(RegistryBuilder.newBuilder().address("etcd3://127.0.0.1:2379?registry.type=service").build())
- .metadataReport(new MetadataReportConfig("nacos://127.0.0.1:8848"))
+ // Nacos in service registry type
+ .registry("nacos", builder -> builder.address("nacos://127.0.0.1:8848")
+ .parameter(REGISTRY_TYPE_KEY, SERVICE_REGISTRY_TYPE)
+ .useAsConfigCenter(true)
+ .useAsMetadataCenter(true))
+ // Nacos in traditional registry type
+// .registry("nacos-traditional", builder -> builder.address("nacos://127.0.0.1:8848"))
.protocol("dubbo", builder -> builder.port(20885).name("dubbo"))
.protocol("rest", builder -> builder.port(9090).name("rest"))
.service(builder -> builder.id("echo").interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo"))
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceConsumerBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceConsumerBootstrap.java
index 9b0d866..27f3eb9 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceConsumerBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceConsumerBootstrap.java
@@ -18,6 +18,10 @@ package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.bootstrap.rest.UserService;
+import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;
+
/**
* Dubbo Provider Bootstrap
*
@@ -28,9 +32,12 @@ public class ZookeeperDubboServiceConsumerBootstrap {
public static void main(String[] args) throws Exception {
DubboBootstrap bootstrap = DubboBootstrap.getInstance()
- .application("zookeeper-dubbo-consumer")
- .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service&subscribed-services=zookeeper-dubbo-provider"))
- .reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo"))
+ .application("zookeeper-dubbo-consumer", app -> app.metadata(COMPOSITE_METADATA_STORAGE_TYPE))
+ .registry("zookeeper", builder -> builder.address("zookeeper://127.0.0.1:2181")
+ .parameter(REGISTRY_TYPE_KEY, SERVICE_REGISTRY_TYPE)
+ .useAsConfigCenter(true)
+ .useAsMetadataCenter(true))
+ .reference("echo", builder -> builder.interfaceClass(EchoService.class).protocol("dubbo").services("zookeeper-dubbo-provider"))
.reference("user", builder -> builder.interfaceClass(UserService.class).protocol("rest"))
.start();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceProviderBootstrap.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceProviderBootstrap.java
index c653fe7..e9b946f 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceProviderBootstrap.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/ZookeeperDubboServiceProviderBootstrap.java
@@ -19,6 +19,10 @@ package org.apache.dubbo.config.bootstrap;
import org.apache.dubbo.config.bootstrap.rest.UserService;
import org.apache.dubbo.config.bootstrap.rest.UserServiceImpl;
+import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_TYPE_KEY;
+import static org.apache.dubbo.common.constants.RegistryConstants.SERVICE_REGISTRY_TYPE;
+
/**
* TODO
*/
@@ -26,8 +30,11 @@ public class ZookeeperDubboServiceProviderBootstrap {
public static void main(String[] args) {
DubboBootstrap.getInstance()
- .application("zookeeper-dubbo-provider")
- .registry(builder -> builder.address("zookeeper://127.0.0.1:2181?registry-type=service"))
+ .application("zookeeper-dubbo-provider", app -> app.metadata(COMPOSITE_METADATA_STORAGE_TYPE))
+ .registry(builder -> builder.address("zookeeper://127.0.0.1:2181")
+ .parameter(REGISTRY_TYPE_KEY, SERVICE_REGISTRY_TYPE)
+ .useAsConfigCenter(true)
+ .useAsMetadataCenter(true))
.protocol("dubbo", builder -> builder.port(-1).name("dubbo"))
.protocol("rest", builder -> builder.port(8081).name("rest"))
.service("echo", builder -> builder.interfaceClass(EchoService.class).ref(new EchoServiceImpl()).protocolIds("dubbo"))
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilderTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilderTest.java
index 210d92e..4d11ef4 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilderTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/builders/ReferenceBuilderTest.java
@@ -26,6 +26,8 @@ import org.junit.jupiter.api.Test;
import java.util.Collections;
+import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
+
class ReferenceBuilderTest {
@Test
@@ -95,8 +97,15 @@ class ReferenceBuilderTest {
MethodConfig method = new MethodConfig();
ReferenceBuilder<DemoService> builder = new ReferenceBuilder<>();
- builder.id("id").interfaceClass(DemoService.class).protocol("protocol").client("client").url("url")
- .consumer(consumer).addMethod(method);
+ builder.id("id")
+ .interfaceClass(DemoService.class)
+ .protocol("protocol")
+ .client("client")
+ .url("url")
+ .consumer(consumer)
+ .addMethod(method)
+ // introduced since 2.7.8
+ .services("test-service", "test-service2");
ReferenceConfig config = builder.build();
ReferenceConfig config2 = builder.build();
@@ -107,6 +116,8 @@ class ReferenceBuilderTest {
Assertions.assertEquals("client", config.getClient());
Assertions.assertEquals("url", config.getUrl());
Assertions.assertEquals(consumer, config.getConsumer());
+ Assertions.assertEquals("test-service,test-service2", config.getServices());
+ Assertions.assertEquals(ofSet("test-service", "test-service2"), config.getSubscribedServices());
Assertions.assertTrue(config.getMethods().contains(method));
Assertions.assertEquals(1, config.getMethods().size());
Assertions.assertNotSame(config, config2);
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/builders/RegistryBuilderTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/builders/RegistryBuilderTest.java
index 24c4a4d..b125547 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/builders/RegistryBuilderTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/bootstrap/builders/RegistryBuilderTest.java
@@ -220,7 +220,7 @@ class RegistryBuilderTest {
.transporter("transporter").server("server").client("client").cluster("cluster").group("group")
.version("version").timeout(1000).session(2000).file("file").wait(Integer.valueOf(10)).isCheck(true)
.isDynamic(false).register(true).subscribe(false).isDefault(true).simplified(false).extraKeys("A")
- .appendParameter("default.num", "one").id("id").prefix("prefix");
+ .parameter("default.num", "one").id("id").prefix("prefix");
RegistryConfig config = builder.build();
RegistryConfig config2 = builder.build();
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListenerTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListenerTest.java
new file mode 100644
index 0000000..67a562d
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/event/listener/PublishingServiceDefinitionListenerTest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.event.listener;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.config.ServiceConfig;
+import org.apache.dubbo.config.bootstrap.EchoService;
+import org.apache.dubbo.config.bootstrap.EchoServiceImpl;
+import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.config.event.ServiceConfigExportedEvent;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import com.google.gson.Gson;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import java.util.List;
+
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
+import static org.apache.dubbo.metadata.definition.ServiceDefinitionBuilder.buildFullDefinition;
+import static org.apache.dubbo.remoting.Constants.BIND_IP_KEY;
+import static org.apache.dubbo.remoting.Constants.BIND_PORT_KEY;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * {@link PublishingServiceDefinitionListener} Test-Cases
+ *
+ * @since 2.7.8
+ */
+public class PublishingServiceDefinitionListenerTest {
+
+ private WritableMetadataService writableMetadataService;
+
+ @BeforeEach
+ public void init() {
+ String metadataType = DEFAULT_METADATA_STORAGE_TYPE;
+ ConfigManager configManager = ApplicationModel.getConfigManager();
+ ApplicationConfig applicationConfig = new ApplicationConfig("dubbo-demo-provider");
+ applicationConfig.setMetadataType(metadataType);
+ configManager.setApplication(applicationConfig);
+ this.writableMetadataService = WritableMetadataService.getExtension(metadataType);
+ }
+
+ @AfterEach
+ public void reset() {
+ ApplicationModel.reset();
+ }
+
+ /**
+ * Test {@link ServiceConfigExportedEvent} arising
+ */
+ @Test
+ public void testOnServiceConfigExportedEvent() {
+ ServiceConfig<EchoService> serviceConfig = new ServiceConfig<>();
+ serviceConfig.setInterface(EchoService.class);
+ serviceConfig.setRef(new EchoServiceImpl());
+ serviceConfig.setRegistry(new RegistryConfig("N/A"));
+ serviceConfig.export();
+
+ String serviceDefinition = writableMetadataService.getServiceDefinition(EchoService.class.getName());
+
+ List<URL> exportedUrls = serviceConfig.getExportedUrls();
+
+ FullServiceDefinition fullServiceDefinition = buildFullDefinition(
+ serviceConfig.getInterfaceClass(),
+ exportedUrls.get(0)
+ .removeParameters(PID_KEY, TIMESTAMP_KEY, BIND_IP_KEY, BIND_PORT_KEY, TIMESTAMP_KEY)
+ .getParameters()
+ );
+
+ assertEquals(serviceDefinition, new Gson().toJson(fullServiceDefinition));
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/RemoteMetadataServiceExporterTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/RemoteMetadataServiceExporterTest.java
new file mode 100644
index 0000000..e4d13a1
--- /dev/null
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/metadata/RemoteMetadataServiceExporterTest.java
@@ -0,0 +1,106 @@
+/*
+ * 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.metadata;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.config.ApplicationConfig;
+import org.apache.dubbo.metadata.MetadataServiceExporter;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.metadata.report.MetadataReportInstance;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.service.EchoService;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
+import static org.apache.dubbo.metadata.MetadataServiceExporter.getExtension;
+import static org.apache.dubbo.metadata.report.support.Constants.SYNC_REPORT_KEY;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * {@link RemoteMetadataServiceExporter} Test-Cases
+ *
+ * @since 2.7.8
+ */
+public class RemoteMetadataServiceExporterTest {
+
+ private static final URL METADATA_REPORT_URL = URL.valueOf("file://")
+ .addParameter(APPLICATION_KEY, "test")
+ .addParameter(SYNC_REPORT_KEY, "true");
+
+ private static final Class<EchoService> INTERFACE_CLASS = EchoService.class;
+
+ private static final String INTERFACE_NAME = INTERFACE_CLASS.getName();
+
+ private static final String APP_NAME = "test-service";
+
+ private static final URL BASE_URL = URL
+ .valueOf("dubbo://127.0.0.1:20880")
+ .setPath(INTERFACE_NAME)
+ .addParameter(APPLICATION_KEY, APP_NAME)
+ .addParameter(SIDE_KEY, "provider");
+
+ private final MetadataServiceExporter exporter = getExtension(REMOTE_METADATA_STORAGE_TYPE);
+
+ private WritableMetadataService writableMetadataService;
+
+ @BeforeEach
+ public void init() {
+ ApplicationModel.getConfigManager().setApplication(new ApplicationConfig(APP_NAME));
+ MetadataReportInstance.init(METADATA_REPORT_URL);
+ writableMetadataService = WritableMetadataService.getDefaultExtension();
+ writableMetadataService.exportURL(BASE_URL);
+ }
+
+ @AfterEach
+ public void reset() {
+ ApplicationModel.reset();
+ }
+
+ @Test
+ public void testType() {
+ assertEquals(RemoteMetadataServiceExporter.class, exporter.getClass());
+ }
+
+ @Test
+ public void testSupports() {
+ assertTrue(exporter.supports(REMOTE_METADATA_STORAGE_TYPE));
+ assertTrue(exporter.supports(COMPOSITE_METADATA_STORAGE_TYPE));
+ assertFalse(exporter.supports(DEFAULT_METADATA_STORAGE_TYPE));
+ }
+
+ @Test
+ public void testExportAndUnexport() {
+ assertFalse(exporter.isExported());
+ assertEquals(exporter, exporter.export());
+ assertTrue(exporter.isExported());
+
+ assertEquals(asList(BASE_URL), exporter.getExportedURLs());
+
+ assertEquals(exporter, exporter.unexport());
+ assertFalse(exporter.isExported());
+ }
+}
diff --git a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/url/ExporterSideConfigUrlTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/url/ExporterSideConfigUrlTest.java
index e1fbfb4..5c19d04 100644
--- a/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/url/ExporterSideConfigUrlTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/url/ExporterSideConfigUrlTest.java
@@ -19,6 +19,7 @@ package org.apache.dubbo.config.url;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
@@ -42,13 +43,13 @@ public class ExporterSideConfigUrlTest extends UrlTestBase {
@BeforeEach
public void setUp() {
+ ApplicationModel.reset();
initServConf();
-// ApplicationModel.getConfigManager().clear();
}
@AfterEach()
public void teardown() {
-// ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@Test
diff --git a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/metadata/MetadataServiceExporterTest.java
similarity index 52%
rename from dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java
rename to dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/metadata/MetadataServiceExporterTest.java
index 57806c3..8096276 100644
--- a/dubbo-common/src/test/java/org/apache/dubbo/convert/StringToStringConverterTest.java
+++ b/dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/metadata/MetadataServiceExporterTest.java
@@ -14,41 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.convert;
+package org.apache.dubbo.metadata;
-import org.apache.dubbo.common.convert.Converter;
-import org.apache.dubbo.common.convert.StringToStringConverter;
-
-import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
- * {@link StringToStringConverter} Test
+ * {@link MetadataServiceExporter} Test-Cases
*
- * @since 2.7.6
+ * @since 2.7.8
*/
-public class StringToStringConverterTest {
-
- private StringToStringConverter converter;
-
- @BeforeEach
- public void init() {
- converter = (StringToStringConverter) getExtensionLoader(Converter.class).getExtension("string-to-string");
- }
-
- @Test
- public void testAccept() {
- assertTrue(converter.accept(String.class, String.class));
- }
+public class MetadataServiceExporterTest {
@Test
- public void testConvert() {
- assertEquals("1", converter.convert("1"));
- assertNull(converter.convert(null));
+ public void test() {
+ MetadataServiceExporter exporter = MetadataServiceExporter.getExtension(null);
+ assertEquals(exporter, MetadataServiceExporter.getDefaultExtension());
+ assertTrue(exporter.supports(DEFAULT_METADATA_STORAGE_TYPE));
+ assertTrue(exporter.supports(REMOTE_METADATA_STORAGE_TYPE));
+ assertTrue(exporter.supports(COMPOSITE_METADATA_STORAGE_TYPE));
}
}
diff --git a/dubbo-config/dubbo-config-spring/pom.xml b/dubbo-config/dubbo-config-spring/pom.xml
index 74cc929..31bfcf4 100644
--- a/dubbo-config/dubbo-config-spring/pom.xml
+++ b/dubbo-config/dubbo-config-spring/pom.xml
@@ -142,6 +142,27 @@
<scope>test</scope>
</dependency>
+ <!-- Zookeeper dependencies for testing -->
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-registry-zookeeper</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metadata-report-zookeeper</artifactId>
+ <version>${project.parent.version}</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
<!-- Nacos dependencies for testing -->
<dependency>
<groupId>org.apache.dubbo</groupId>
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
index 05c8139..07de2ee 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessor.java
@@ -17,11 +17,11 @@
package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.dubbo.config.annotation.DubboService;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.annotation.Service;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
-import org.apache.dubbo.config.spring.context.event.ServiceBeanExportedEvent;
import com.alibaba.spring.beans.factory.annotation.AbstractAnnotationBeanPostProcessor;
import org.springframework.beans.BeansException;
@@ -31,12 +31,9 @@ import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
-import org.springframework.context.ApplicationListener;
import org.springframework.core.annotation.AnnotationAttributes;
import java.lang.reflect.Field;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
@@ -46,7 +43,6 @@ import java.util.concurrent.ConcurrentMap;
import static com.alibaba.spring.util.AnnotationUtils.getAttribute;
import static com.alibaba.spring.util.AnnotationUtils.getAttributes;
-import static java.lang.reflect.Proxy.newProxyInstance;
import static org.apache.dubbo.config.spring.beans.factory.annotation.ServiceBeanNameBuilder.create;
import static org.springframework.util.StringUtils.hasText;
@@ -60,7 +56,7 @@ import static org.springframework.util.StringUtils.hasText;
* @since 2.5.7
*/
public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBeanPostProcessor implements
- ApplicationContextAware, ApplicationListener<ServiceBeanExportedEvent> {
+ ApplicationContextAware {
/**
* The bean name of {@link ReferenceAnnotationBeanPostProcessor}
@@ -81,9 +77,6 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
private final ConcurrentMap<InjectionMetadata.InjectedElement, ReferenceBean<?>> injectedMethodReferenceBeanCache =
new ConcurrentHashMap<>(CACHE_SIZE);
- private final ConcurrentMap<String, ReferencedBeanInvocationHandler> referencedBeanInvocationHandlersCache =
- new ConcurrentHashMap<>();
-
private ApplicationContext applicationContext;
/**
@@ -142,11 +135,13 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
boolean localServiceBean = isLocalServiceBean(referencedBeanName, referenceBean, attributes);
+ prepareReferenceBean(referencedBeanName, referenceBean, localServiceBean);
+
registerReferenceBean(referencedBeanName, referenceBean, attributes, localServiceBean, injectedType);
cacheInjectedReferenceBean(referenceBean, injectedElement);
- return getOrCreateProxy(referencedBeanName, referenceBean, localServiceBean, injectedType);
+ return referenceBean.get();
}
/**
@@ -261,23 +256,19 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
}
/**
- * Get or Create a proxy of {@link ReferenceBean} for the specified the type of Dubbo service interface
+ * Prepare {@link ReferenceBean}
*
- * @param referencedBeanName The name of bean that annotated Dubbo's {@link Service @Service} in the Spring {@link ApplicationContext}
- * @param referenceBean the instance of {@link ReferenceBean}
- * @param localServiceBean Is Local Service bean or not
- * @param serviceInterfaceType the type of Dubbo service interface
- * @return non-null
- * @since 2.7.4
+ * @param referencedBeanName The name of bean that annotated Dubbo's {@link DubboService @DubboService}
+ * in the Spring {@link ApplicationContext}
+ * @param referenceBean the instance of {@link ReferenceBean}
+ * @param localServiceBean Is Local Service bean or not
+ * @since 2.7.8
*/
- private Object getOrCreateProxy(String referencedBeanName, ReferenceBean referenceBean, boolean localServiceBean,
- Class<?> serviceInterfaceType) {
- if (localServiceBean) { // If the local @Service Bean exists, build a proxy of Service
- return newProxyInstance(getClassLoader(), new Class[]{serviceInterfaceType},
- newReferencedBeanInvocationHandler(referencedBeanName));
- } else {
+ private void prepareReferenceBean(String referencedBeanName, ReferenceBean referenceBean, boolean localServiceBean) {
+ // Issue : https://github.com/apache/dubbo/issues/6224
+ if (localServiceBean) { // If the local @Service Bean exists
+ referenceBean.setInjvm(Boolean.TRUE);
exportServiceBeanIfNecessary(referencedBeanName); // If the referenced ServiceBean exits, export it immediately
- return referenceBean.get();
}
}
@@ -295,58 +286,6 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
return applicationContext.getBean(referencedBeanName, ServiceBean.class);
}
- private InvocationHandler newReferencedBeanInvocationHandler(String referencedBeanName) {
- return referencedBeanInvocationHandlersCache.computeIfAbsent(referencedBeanName,
- ReferencedBeanInvocationHandler::new);
- }
-
- /**
- * The {@link InvocationHandler} class for the referenced Bean
- */
- @Override
- public void onApplicationEvent(ServiceBeanExportedEvent event) {
- initReferencedBeanInvocationHandler(event.getServiceBean());
- }
-
- private void initReferencedBeanInvocationHandler(ServiceBean serviceBean) {
- String serviceBeanName = serviceBean.getBeanName();
- referencedBeanInvocationHandlersCache.computeIfPresent(serviceBeanName, (name, handler) -> {
- handler.init();
- return null;
- });
- }
-
- private class ReferencedBeanInvocationHandler implements InvocationHandler {
-
- private final String referencedBeanName;
-
- private Object bean;
-
- private ReferencedBeanInvocationHandler(String referencedBeanName) {
- this.referencedBeanName = referencedBeanName;
- }
-
- @Override
- public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
- Object result = null;
- try {
- if (bean == null) {
- init();
- }
- result = method.invoke(bean, args);
- } catch (InvocationTargetException e) {
- // re-throws the actual Exception.
- throw e.getTargetException();
- }
- return result;
- }
-
- private void init() {
- ServiceBean serviceBean = applicationContext.getBean(referencedBeanName, ServiceBean.class);
- this.bean = serviceBean.getRef();
- }
- }
-
@Override
protected String buildInjectedObjectCacheKey(AnnotationAttributes attributes, Object bean, String beanName,
Class<?> injectedType, InjectionMetadata.InjectedElement injectedElement) {
@@ -402,7 +341,6 @@ public class ReferenceAnnotationBeanPostProcessor extends AbstractAnnotationBean
public void destroy() throws Exception {
super.destroy();
this.referenceBeanCache.clear();
- this.referencedBeanInvocationHandlersCache.clear();
this.injectedFieldReferenceBeanCache.clear();
this.injectedMethodReferenceBeanCache.clear();
}
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/AnnotationBeanDefinitionParser.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/AnnotationBeanDefinitionParser.java
index bcc16bf..05d9027 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/AnnotationBeanDefinitionParser.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/AnnotationBeanDefinitionParser.java
@@ -25,7 +25,6 @@ import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.w3c.dom.Element;
-import static org.apache.dubbo.config.spring.util.DubboBeanUtils.registerCommonBeans;
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray;
import static org.springframework.util.StringUtils.trimArrayElements;
@@ -58,8 +57,13 @@ public class AnnotationBeanDefinitionParser extends AbstractSingleBeanDefinition
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
- // @since 2.7.6 Register the common beans
- registerCommonBeans(parserContext.getRegistry());
+ /**
+ * @since 2.7.6 Register the common beans
+ * @since 2.7.8 comment this code line, and migrated to
+ * @see DubboNamespaceHandler#parse(Element, ParserContext)
+ * @see https://github.com/apache/dubbo/issues/6174
+ */
+ // registerCommonBeans(parserContext.getRegistry());
}
@Override
diff --git a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
index 31b299a..084479a 100644
--- a/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
+++ b/dubbo-config/dubbo-config-spring/src/main/java/org/apache/dubbo/config/spring/schema/DubboBeanDefinitionParser.java
@@ -29,14 +29,13 @@ import org.apache.dubbo.config.ProviderConfig;
import org.apache.dubbo.config.RegistryConfig;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
-import org.apache.dubbo.config.spring.beans.factory.annotation.DubboConfigAliasPostProcessor;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.config.TypedStringValue;
-import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.support.RootBeanDefinition;
@@ -55,7 +54,6 @@ import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
-import static com.alibaba.spring.util.BeanRegistrar.registerInfrastructureBean;
import static org.apache.dubbo.common.constants.CommonConstants.HIDE_KEY_PREFIX;
/**
@@ -80,7 +78,7 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
}
@SuppressWarnings("unchecked")
- private static BeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
+ private static RootBeanDefinition parse(Element element, ParserContext parserContext, Class<?> beanClass, boolean required) {
RootBeanDefinition beanDefinition = new RootBeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setLazyInit(false);
@@ -130,7 +128,7 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
parseProperties(element.getChildNodes(), classDefinition, parserContext);
beanDefinition.getPropertyValues().addPropertyValue("ref", new BeanDefinitionHolder(classDefinition, id + "Impl"));
}
- } else if (ProviderConfig.class.equals(beanClass)) {
+ } else if (ProviderConfig.class.equals(beanClass)) {
parseNested(element, parserContext, ServiceBean.class, true, "service", "provider", id, beanDefinition);
} else if (ConsumerConfig.class.equals(beanClass)) {
parseNested(element, parserContext, ReferenceBean.class, false, "reference", "consumer", id, beanDefinition);
@@ -350,11 +348,18 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
if (methods == null) {
methods = new ManagedList();
}
- BeanDefinition methodBeanDefinition = parse(element,
+ RootBeanDefinition methodBeanDefinition = parse(element,
parserContext, MethodConfig.class, false);
- String name = id + "." + methodName;
+ String beanName = id + "." + methodName;
+
+ // If the PropertyValue named "id" can't be found,
+ // bean name will be taken as the "id" PropertyValue for MethodConfig
+ if (!hasPropertyValue(methodBeanDefinition, "id")) {
+ addPropertyValue(methodBeanDefinition, "id", beanName);
+ }
+
BeanDefinitionHolder methodBeanDefinitionHolder = new BeanDefinitionHolder(
- methodBeanDefinition, name);
+ methodBeanDefinition, beanName);
methods.add(methodBeanDefinitionHolder);
}
}
@@ -363,6 +368,17 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
}
}
+ private static boolean hasPropertyValue(AbstractBeanDefinition beanDefinition, String propertyName) {
+ return beanDefinition.getPropertyValues().contains(propertyName);
+ }
+
+ private static void addPropertyValue(AbstractBeanDefinition beanDefinition, String propertyName, String propertyValue) {
+ if (StringUtils.isBlank(propertyName) || StringUtils.isBlank(propertyValue)) {
+ return;
+ }
+ beanDefinition.getPropertyValues().addPropertyValue(propertyName, propertyValue);
+ }
+
@SuppressWarnings("unchecked")
private static void parseArguments(String id, NodeList nodeList, RootBeanDefinition beanDefinition,
ParserContext parserContext) {
@@ -395,22 +411,9 @@ public class DubboBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
- // Register DubboConfigAliasPostProcessor
- registerDubboConfigAliasPostProcessor(parserContext.getRegistry());
-
return parse(element, parserContext, beanClass, required);
}
- /**
- * Register {@link DubboConfigAliasPostProcessor}
- *
- * @param registry {@link BeanDefinitionRegistry}
- * @since 2.7.5 [Feature] https://github.com/apache/dubbo/issues/5093
- */
- private void registerDubboConfigAliasPostProcessor(BeanDefinitionRegistry registry) {
- registerInfrastructureBean(registry, DubboConfigAliasPostProcessor.BEAN_NAME, DubboConfigAliasPostProcessor.class);
- }
-
private static String resolveAttribute(Element element, String attributeName, ParserContext parserContext) {
String attributeValue = element.getAttribute(attributeName);
Environment environment = parserContext.getReaderContext().getEnvironment();
diff --git a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
index bfaaf3f..b12d815 100644
--- a/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
+++ b/dubbo-config/dubbo-config-spring/src/main/resources/META-INF/dubbo.xsd
@@ -6,7 +6,8 @@
targetNamespace="http://dubbo.apache.org/schema/dubbo">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace"/>
- <xsd:import namespace="http://www.springframework.org/schema/beans" schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
+ <xsd:import namespace="http://www.springframework.org/schema/beans"
+ schemaLocation="http://www.springframework.org/schema/beans/spring-beans.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:annotation>
@@ -702,7 +703,8 @@
</xsd:attribute>
<xsd:attribute name="cluster" type="xsd:string" use="optional">
<xsd:annotation>
- <xsd:documentation><![CDATA[ The config center cluster, it's real meaning may very on different Config Center products. ]]></xsd:documentation>
+ <xsd:documentation>
+ <![CDATA[ The config center cluster, it's real meaning may very on different Config Center products. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="namespace" type="xsd:string" use="optional">
@@ -945,7 +947,8 @@
</xsd:attribute>
<xsd:attribute name="threadpool" type="xsd:string">
<xsd:annotation>
- <xsd:documentation><![CDATA[ Consumer threadpool: cached, fixed, limited, eager]]></xsd:documentation>
+ <xsd:documentation>
+ <![CDATA[ Consumer threadpool: cached, fixed, limited, eager]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="corethreads" type="xsd:string">
@@ -1011,6 +1014,14 @@
<xsd:documentation><![CDATA[ The service protocol. ]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
+ <xsd:attribute name="services" type="xsd:string">
+ <xsd:annotation>
+ <xsd:documentation>
+ <![CDATA[ The service names that the Dubbo interface subscribed.
+ If it is a multiple-values, the content will be a comma-delimited String. ]]>
+ </xsd:documentation>
+ </xsd:annotation>
+ </xsd:attribute>
<xsd:anyAttribute namespace="##other" processContents="lax"/>
</xsd:extension>
</xsd:complexContent>
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
index 679d46d..598933d 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceAnnotationBeanPostProcessorTest.java
@@ -22,11 +22,14 @@ import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.api.DemoService;
import org.apache.dubbo.config.spring.api.HelloService;
import org.apache.dubbo.config.utils.ReferenceConfigCache;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
+import org.junit.After;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -67,6 +70,16 @@ import static org.junit.Assert.assertTrue;
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class ReferenceAnnotationBeanPostProcessorTest {
+ @Before
+ public void setUp() {
+ ApplicationModel.reset();
+ }
+
+ @After
+ public void tearDown() {
+ ApplicationModel.reset();
+ }
+
private static final String AOP_SUFFIX = "(based on AOP)";
@Aspect
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilderTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilderTest.java
index 4395c39..60837e2 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilderTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ReferenceBeanBuilderTest.java
@@ -17,15 +17,20 @@
package org.apache.dubbo.config.spring.beans.factory.annotation;
+import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.dubbo.config.spring.ReferenceBean;
+import org.apache.dubbo.rpc.model.ApplicationModel;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
+import org.springframework.core.annotation.AnnotationAttributes;
+import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -33,6 +38,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import static org.apache.dubbo.common.utils.CollectionUtils.ofSet;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
import static org.springframework.util.ReflectionUtils.findField;
@@ -40,6 +46,7 @@ import static org.springframework.util.ReflectionUtils.findField;
* {@link ReferenceBeanBuilder} Test
*
* @see ReferenceBeanBuilder
+ * @see DubboReference
* @see Reference
* @since 2.6.4
*/
@@ -47,7 +54,7 @@ import static org.springframework.util.ReflectionUtils.findField;
@ContextConfiguration(classes = ReferenceBeanBuilderTest.class)
public class ReferenceBeanBuilderTest {
- @Reference(
+ @DubboReference(
interfaceClass = CharSequence.class,
interfaceName = "java.lang.CharSequence",
version = "1.0.0", group = "TEST_GROUP", url = "dubbo://localhost:12345",
@@ -62,17 +69,27 @@ public class ReferenceBeanBuilderTest {
timeout = 3, cache = "cache", filter = {"echo", "generic", "accesslog"},
listener = {"deprecated"}, parameters = {"n1=v1 ", "n2 = v2 ", " n3 = v3 "},
application = "application",
- module = "module", consumer = "consumer", monitor = "monitor", registry = {"registry"}
+ module = "module", consumer = "consumer", monitor = "monitor", registry = {"registry"},
+ // @since 2.7.3
+ id = "reference",
+ // @since 2.7.8
+ services = {"service1", "service2", "service3", "service2", "service1"}
)
private static final Object TEST_FIELD = new Object();
@Autowired
private ApplicationContext context;
+ @Before
+ public void init() {
+ ApplicationModel.reset();
+ }
+
@Test
public void testBuild() throws Exception {
- Reference reference = findAnnotation(findField(getClass(), "TEST_FIELD"), Reference.class);
- ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder.create(reference, context.getClassLoader(), context);
+ DubboReference reference = findAnnotation(findField(getClass(), "TEST_FIELD"), DubboReference.class);
+ AnnotationAttributes attributes = AnnotationUtils.getAnnotationAttributes(reference, false, false);
+ ReferenceBeanBuilder beanBuilder = ReferenceBeanBuilder.create(attributes, context);
beanBuilder.interfaceClass(CharSequence.class);
ReferenceBean referenceBean = beanBuilder.build();
Assert.assertEquals(CharSequence.class, referenceBean.getInterfaceClass());
@@ -81,7 +98,7 @@ public class ReferenceBeanBuilderTest {
Assert.assertEquals("dubbo://localhost:12345", referenceBean.getUrl());
Assert.assertEquals("client", referenceBean.getClient());
Assert.assertEquals(true, referenceBean.isGeneric());
- Assert.assertNull(referenceBean.isInjvm());
+ Assert.assertTrue(referenceBean.isInjvm());
Assert.assertEquals(false, referenceBean.isCheck());
Assert.assertFalse(referenceBean.isInit());
Assert.assertEquals(true, referenceBean.getLazy());
@@ -108,6 +125,8 @@ public class ReferenceBeanBuilderTest {
Assert.assertEquals("cache", referenceBean.getCache());
Assert.assertEquals("echo,generic,accesslog", referenceBean.getFilter());
Assert.assertEquals("deprecated", referenceBean.getListener());
+ Assert.assertEquals("reference", referenceBean.getId());
+ Assert.assertEquals(ofSet("service1", "service2", "service3"), referenceBean.getSubscribedServices());
// parameters
Map<String, String> parameters = new HashMap<String, String>();
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java
index a509b43..171cda3 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceAnnotationBeanPostProcessorTest.java
@@ -18,8 +18,11 @@ package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.api.HelloService;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.junit.After;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -49,6 +52,16 @@ import java.util.Map;
})
public class ServiceAnnotationBeanPostProcessorTest {
+ @Before
+ public void setUp() {
+ ApplicationModel.reset();
+ }
+
+ @After
+ public void tearDown() {
+ ApplicationModel.reset();
+ }
+
@Autowired
private ConfigurableListableBeanFactory beanFactory;
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessorTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessorTest.java
index 4422e75..e6c1d77 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessorTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/annotation/ServiceClassPostProcessorTest.java
@@ -18,8 +18,11 @@ package org.apache.dubbo.config.spring.beans.factory.annotation;
import org.apache.dubbo.config.spring.ServiceBean;
import org.apache.dubbo.config.spring.api.HelloService;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.junit.After;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -49,6 +52,16 @@ import java.util.Map;
})
public class ServiceClassPostProcessorTest {
+ @Before
+ public void setUp() {
+ ApplicationModel.reset();
+ }
+
+ @After
+ public void tearDown() {
+ ApplicationModel.reset();
+ }
+
@Autowired
private ConfigurableListableBeanFactory beanFactory;
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/config/MultipleServicesWithMethodConfigsTest.java
similarity index 62%
copy from dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
copy to dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/config/MultipleServicesWithMethodConfigsTest.java
index 410e3e9..d66c8c3 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/beans/factory/config/MultipleServicesWithMethodConfigsTest.java
@@ -14,37 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.config.spring.schema;
-
-import org.apache.dubbo.config.spring.ReferenceBean;
-import org.apache.dubbo.config.spring.ServiceBean;
+package org.apache.dubbo.config.spring.beans.factory.config;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ImportResource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
-import static org.junit.Assert.assertNotNull;
-
@RunWith(SpringRunner.class)
-@ContextConfiguration(classes = GenericServiceTest.class)
-@ImportResource(locations = "classpath:/META-INF/spring/dubbo-generic-consumer.xml")
-public class GenericServiceTest {
-
- @Autowired
- @Qualifier("demoServiceRef")
- private ReferenceBean referenceBean;
+@ContextConfiguration(classes = MultipleServicesWithMethodConfigsTest.class)
+@ImportResource(locations = "classpath:/META-INF/spring/multiple-services-with-methods.xml")
+public class MultipleServicesWithMethodConfigsTest {
@Autowired
- @Qualifier("demoService")
- private ServiceBean serviceBean;
+ private ApplicationContext applicationContext;
@Test
- public void testBeanDefinitionParser() {
- assertNotNull(referenceBean);
- assertNotNull(serviceBean);
+ public void test() {
+// Map<String, MethodConfig> methodConfigs = applicationContext.getBeansOfType(MethodConfig.class);
+// assertEquals(2, methodConfigs.size());
}
}
+
+
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
index 2116302..80a8d40 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/DubboComponentScanRegistrarTest.java
@@ -41,12 +41,12 @@ public class DubboComponentScanRegistrarTest {
@BeforeEach
public void setUp() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@AfterEach
public void tearDown() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@Test
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboTest.java
index 42fadfc..d9364d0 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/EnableDubboTest.java
@@ -52,13 +52,13 @@ public class EnableDubboTest {
@BeforeEach
public void setUp() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
context = new AnnotationConfigApplicationContext();
}
@AfterEach
public void tearDown() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
context.close();
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/consumer/test/TestConsumerConfiguration.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/consumer/test/TestConsumerConfiguration.java
index b5b0aa5..47e0d30 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/consumer/test/TestConsumerConfiguration.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/annotation/consumer/test/TestConsumerConfiguration.java
@@ -38,7 +38,10 @@ public class TestConsumerConfiguration {
private static final String remoteURL = "dubbo://127.0.0.1:12345?version=2.5.7";
- @Reference(version = "2.5.7", url = remoteURL, application = "dubbo-demo-application")
+ @Reference(version = "2.5.7",
+ url = remoteURL,
+ application = "dubbo-demo-application",
+ filter = "mymock")
private DemoService demoService;
@Autowired
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/properties/DefaultDubboConfigBinderTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/properties/DefaultDubboConfigBinderTest.java
index aea9fb9..2123b54 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/properties/DefaultDubboConfigBinderTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/context/properties/DefaultDubboConfigBinderTest.java
@@ -20,7 +20,10 @@ package org.apache.dubbo.config.spring.context.properties;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ProtocolConfig;
import org.apache.dubbo.config.RegistryConfig;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.jupiter.api.Assertions;
import org.junit.runner.RunWith;
@@ -34,6 +37,16 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@ContextConfiguration(classes = DefaultDubboConfigBinder.class)
public class DefaultDubboConfigBinderTest {
+ @Before
+ public void setUp() {
+ ApplicationModel.reset();
+ }
+
+ @After
+ public void tearDown() {
+ ApplicationModel.reset();
+ }
+
@Autowired
private DubboConfigBinder dubboConfigBinder;
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/Issue6252Test.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/Issue6252Test.java
new file mode 100644
index 0000000..8c34e7e
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/issues/Issue6252Test.java
@@ -0,0 +1,50 @@
+/*
+ * 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.spring.issues;
+
+import org.apache.dubbo.config.spring.ReferenceBean;
+import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.PropertySource;
+
+/**
+ * The test-case for https://github.com/apache/dubbo/issues/6252
+ *
+ * @since 2.7.8
+ */
+@Configuration
+@EnableDubboConfig
+@PropertySource("classpath:/META-INF/issue-6252-test.properties")
+public class Issue6252Test {
+
+ @Bean
+ public static ReferenceBean referenceBean() {
+ return new ReferenceBean();
+ }
+
+ @Test
+ public void test() throws Exception {
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Issue6252Test.class);
+ context.getBean(ReferenceBean.class);
+ context.close();
+ }
+
+}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringConsumerBootstrap.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringConsumerBootstrap.java
new file mode 100644
index 0000000..4c567e5
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringConsumerBootstrap.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config.spring.samples;
+
+import org.apache.dubbo.config.annotation.DubboReference;
+import org.apache.dubbo.config.spring.api.DemoService;
+import org.apache.dubbo.config.spring.context.annotation.EnableDubboConfig;
+
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.PropertySource;
+
+/**
+ * Zookeeper Dubbo Spring Provider Bootstrap
+ *
+ * @since 2.7.8
+ */
+@EnableDubboConfig
+@PropertySource("classpath:/META-INF/service-introspection/zookeeper-dubbb-consumer.properties")
+public class ZookeeperDubboSpringConsumerBootstrap {
+
+ @DubboReference(services = "${dubbo.provider.name},${dubbo.provider.name1},${dubbo.provider.name2}")
+ private DemoService demoService;
+
+ public static void main(String[] args) throws Exception {
+ Class<?> beanType = ZookeeperDubboSpringConsumerBootstrap.class;
+ AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(beanType);
+
+ ZookeeperDubboSpringConsumerBootstrap bootstrap = context.getBean(ZookeeperDubboSpringConsumerBootstrap.class);
+
+ for (int i = 0; i < 100; i++) {
+ System.out.println(bootstrap.demoService.sayName("Hello"));
+ Thread.sleep(1000L);
+ }
+
+ System.in.read();
+
+ context.close();
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringConsumerXmlBootstrap.java
similarity index 51%
copy from dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
copy to dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringConsumerXmlBootstrap.java
index 0ffed8d..08c1450 100644
--- a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringConsumerXmlBootstrap.java
@@ -14,27 +14,29 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.metadata.store.zookeeper;
+package org.apache.dubbo.config.spring.samples;
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.report.MetadataReport;
-import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
-import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
+import org.apache.dubbo.config.spring.api.DemoService;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
- * ZookeeperRegistryFactory.
+ * Zookeeper Dubbo Spring Provider XML Bootstrap
+ *
+ * @since 2.7.8
*/
-public class ZookeeperMetadataReportFactory extends AbstractMetadataReportFactory {
+public class ZookeeperDubboSpringConsumerXmlBootstrap {
- private ZookeeperTransporter zookeeperTransporter;
+ public static void main(String[] args) throws Exception {
+ String location = "classpath:/META-INF/service-introspection/zookeeper-dubbo-consumer.xml";
+ ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(location);
- public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
- this.zookeeperTransporter = zookeeperTransporter;
- }
+ DemoService demoService = context.getBean("demoService", DemoService.class);
- @Override
- public MetadataReport createMetadataReport(URL url) {
- return new ZookeeperMetadataReport(url, zookeeperTransporter);
- }
+ for (int i = 0; i < 100; i++) {
+ System.out.println(demoService.sayName("Hello"));
+ }
+ context.close();
+ }
}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringProviderBootstrap.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringProviderBootstrap.java
new file mode 100644
index 0000000..ddd4010
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/samples/ZookeeperDubboSpringProviderBootstrap.java
@@ -0,0 +1,60 @@
+/*
+ * 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.spring.samples;
+
+import org.apache.dubbo.config.annotation.DubboService;
+import org.apache.dubbo.config.spring.api.Box;
+import org.apache.dubbo.config.spring.api.DemoService;
+import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
+import org.apache.dubbo.rpc.RpcContext;
+
+import org.springframework.context.annotation.AnnotationConfigApplicationContext;
+import org.springframework.context.annotation.PropertySource;
+
+import static java.lang.String.format;
+
+/**
+ * Zookeeper Dubbo Spring Provider Bootstrap
+ *
+ * @since 2.7.8
+ */
+@EnableDubbo
+@PropertySource("classpath:/META-INF/service-introspection/zookeeper-dubbb-provider.properties")
+public class ZookeeperDubboSpringProviderBootstrap {
+
+ public static void main(String[] args) throws Exception {
+ AnnotationConfigApplicationContext context =
+ new AnnotationConfigApplicationContext(ZookeeperDubboSpringProviderBootstrap.class);
+ System.in.read();
+ context.close();
+ }
+}
+
+@DubboService
+class DefaultDemoService implements DemoService {
+
+ @Override
+ public String sayName(String name) {
+ RpcContext rpcContext = RpcContext.getContext();
+ return format("[%s:%s] Say - %s", rpcContext.getLocalHost(), rpcContext.getLocalPort(), name);
+ }
+
+ @Override
+ public Box getBox() {
+ return null;
+ }
+}
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java
index a7c733c..705b890 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/DubboNamespaceHandlerTest.java
@@ -49,12 +49,12 @@ import static org.hamcrest.MatcherAssert.assertThat;
public class DubboNamespaceHandlerTest {
@BeforeEach
public void setUp() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@AfterEach
public void tearDown() {
- ApplicationModel.getConfigManager().clear();
+ ApplicationModel.reset();
}
@Configuration
diff --git a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
index 410e3e9..6deb2ab 100644
--- a/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
+++ b/dubbo-config/dubbo-config-spring/src/test/java/org/apache/dubbo/config/spring/schema/GenericServiceTest.java
@@ -18,7 +18,10 @@ package org.apache.dubbo.config.spring.schema;
import org.apache.dubbo.config.spring.ReferenceBean;
import org.apache.dubbo.config.spring.ServiceBean;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.junit.After;
+import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
@@ -34,6 +37,16 @@ import static org.junit.Assert.assertNotNull;
@ImportResource(locations = "classpath:/META-INF/spring/dubbo-generic-consumer.xml")
public class GenericServiceTest {
+ @Before
+ public void setUp() {
+ ApplicationModel.reset();
+ }
+
+ @After
+ public void tearDown() {
+ ApplicationModel.reset();
+ }
+
@Autowired
@Qualifier("demoServiceRef")
private ReferenceBean referenceBean;
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/issue-6252-test.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/issue-6252-test.properties
new file mode 100644
index 0000000..413806d
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/issue-6252-test.properties
@@ -0,0 +1,11 @@
+dubbo.application.name=demo-zk
+dubbo.application.qos-enable=false
+dubbo.protocol.name=dubbo
+dubbo.protocol.port=-1
+dubbo.scan.basePackages=com.example.demo
+dubbo.consumer.check=false
+dubbo.registries.z214.address=zookeeper://192.168.99.214:2181
+dubbo.registries.z214.timeout=60000
+dubbo.registries.z214.subscribe=false
+dubbo.registries.z205.address=zookeeper://192.168.99.205:2181
+dubbo.registries.z205.timeout=60000
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-consumer.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-consumer.properties
new file mode 100644
index 0000000..1795afa
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-consumer.properties
@@ -0,0 +1,14 @@
+# Dubbo Consumer for Zookeeper
+
+dubbo.application.name = zookeeper-dubbo-spring-consumer
+
+dubbo.registry.address = zookeeper://127.0.0.1:2181?registry-type=service
+dubbo.registry.useAsConfigCenter = true
+dubbo.registry.useAsMetadataCenter = true
+
+dubbo.protocol.name = dubbo
+dubbo.protocol.port = -1
+
+dubbo.provider.name = zookeeper-dubbo-spring-provider
+dubbo.provider.name1 = zookeeper-dubbo-spring-provider-1
+dubbo.provider.name2 = zookeeper-dubbo-spring-provider-2
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-provider.properties b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-provider.properties
new file mode 100644
index 0000000..1b977a5
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbb-provider.properties
@@ -0,0 +1,10 @@
+# Dubbo Provider for Zookeeper
+
+dubbo.application.name = zookeeper-dubbo-spring-provider-1
+
+dubbo.registry.address = zookeeper://127.0.0.1:2181?registry-type=service
+dubbo.registry.useAsConfigCenter = true
+dubbo.registry.useAsMetadataCenter = true
+
+dubbo.protocol.name = dubbo
+dubbo.protocol.port = -1
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbo-consumer.xml b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbo-consumer.xml
new file mode 100644
index 0000000..92305f5
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/service-introspection/zookeeper-dubbo-consumer.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+ -->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
+ xmlns="http://www.springframework.org/schema/beans"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
+ http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">
+
+ <!-- 当前应用信息配置 -->
+ <dubbo:application name="zookeeper-dubbo-spring-consumer"/>
+
+ <!-- 连接注册中心配置 -->
+ <dubbo:registry address="zookeeper://127.0.0.1:2181?registry-type=service" use-as-config-center="true"
+ use-as-metadata-center="true"/>
+
+ <dubbo:reference id="demoService" interface="org.apache.dubbo.config.spring.api.DemoService"
+ services="zookeeper-dubbo-spring-provider,zookeeper-dubbo-spring-provider"/>
+
+</beans>
\ No newline at end of file
diff --git a/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/multiple-services-with-methods.xml b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/multiple-services-with-methods.xml
new file mode 100644
index 0000000..848990d
--- /dev/null
+++ b/dubbo-config/dubbo-config-spring/src/test/resources/META-INF/spring/multiple-services-with-methods.xml
@@ -0,0 +1,45 @@
+<!--
+ 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.
+ -->
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
+ xmlns="http://www.springframework.org/schema/beans"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
+ http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd
+ ">
+
+ <!-- current application configuration -->
+ <dubbo:application id="application" name="demo-provider"/>
+
+ <!-- registry center configuration -->
+ <dubbo:registry id="registry" address="N/A"/>
+
+ <!-- protocol configuration -->
+ <dubbo:protocol name="dubbo" port="-1"/>
+
+ <!-- service configuration -->
+ <dubbo:service interface="org.apache.dubbo.config.spring.api.DemoService"
+ class="org.apache.dubbo.config.spring.impl.DemoServiceImpl">
+ <dubbo:method name="sayName" timeout="500" />
+ </dubbo:service>
+
+ <dubbo:service interface="org.apache.dubbo.config.spring.api.DemoService"
+ class="org.apache.dubbo.config.spring.impl.DemoServiceImpl_LongWaiting">
+ <dubbo:method name="sayName" timeout="1000" />
+ </dubbo:service>
+
+
+</beans>
\ No newline at end of file
diff --git a/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
index e0e9a86..5bf8abe 100644
--- a/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
@@ -21,11 +21,10 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.ConfigChangeType;
import org.apache.dubbo.common.config.configcenter.ConfigChangedEvent;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
-import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.TreePathDynamicConfiguration;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.StringUtils;
import com.google.common.base.Charsets;
import com.google.common.net.HostAndPort;
@@ -34,39 +33,36 @@ import com.orbitz.consul.KeyValueClient;
import com.orbitz.consul.cache.KVCache;
import com.orbitz.consul.model.kv.Value;
+import java.util.Collection;
import java.util.LinkedHashSet;
+import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.SortedSet;
-import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
-import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
-import static org.apache.dubbo.common.utils.StringUtils.EMPTY_STRING;
/**
* config center implementation for consul
*/
-public class ConsulDynamicConfiguration implements DynamicConfiguration {
+public class ConsulDynamicConfiguration extends TreePathDynamicConfiguration {
private static final Logger logger = LoggerFactory.getLogger(ConsulDynamicConfiguration.class);
private static final int DEFAULT_PORT = 8500;
private static final int DEFAULT_WATCH_TIMEOUT = 60 * 1000;
private static final String WATCH_TIMEOUT = "consul-watch-timeout";
- private URL url;
- private String rootPath;
private Consul client;
+
private KeyValueClient kvClient;
+
private ConcurrentMap<String, ConsulListener> watchers = new ConcurrentHashMap<>();
public ConsulDynamicConfiguration(URL url) {
- this.url = url;
- this.rootPath = PATH_SEPARATOR + url.getParameter(CONFIG_NAMESPACE_KEY, DEFAULT_GROUP) + PATH_SEPARATOR + "config";
+ super(url);
String host = url.getHost();
int port = url.getPort() != 0 ? url.getPort() : DEFAULT_PORT;
client = Consul.builder().withHostAndPort(HostAndPort.fromParts(host, port)).build();
@@ -74,112 +70,69 @@ public class ConsulDynamicConfiguration implements DynamicConfiguration {
}
@Override
- public void addListener(String key, String group, ConfigurationListener listener) {
- logger.info("register listener " + listener.getClass() + " for config with key: " + key + ", group: " + group);
- String normalizedKey = convertKey(group, key);
- ConsulListener watcher = watchers.computeIfAbsent(normalizedKey, k -> new ConsulListener(key, group));
- watcher.addListener(listener);
+ public String getInternalProperty(String key) {
+ logger.info("getting config from: " + key);
+ return kvClient.getValueAsString(key, Charsets.UTF_8).orElse(null);
}
@Override
- public void removeListener(String key, String group, ConfigurationListener listener) {
- logger.info("unregister listener " + listener.getClass() + " for config with key: " + key + ", group: " + group);
- ConsulListener watcher = watchers.get(convertKey(group, key));
- if (watcher != null) {
- watcher.removeListener(listener);
- }
+ protected boolean doPublishConfig(String pathKey, String content) throws Exception {
+ return kvClient.putValue(pathKey, content);
+ }
+
+ @Override
+ protected String doGetConfig(String pathKey) throws Exception {
+ return getInternalProperty(pathKey);
}
@Override
- public String getConfig(String key, String group, long timeout) throws IllegalStateException {
- return (String) getInternalProperty(convertKey(group, key));
+ protected boolean doRemoveConfig(String pathKey) throws Exception {
+ kvClient.deleteKey(pathKey);
+ return true;
}
@Override
- public SortedSet<String> getConfigKeys(String group) throws UnsupportedOperationException {
- SortedSet<String> configKeys = new TreeSet<>();
- String normalizedKey = convertKey(group, EMPTY_STRING);
- List<String> keys = kvClient.getKeys(normalizedKey);
+ protected Collection<String> doGetConfigKeys(String groupPath) {
+ List<String> keys = kvClient.getKeys(groupPath);
+ List<String> configKeys = new LinkedList<>();
if (CollectionUtils.isNotEmpty(keys)) {
keys.stream()
- .filter(k -> !k.equals(normalizedKey))
+ .filter(k -> !k.equals(groupPath))
.map(k -> k.substring(k.lastIndexOf(PATH_SEPARATOR) + 1))
.forEach(configKeys::add);
}
return configKeys;
-// SortedSet<String> configKeys = new TreeSet<>();
-// String normalizedKey = convertKey(group, key);
-// kvClient.getValueAsString(normalizedKey).ifPresent(v -> {
-// Collections.addAll(configKeys, v.split(","));
-// });
-// return configKeys;
}
- /**
- * @param key the key to represent a configuration
- * @param group the group where the key belongs to
- * @param content the content of configuration
- * @return
- * @throws UnsupportedOperationException
- */
@Override
- public boolean publishConfig(String key, String group, String content) throws UnsupportedOperationException {
-// String normalizedKey = convertKey(group, key);
-// Value value = kvClient.getValue(normalizedKey).orElseThrow(() -> new IllegalArgumentException(normalizedKey + " does not exit."));
-// Optional<String> old = value.getValueAsString();
-// if (old.isPresent()) {
-// content = old.get() + "," + content;
-// }
-//
-// while (!kvClient.putValue(key, content, value.getModifyIndex())) {
-// value = kvClient.getValue(normalizedKey).orElseThrow(() -> new IllegalArgumentException(normalizedKey + " does not exit."));
-// old = value.getValueAsString();
-// if (old.isPresent()) {
-// content = old.get() + "," + content;
-// }
-// try {
-// Thread.sleep(10);
-// } catch (InterruptedException e) {
-// e.printStackTrace();
-// }
-// }
-// return true;
- String normalizedKey = convertKey(group, key);
- return kvClient.putValue(normalizedKey, content);
+ protected void doAddListener(String pathKey, ConfigurationListener listener) {
+ logger.info("register listener " + listener.getClass() + " for config with key: " + pathKey);
+ ConsulListener watcher = watchers.computeIfAbsent(pathKey, k -> new ConsulListener(pathKey));
+ watcher.addListener(listener);
}
@Override
- public Object getInternalProperty(String key) {
- logger.info("getting config from: " + key);
- return kvClient.getValueAsString(key, Charsets.UTF_8).orElse(null);
+ protected void doRemoveListener(String pathKey, ConfigurationListener listener) {
+ logger.info("unregister listener " + listener.getClass() + " for config with key: " + pathKey);
+ ConsulListener watcher = watchers.get(pathKey);
+ if (watcher != null) {
+ watcher.removeListener(listener);
+ }
}
@Override
- public void close() throws Exception {
+ protected void doClose() throws Exception {
client.destroy();
}
- private String buildPath(String group) {
- String actualGroup = StringUtils.isEmpty(group) ? DEFAULT_GROUP : group;
- return rootPath + PATH_SEPARATOR + actualGroup;
- }
-
- private String convertKey(String group, String key) {
- return buildPath(group) + PATH_SEPARATOR + key;
- }
-
private class ConsulListener implements KVCache.Listener<String, Value> {
private KVCache kvCache;
private Set<ConfigurationListener> listeners = new LinkedHashSet<>();
- private String key;
- private String group;
private String normalizedKey;
- public ConsulListener(String key, String group) {
- this.key = key;
- this.group = group;
- this.normalizedKey = convertKey(group, key);
+ public ConsulListener(String normalizedKey) {
+ this.normalizedKey = normalizedKey;
initKVCache();
}
@@ -201,7 +154,7 @@ public class ConsulDynamicConfiguration implements DynamicConfiguration {
// Values are encoded in key/value store, decode it if needed
Optional<String> decodedValue = newValue.get().getValueAsString();
decodedValue.ifPresent(v -> listeners.forEach(l -> {
- ConfigChangedEvent event = new ConfigChangedEvent(key, group, v, ConfigChangeType.MODIFIED);
+ ConfigChangedEvent event = new ConfigChangedEvent(normalizedKey, getGroup(), v, ConfigChangeType.MODIFIED);
l.process(event);
}));
});
diff --git a/dubbo-configcenter/dubbo-configcenter-consul/src/test/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-consul/src/test/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfigurationTest.java
index d924c83..c54d103 100644
--- a/dubbo-configcenter/dubbo-configcenter-consul/src/test/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfigurationTest.java
+++ b/dubbo-configcenter/dubbo-configcenter-consul/src/test/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfigurationTest.java
@@ -30,7 +30,9 @@ import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import java.util.Arrays;
import java.util.Optional;
+import java.util.TreeSet;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -51,10 +53,10 @@ public class ConsulDynamicConfigurationTest {
consul = ConsulStarterBuilder.consulStarter()
.build()
.start();
- configCenterUrl = URL.valueOf("consul://localhost:" + consul.getHttpPort());
+ configCenterUrl = URL.valueOf("consul://127.0.0.1:" + consul.getHttpPort());
configuration = new ConsulDynamicConfiguration(configCenterUrl);
- client = Consul.builder().withHostAndPort(HostAndPort.fromParts("localhost", consul.getHttpPort())).build();
+ client = Consul.builder().withHostAndPort(HostAndPort.fromParts("127.0.0.1", consul.getHttpPort())).build();
kvClient = client.keyValueClient();
}
@@ -75,6 +77,14 @@ public class ConsulDynamicConfigurationTest {
}
@Test
+ public void testPublishConfig() {
+ configuration.publishConfig("value", "metadata", "1");
+ // test equals
+ assertEquals("1", configuration.getConfig("value", "/metadata"));
+ assertEquals("1", kvClient.getValueAsString("/dubbo/config/metadata/value").get());
+ }
+
+ @Test
public void testAddListener() {
KVCache cache = KVCache.newCache(kvClient, "/dubbo/config/dubbo/foo");
cache.addListener(newValues -> {
@@ -103,13 +113,11 @@ public class ConsulDynamicConfigurationTest {
}
@Test
- public void testPublishConfig() {
- configuration.publishConfig("foo", "value1");
- Assertions.assertEquals("value1", configuration.getString("/dubbo/config/dubbo/foo"));
- }
-
- @Test
public void testGetConfigKeys() {
-
+ configuration.publishConfig("v1", "metadata", "1");
+ configuration.publishConfig("v2", "metadata", "2");
+ configuration.publishConfig("v3", "metadata", "3");
+ // test equals
+ assertEquals(new TreeSet(Arrays.asList("v1", "v2", "v3")), configuration.getConfigKeys("metadata"));
}
}
diff --git a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
index 2227015..cca467f 100644
--- a/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
@@ -30,6 +30,7 @@ import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.AbstractSharedListener;
import com.alibaba.nacos.api.exception.NacosException;
@@ -50,31 +51,17 @@ import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.Executor;
import java.util.stream.Stream;
-import static com.alibaba.nacos.api.PropertyKeyConst.ACCESS_KEY;
-import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_NAME;
-import static com.alibaba.nacos.api.PropertyKeyConst.CONFIG_LONG_POLL_TIMEOUT;
-import static com.alibaba.nacos.api.PropertyKeyConst.CONFIG_RETRY_TIME;
-import static com.alibaba.nacos.api.PropertyKeyConst.CONTEXT_PATH;
-import static com.alibaba.nacos.api.PropertyKeyConst.ENABLE_REMOTE_SYNC_CONFIG;
import static com.alibaba.nacos.api.PropertyKeyConst.ENCODE;
-import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT;
-import static com.alibaba.nacos.api.PropertyKeyConst.ENDPOINT_PORT;
-import static com.alibaba.nacos.api.PropertyKeyConst.IS_USE_CLOUD_NAMESPACE_PARSING;
-import static com.alibaba.nacos.api.PropertyKeyConst.IS_USE_ENDPOINT_PARSING_RULE;
-import static com.alibaba.nacos.api.PropertyKeyConst.MAX_RETRY;
-import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
-import static com.alibaba.nacos.api.PropertyKeyConst.NAMING_CLIENT_BEAT_THREAD_COUNT;
import static com.alibaba.nacos.api.PropertyKeyConst.NAMING_LOAD_CACHE_AT_START;
-import static com.alibaba.nacos.api.PropertyKeyConst.NAMING_POLLING_THREAD_COUNT;
-import static com.alibaba.nacos.api.PropertyKeyConst.RAM_ROLE_NAME;
-import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
import static com.alibaba.nacos.client.naming.utils.UtilAndComs.NACOS_NAMING_LOG_NAME;
import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
+import static org.apache.dubbo.common.utils.StringConstantFieldValuePredicate.of;
import static org.apache.dubbo.common.utils.StringUtils.HYPHEN_CHAR;
import static org.apache.dubbo.common.utils.StringUtils.SLASH_CHAR;
+import static org.apache.dubbo.common.utils.StringUtils.isBlank;
/**
* The nacos implementation of {@link DynamicConfiguration}
@@ -159,24 +146,13 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
private static void setProperties(URL url, Properties properties) {
putPropertyIfAbsent(url, properties, NACOS_NAMING_LOG_NAME);
- putPropertyIfAbsent(url, properties, IS_USE_CLOUD_NAMESPACE_PARSING);
- putPropertyIfAbsent(url, properties, IS_USE_ENDPOINT_PARSING_RULE);
- putPropertyIfAbsent(url, properties, ENDPOINT);
- putPropertyIfAbsent(url, properties, ENDPOINT_PORT);
- putPropertyIfAbsent(url, properties, NAMESPACE);
- putPropertyIfAbsent(url, properties, ACCESS_KEY);
- putPropertyIfAbsent(url, properties, SECRET_KEY);
- putPropertyIfAbsent(url, properties, RAM_ROLE_NAME);
- putPropertyIfAbsent(url, properties, CONTEXT_PATH);
- putPropertyIfAbsent(url, properties, CLUSTER_NAME);
- putPropertyIfAbsent(url, properties, ENCODE);
- putPropertyIfAbsent(url, properties, CONFIG_LONG_POLL_TIMEOUT);
- putPropertyIfAbsent(url, properties, CONFIG_RETRY_TIME);
- putPropertyIfAbsent(url, properties, MAX_RETRY);
- putPropertyIfAbsent(url, properties, ENABLE_REMOTE_SYNC_CONFIG);
+
+ // Get the parameters from constants
+ Map<String, String> parameters = url.getParameters(of(PropertyKeyConst.class));
+ // Put all parameters
+ properties.putAll(parameters);
+
putPropertyIfAbsent(url, properties, NAMING_LOAD_CACHE_AT_START, "true");
- putPropertyIfAbsent(url, properties, NAMING_CLIENT_BEAT_THREAD_COUNT);
- putPropertyIfAbsent(url, properties, NAMING_POLLING_THREAD_COUNT);
}
private static void putPropertyIfAbsent(URL url, Properties properties, String propertyName) {
@@ -260,13 +236,9 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
boolean published = false;
String resolvedGroup = resolveGroup(group);
try {
- String value = configService.getConfig(key, resolvedGroup, getDefaultTimeout());
- if (StringUtils.isNotEmpty(value)) {
- content = value + "," + content;
- }
published = configService.publishConfig(key, resolvedGroup, content);
} catch (NacosException e) {
- logger.error(e.getErrMsg());
+ logger.error(e.getErrMsg(), e);
}
return published;
}
@@ -279,7 +251,6 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
/**
* TODO Nacos does not support atomic update of the value mapped to a key.
*
- * @param key
* @param group the specified group
* @return
*/
@@ -307,6 +278,19 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
return keys;
}
+ @Override
+ public boolean removeConfig(String key, String group) {
+ boolean removed = false;
+ try {
+ removed = configService.removeConfig(key, group);
+ } catch (NacosException e) {
+ if (logger.isErrorEnabled()) {
+ logger.error(e.getMessage(), e);
+ }
+ }
+ return removed;
+ }
+
private Stream<String> toKeysStream(String content) {
JSONObject jsonObject = JSON.parseObject(content);
JSONArray pageItems = jsonObject.getJSONArray("pageItems");
@@ -376,6 +360,6 @@ public class NacosDynamicConfiguration implements DynamicConfiguration {
}
protected String resolveGroup(String group) {
- return group.replace(SLASH_CHAR, HYPHEN_CHAR);
+ return isBlank(group) ? group : group.replace(SLASH_CHAR, HYPHEN_CHAR);
}
}
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
index 4bd65a9..a96f843 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
@@ -18,36 +18,21 @@ package org.apache.dubbo.configcenter.support.zookeeper;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
-import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.TreePathDynamicConfiguration;
import org.apache.dubbo.common.utils.NamedThreadFactory;
-import org.apache.dubbo.common.utils.StringUtils;
import org.apache.dubbo.remoting.zookeeper.ZookeeperClient;
import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.List;
-import java.util.SortedSet;
-import java.util.TreeSet;
+import java.util.Collection;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
-import static java.util.Collections.emptySortedSet;
-import static java.util.Collections.unmodifiableSortedSet;
-import static org.apache.dubbo.common.config.configcenter.Constants.CONFIG_NAMESPACE_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
-import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
-import static org.apache.dubbo.common.utils.StringUtils.EMPTY_STRING;
-
/**
*
*/
-public class ZookeeperDynamicConfiguration implements DynamicConfiguration {
-
- private static final Logger logger = LoggerFactory.getLogger(ZookeeperDynamicConfiguration.class);
+public class ZookeeperDynamicConfiguration extends TreePathDynamicConfiguration {
private Executor executor;
// The final root path would be: /configRootPath/"config"
@@ -60,8 +45,9 @@ public class ZookeeperDynamicConfiguration implements DynamicConfiguration {
ZookeeperDynamicConfiguration(URL url, ZookeeperTransporter zookeeperTransporter) {
+ super(url);
this.url = url;
- rootPath = PATH_SEPARATOR + url.getParameter(CONFIG_NAMESPACE_KEY, DEFAULT_GROUP) + "/config";
+ rootPath = getRootPath(url);
initializedLatch = new CountDownLatch(1);
this.cacheListener = new CacheListener(rootPath, initializedLatch);
@@ -87,52 +73,44 @@ public class ZookeeperDynamicConfiguration implements DynamicConfiguration {
* @return
*/
@Override
- public Object getInternalProperty(String key) {
+ public String getInternalProperty(String key) {
return zkClient.getContent(key);
}
- /**
- * For service governance, multi group is not supported by this implementation. So group is not used at present.
- */
@Override
- public void addListener(String key, String group, ConfigurationListener listener) {
- cacheListener.addListener(getPathKey(group, key), listener);
+ protected void doClose() throws Exception {
+ zkClient.close();
}
@Override
- public void removeListener(String key, String group, ConfigurationListener listener) {
- cacheListener.removeListener(getPathKey(group, key), listener);
+ protected boolean doPublishConfig(String pathKey, String content) throws Exception {
+ zkClient.create(pathKey, content, false);
+ return true;
}
@Override
- public String getConfig(String key, String group, long timeout) throws IllegalStateException {
- return (String) getInternalProperty(getPathKey(group, key));
+ protected String doGetConfig(String pathKey) throws Exception {
+ return zkClient.getContent(pathKey);
}
@Override
- public boolean publishConfig(String key, String group, String content) {
- String path = getPathKey(group, key);
- zkClient.create(path, content, false);
+ protected boolean doRemoveConfig(String pathKey) throws Exception {
+ zkClient.delete(pathKey);
return true;
}
@Override
- public SortedSet<String> getConfigKeys(String group) {
- String path = getPathKey(group, EMPTY_STRING);
- List<String> nodes = zkClient.getChildren(path);
- return isEmpty(nodes) ? emptySortedSet() : unmodifiableSortedSet(new TreeSet<>(nodes));
+ protected Collection<String> doGetConfigKeys(String groupPath) {
+ return zkClient.getChildren(groupPath);
}
- private String buildPath(String group) {
- String actualGroup = StringUtils.isEmpty(group) ? DEFAULT_GROUP : group;
- return rootPath + PATH_SEPARATOR + actualGroup;
+ @Override
+ protected void doAddListener(String pathKey, ConfigurationListener listener) {
+ cacheListener.addListener(pathKey, listener);
}
- private String getPathKey(String group, String key) {
- if (StringUtils.isEmpty(key)) {
- return buildPath(group);
- }
- return buildPath(group) + PATH_SEPARATOR + key;
+ @Override
+ protected void doRemoveListener(String pathKey, ConfigurationListener listener) {
+ cacheListener.removeListener(pathKey, listener);
}
-
}
diff --git a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java
index 3c06fbe..9d4a0c3 100644
--- a/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java
+++ b/dubbo-configcenter/dubbo-configcenter-zookeeper/src/test/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfigurationTest.java
@@ -58,7 +58,7 @@ public class ZookeeperDynamicConfigurationTest {
public static void setUp() throws Exception {
zkServer = new TestingServer(zkServerPort, true);
- client = CuratorFrameworkFactory.newClient("localhost:" + zkServerPort, 60 * 1000, 60 * 1000,
+ client = CuratorFrameworkFactory.newClient("127.0.0.1:" + zkServerPort, 60 * 1000, 60 * 1000,
new ExponentialBackoffRetry(1000, 3));
client.start();
@@ -73,7 +73,7 @@ public class ZookeeperDynamicConfigurationTest {
}
- configUrl = URL.valueOf("zookeeper://localhost:" + zkServerPort);
+ configUrl = URL.valueOf("zookeeper://127.0.0.1:" + zkServerPort);
configuration = ExtensionLoader.getExtensionLoader(DynamicConfigurationFactory.class).getExtension(configUrl.getProtocol()).getDynamicConfiguration(configUrl);
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/CompositeServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/CompositeServiceNameMapping.java
new file mode 100644
index 0000000..9ad130b
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/CompositeServiceNameMapping.java
@@ -0,0 +1,96 @@
+/*
+ * 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.metadata;
+
+
+import org.apache.dubbo.common.URL;
+
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import static java.util.Collections.emptySet;
+import static java.util.Collections.unmodifiableSet;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.apache.dubbo.common.utils.CollectionUtils.isNotEmpty;
+
+/**
+ * The composite implementation of {@link ServiceNameMapping}
+ *
+ * @see ParameterizedServiceNameMapping
+ * @see PropertiesFileServiceNameMapping
+ * @see DynamicConfigurationServiceNameMapping
+ * @since 2.7.8
+ */
+public class CompositeServiceNameMapping implements ServiceNameMapping {
+
+ private volatile List<ServiceNameMapping> serviceNameMappings;
+
+ private List<ServiceNameMapping> getServiceNameMappings() {
+ if (this.serviceNameMappings == null) {
+ synchronized (this) {
+ if (this.serviceNameMappings == null) {
+ Set<ServiceNameMapping> serviceNameMappings = loadAllServiceNameMappings();
+
+ removeSelf(serviceNameMappings);
+
+ this.serviceNameMappings = new LinkedList<>(serviceNameMappings);
+ }
+ }
+ }
+ return this.serviceNameMappings;
+ }
+
+ private Set<ServiceNameMapping> loadAllServiceNameMappings() {
+ return getExtensionLoader(ServiceNameMapping.class).getSupportedExtensionInstances();
+ }
+
+ private void removeSelf(Set<ServiceNameMapping> serviceNameMappings) {
+ Iterator<ServiceNameMapping> iterator = serviceNameMappings.iterator();
+ while (iterator.hasNext()) {
+ ServiceNameMapping serviceNameMapping = iterator.next();
+ if (this.getClass().equals(serviceNameMapping.getClass())) {
+ iterator.remove(); // Remove self
+ }
+ }
+ }
+
+ @Override
+ public void map(URL exportedURL) {
+ List<ServiceNameMapping> serviceNameMappings = getServiceNameMappings();
+ serviceNameMappings.forEach(serviceNameMapping -> serviceNameMapping.map(exportedURL));
+ }
+
+ @Override
+ public Set<String> get(URL subscribedURL) {
+ List<ServiceNameMapping> serviceNameMappings = getServiceNameMappings();
+ Set<String> serviceNames = null;
+ for (ServiceNameMapping serviceNameMapping : serviceNameMappings) {
+ serviceNames = serviceNameMapping.get(subscribedURL);
+ if (isNotEmpty(serviceNames)) {
+ break;
+ }
+ }
+ return serviceNames == null ? emptySet() : unmodifiableSet(serviceNames);
+ }
+
+ @Override
+ public int getPriority() {
+ return MIN_PRIORITY;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
index d84eba0..2a04cb7 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/DynamicConfigurationServiceNameMapping.java
@@ -16,6 +16,7 @@
*/
package org.apache.dubbo.metadata;
+import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import org.apache.dubbo.common.logger.Logger;
import org.apache.dubbo.common.logger.LoggerFactory;
@@ -27,11 +28,17 @@ import java.util.Set;
import static java.lang.String.valueOf;
import static java.util.Arrays.asList;
+import static org.apache.dubbo.common.config.configcenter.DynamicConfiguration.getDynamicConfiguration;
+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.common.utils.CollectionUtils.isNotEmpty;
import static org.apache.dubbo.common.utils.StringUtils.SLASH;
import static org.apache.dubbo.rpc.model.ApplicationModel.getName;
/**
* The {@link ServiceNameMapping} implementation based on {@link DynamicConfiguration}
+ *
+ * @since 2.7.5
*/
public class DynamicConfigurationServiceNameMapping implements ServiceNameMapping {
@@ -41,14 +48,24 @@ public class DynamicConfigurationServiceNameMapping implements ServiceNameMappin
private final Logger logger = LoggerFactory.getLogger(getClass());
+ /**
+ * The priority of {@link DynamicConfigurationServiceNameMapping} is
+ * lower than {@link ParameterizedServiceNameMapping}
+ */
+ static final int PRIORITY = PropertiesFileServiceNameMapping.PRIORITY + 1;
+
@Override
- public void map(String serviceInterface, String group, String version, String protocol) {
+ public void map(URL exportedURL) {
+
+ String serviceInterface = exportedURL.getServiceInterface();
if (IGNORED_SERVICE_INTERFACES.contains(serviceInterface)) {
return;
}
- DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration();
+ String group = exportedURL.getParameter(GROUP_KEY);
+ String version = exportedURL.getParameter(VERSION_KEY);
+ String protocol = exportedURL.getProtocol();
// the Dubbo Service Key as group
// the service(application) name as key
@@ -56,7 +73,7 @@ public class DynamicConfigurationServiceNameMapping implements ServiceNameMappin
String key = getName();
String content = valueOf(System.currentTimeMillis());
execute(() -> {
- dynamicConfiguration.publishConfig(key, buildGroup(serviceInterface, group, version, protocol), content);
+ getDynamicConfiguration().publishConfig(key, buildGroup(serviceInterface, group, version, protocol), content);
if (logger.isInfoEnabled()) {
logger.info(String.format("Dubbo service[%s] mapped to interface name[%s].",
group, serviceInterface, group));
@@ -65,14 +82,19 @@ public class DynamicConfigurationServiceNameMapping implements ServiceNameMappin
}
@Override
- public Set<String> get(String serviceInterface, String group, String version, String protocol) {
+ public Set<String> get(URL subscribedURL) {
- DynamicConfiguration dynamicConfiguration = DynamicConfiguration.getDynamicConfiguration();
+ String serviceInterface = subscribedURL.getServiceInterface();
+ String group = subscribedURL.getParameter(GROUP_KEY);
+ String version = subscribedURL.getParameter(VERSION_KEY);
+ String protocol = subscribedURL.getProtocol();
Set<String> serviceNames = new LinkedHashSet<>();
execute(() -> {
- Set<String> keys = dynamicConfiguration.getConfigKeys(buildGroup(serviceInterface, group, version, protocol));
- serviceNames.addAll(keys);
+ Set<String> keys = getDynamicConfiguration().getConfigKeys(buildGroup(serviceInterface, group, version, protocol));
+ if (isNotEmpty(keys)) {
+ serviceNames.addAll(keys);
+ }
});
return Collections.unmodifiableSet(serviceNames);
}
@@ -96,4 +118,9 @@ public class DynamicConfigurationServiceNameMapping implements ServiceNameMappin
}
}
}
+
+ @Override
+ public int getPriority() {
+ return PRIORITY;
+ }
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java
index e03ddd6..d670089 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataConstants.java
@@ -16,11 +16,22 @@
*/
package org.apache.dubbo.metadata;
-public class MetadataConstants {
- public static final String KEY_SEPARATOR = ":";
- public static final String DEFAULT_PATH_TAG = "metadata";
- public static final String KEY_REVISON_PREFIX = "revision";
- public static final String META_DATA_STORE_TAG = ".metaData";
- public static final String SERVICE_META_DATA_STORE_TAG = ".smd";
- public static final String CONSUMER_META_DATA_STORE_TAG = ".cmd";
+public interface MetadataConstants {
+ String KEY_SEPARATOR = ":";
+ String DEFAULT_PATH_TAG = "metadata";
+ String KEY_REVISON_PREFIX = "revision";
+ String META_DATA_STORE_TAG = ".metaData";
+ String SERVICE_META_DATA_STORE_TAG = ".smd";
+ String CONSUMER_META_DATA_STORE_TAG = ".cmd";
+
+ /**
+ * @since 2.7.8
+ */
+ String EXPORTED_URLS_TAG = "exported-urls";
+
+ /**
+ * @since 2.7.8
+ */
+ String SUBSCRIBED_URLS_TAG = "subscribed-urls";
+
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
index 0780149..660ac42 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataService.java
@@ -28,6 +28,7 @@ import java.util.stream.StreamSupport;
import static java.util.Collections.unmodifiableSortedSet;
import static java.util.stream.StreamSupport.stream;
+import static org.apache.dubbo.common.URL.buildKey;
/**
* A framework interface of Dubbo Metadata Service defines the contract of Dubbo Services registartion and subscription
@@ -90,7 +91,7 @@ public interface MetadataService {
* @see #toSortedStrings(Stream)
* @see URL#toFullString()
*/
- default SortedSet<String> getSubscribedURLs(){
+ default SortedSet<String> getSubscribedURLs() {
throw new UnsupportedOperationException("This operation is not supported for consumer.");
}
@@ -165,7 +166,9 @@ public interface MetadataService {
*
* @return
*/
- String getServiceDefinition(String interfaceName, String version, String group);
+ default String getServiceDefinition(String interfaceName, String version, String group) {
+ return getServiceDefinition(buildKey(interfaceName, group, version));
+ }
/**
* Interface definition.
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
index 16d1e3b..34d3b54 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceExporter.java
@@ -17,9 +17,14 @@
package org.apache.dubbo.metadata;
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.lang.Prioritized;
import java.util.List;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+
/**
* The exporter of {@link MetadataService}
*
@@ -28,7 +33,8 @@ import java.util.List;
* @see #unexport()
* @since 2.7.5
*/
-public interface MetadataServiceExporter {
+@SPI(DEFAULT_METADATA_STORAGE_TYPE)
+public interface MetadataServiceExporter extends Prioritized {
/**
* Exports the {@link MetadataService} as a Dubbo service
@@ -57,5 +63,38 @@ public interface MetadataServiceExporter {
* @return if {@link #export()} was executed, return <code>true</code>, or <code>false</code>
*/
boolean isExported();
+
+ /**
+ * Does current implementation support the specified metadata type?
+ *
+ * @param metadataType the specified metadata type
+ * @return If supports, return <code>true</code>, or <code>false</code>
+ * @since 2.7.8
+ */
+ default boolean supports(String metadataType) {
+ return true;
+ }
+
+ /**
+ * Get the extension of {@link MetadataServiceExporter} by the type.
+ * If not found, return the default implementation
+ *
+ * @param metadataType the metadata type
+ * @return non-null
+ * @since 2.7.8
+ */
+ static MetadataServiceExporter getExtension(String metadataType) {
+ return getExtensionLoader(MetadataServiceExporter.class).getOrDefaultExtension(metadataType);
+ }
+
+ /**
+ * Get the default extension of {@link MetadataServiceExporter}
+ *
+ * @return non-null
+ * @since 2.7.8
+ */
+ static MetadataServiceExporter getDefaultExtension() {
+ return getExtension(DEFAULT_METADATA_STORAGE_TYPE);
+ }
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceType.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceType.java
new file mode 100644
index 0000000..3af6b38
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataServiceType.java
@@ -0,0 +1,72 @@
+/*
+ * 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.metadata;
+
+import static org.apache.dubbo.common.constants.CommonConstants.COMPOSITE_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
+import static org.apache.dubbo.common.constants.CommonConstants.REMOTE_METADATA_STORAGE_TYPE;
+
+/**
+ * The type enumerations of {@link MetadataService}
+ *
+ * @see MetadataService
+ * @since 2.7.8
+ */
+public enum MetadataServiceType {
+
+ /**
+ * The default type of {@link MetadataService}
+ */
+ DEFAULT(DEFAULT_METADATA_STORAGE_TYPE),
+
+ /**
+ * The remote type of {@link MetadataService}
+ */
+ REMOTE(REMOTE_METADATA_STORAGE_TYPE),
+
+ /**
+ * The composite type of {@link MetadataService}
+ */
+ COMPOSITE(COMPOSITE_METADATA_STORAGE_TYPE);
+
+ /**
+ * The {@link String} value of type
+ */
+ private final String value;
+
+ MetadataServiceType(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public static MetadataServiceType getOrDefault(String value) {
+ MetadataServiceType targetType = null;
+ for (MetadataServiceType type : values()) {
+ if (type.getValue().equals(value)) {
+ targetType = type;
+ break;
+ }
+ }
+ if (targetType == null) {
+ targetType = DEFAULT;
+ }
+ return targetType;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataUtil.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataUtil.java
deleted file mode 100644
index 85ce30e..0000000
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/MetadataUtil.java
+++ /dev/null
@@ -1,49 +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.metadata;
-
-/**
- * FIXME
- * 2019-07-31
- */
-public class MetadataUtil {
-
-// public static String getMetadataKey(URL url, KeyTypeEnum keyType){
-//
-// }
-//
-// private String getIdentifierKey() {
-// return serviceInterface
-// + KEY_SEPARATOR + (version == null ? "" : version)
-// + KEY_SEPARATOR + (group == null ? "" : group)
-// + KEY_SEPARATOR + (side == null ? "" : side)
-// + KEY_SEPARATOR + application;
-// }
-//
-// private String getFilePathKey() {
-// return getFilePathKey(DEFAULT_PATH_TAG);
-// }
-//
-// private String getFilePathKey(String pathTag) {
-// return pathTag
-// + (StringUtils.isEmpty(toServicePath()) ? "" : (PATH_SEPARATOR + toServicePath()))
-// + (version == null ? "" : (PATH_SEPARATOR + version))
-// + (group == null ? "" : (PATH_SEPARATOR + group))
-// + (side == null ? "" : (PATH_SEPARATOR + side))
-// + (getApplication() == null ? "" : (PATH_SEPARATOR + getApplication()));
-// }
-}
diff --git a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ParameterizedServiceNameMapping.java
similarity index 56%
copy from dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
copy to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ParameterizedServiceNameMapping.java
index 0ffed8d..893a6f4 100644
--- a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ParameterizedServiceNameMapping.java
@@ -14,27 +14,34 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.metadata.store.zookeeper;
+package org.apache.dubbo.metadata;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.report.MetadataReport;
-import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
-import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
+
+import java.util.Set;
+
+import static org.apache.dubbo.common.constants.RegistryConstants.SUBSCRIBED_SERVICE_NAMES_KEY;
/**
- * ZookeeperRegistryFactory.
+ * The parameterized implementation of {@link ServiceNameMapping}
+ *
+ * @see ReadOnlyServiceNameMapping
+ * @since 2.7.8
*/
-public class ZookeeperMetadataReportFactory extends AbstractMetadataReportFactory {
+public class ParameterizedServiceNameMapping extends ReadOnlyServiceNameMapping {
- private ZookeeperTransporter zookeeperTransporter;
+ /**
+ * The priority of {@link PropertiesFileServiceNameMapping}
+ */
+ static final int PRIORITY = MAX_PRIORITY + 99;
- public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
- this.zookeeperTransporter = zookeeperTransporter;
+ @Override
+ public Set<String> get(URL subscribedURL) {
+ return getValue(subscribedURL.getParameter(SUBSCRIBED_SERVICE_NAMES_KEY));
}
@Override
- public MetadataReport createMetadataReport(URL url) {
- return new ZookeeperMetadataReport(url, zookeeperTransporter);
+ public int getPriority() {
+ return PRIORITY;
}
-
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/PropertiesFileServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/PropertiesFileServiceNameMapping.java
new file mode 100644
index 0000000..7870895
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/PropertiesFileServiceNameMapping.java
@@ -0,0 +1,148 @@
+/*
+ * 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.metadata;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.Configuration;
+import org.apache.dubbo.common.constants.CommonConstants;
+import org.apache.dubbo.common.utils.ClassUtils;
+import org.apache.dubbo.common.utils.PathUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Set;
+
+import static java.lang.String.format;
+import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.VERSION_KEY;
+import static org.apache.dubbo.common.utils.StringUtils.SLASH;
+import static org.apache.dubbo.metadata.MetadataConstants.KEY_SEPARATOR;
+
+/**
+ * The externalized {@link Properties} file implementation of {@link ServiceNameMapping},
+ * the default properties class path is
+ * {@link CommonConstants#DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH "/META-INF/dubbo/service-name-mapping.properties"},
+ * whose format as following:
+ * <pre>
+ * dubbo\:com.acme.Interface1\:default = Service1
+ * thirft\:com.acme.InterfaceX = Service1,Service2
+ * rest\:com.acme.interfaceN = Service3
+ * </pre>
+ * <p>
+ * THe search path could be configured by the externalized property {@link CommonConstants#SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY}
+ *
+ * @see ReadOnlyServiceNameMapping
+ * @see ParameterizedServiceNameMapping
+ * @since 2.7.8
+ */
+public class PropertiesFileServiceNameMapping extends ReadOnlyServiceNameMapping {
+
+ /**
+ * The priority of {@link PropertiesFileServiceNameMapping} is
+ * lower than {@link ParameterizedServiceNameMapping}
+ */
+ static final int PRIORITY = ParameterizedServiceNameMapping.PRIORITY + 1;
+
+
+ private final List<Properties> propertiesList;
+
+ public PropertiesFileServiceNameMapping() {
+ this.propertiesList = loadPropertiesList();
+ }
+
+ @Override
+ public Set<String> get(URL subscribedURL) {
+ String propertyKey = getPropertyKey(subscribedURL);
+ String propertyValue = null;
+
+ for (Properties properties : propertiesList) {
+ propertyValue = properties.getProperty(propertyKey);
+ if (propertyValue != null) {
+ break;
+ }
+ }
+
+ return getValue(propertyValue);
+ }
+
+ private String getPropertyKey(URL url) {
+ String protocol = url.getProtocol();
+ String serviceInterface = url.getServiceInterface();
+ // Optional
+ String group = url.getParameter(GROUP_KEY);
+ String version = url.getParameter(VERSION_KEY);
+
+ StringBuilder propertyKeyBuilder = new StringBuilder(protocol)
+ .append(KEY_SEPARATOR)
+ .append(serviceInterface);
+
+ appendIfPresent(propertyKeyBuilder, group);
+ appendIfPresent(propertyKeyBuilder, version);
+
+ return propertyKeyBuilder.toString();
+ }
+
+ private void appendIfPresent(StringBuilder builder, String value) {
+ if (!StringUtils.isBlank(value)) {
+ builder.append(KEY_SEPARATOR).append(value);
+ }
+ }
+
+ private List<Properties> loadPropertiesList() {
+ List<Properties> propertiesList = new LinkedList<>();
+ String propertiesPath = getPropertiesPath();
+ try {
+ Enumeration<java.net.URL> resources = ClassUtils.getClassLoader().getResources(propertiesPath);
+ while (resources.hasMoreElements()) {
+ java.net.URL resource = resources.nextElement();
+ InputStream inputStream = resource.openStream();
+ Properties properties = new Properties();
+ properties.load(new InputStreamReader(inputStream, "UTF-8"));
+ propertiesList.add(properties);
+ }
+ } catch (IOException e) {
+ if (logger.isErrorEnabled()) {
+ logger.error(format("The path of ServiceNameMapping's Properties file[path : %s] can't be loaded", propertiesPath), e);
+ }
+ }
+ return propertiesList;
+ }
+
+ private String getPropertiesPath() {
+ Configuration configuration = ApplicationModel.getEnvironment().getConfiguration();
+ String propertyPath = configuration.getString(SERVICE_NAME_MAPPING_PROPERTIES_FILE_KEY, DEFAULT_SERVICE_NAME_MAPPING_PROPERTIES_PATH);
+ propertyPath = PathUtils.normalize(propertyPath);
+ if (propertyPath.startsWith(SLASH)) {
+ propertyPath = propertyPath.substring(SLASH.length());
+ }
+ return propertyPath;
+ }
+
+ @Override
+ public int getPriority() {
+ return PRIORITY;
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ReadOnlyServiceNameMapping.java
similarity index 54%
copy from dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
copy to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ReadOnlyServiceNameMapping.java
index 0ffed8d..58035d3 100644
--- a/dubbo-metadata/dubbo-metadata-report-zookeeper/src/main/java/org/apache/dubbo/metadata/store/zookeeper/ZookeeperMetadataReportFactory.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ReadOnlyServiceNameMapping.java
@@ -14,27 +14,32 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.metadata.store.zookeeper;
+package org.apache.dubbo.metadata;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.metadata.report.MetadataReport;
-import org.apache.dubbo.metadata.report.support.AbstractMetadataReportFactory;
-import org.apache.dubbo.remoting.zookeeper.ZookeeperTransporter;
+import org.apache.dubbo.common.logger.Logger;
+import org.apache.dubbo.common.logger.LoggerFactory;
+
+import java.util.Set;
+
+import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR_CHAR;
+import static org.apache.dubbo.common.utils.StringUtils.splitToSet;
/**
- * ZookeeperRegistryFactory.
+ * Read-Only implementation of {@link ServiceNameMapping}
+ *
+ * @since 2.7.8
*/
-public class ZookeeperMetadataReportFactory extends AbstractMetadataReportFactory {
+public abstract class ReadOnlyServiceNameMapping implements ServiceNameMapping {
- private ZookeeperTransporter zookeeperTransporter;
-
- public void setZookeeperTransporter(ZookeeperTransporter zookeeperTransporter) {
- this.zookeeperTransporter = zookeeperTransporter;
- }
+ protected final Logger logger = LoggerFactory.getLogger(getClass());
@Override
- public MetadataReport createMetadataReport(URL url) {
- return new ZookeeperMetadataReport(url, zookeeperTransporter);
+ public void map(URL exportedURL) {
+ // DO NOTING for mapping
}
+ protected Set<String> getValue(String rawValue) {
+ return splitToSet(rawValue, COMMA_SEPARATOR_CHAR, true);
+ }
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
index 74113f2..46f657d 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/ServiceNameMapping.java
@@ -16,7 +16,9 @@
*/
package org.apache.dubbo.metadata;
+import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.SPI;
+import org.apache.dubbo.common.lang.Prioritized;
import java.util.Set;
@@ -28,7 +30,7 @@ import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoad
* @since 2.7.5
*/
@SPI("default")
-public interface ServiceNameMapping {
+public interface ServiceNameMapping extends Prioritized {
/**
* Map the specified Dubbo service interface, group, version and protocol to current Dubbo service name
@@ -37,8 +39,20 @@ public interface ServiceNameMapping {
* @param group the group of Dubbo service interface (optional)
* @param version the version of Dubbo service interface version (optional)
* @param protocol the protocol of Dubbo service interface exported (optional)
+ * @deprecated 2.7.8 This method will be removed since 3.0
*/
- void map(String serviceInterface, String group, String version, String protocol);
+ @Deprecated
+ default void map(String serviceInterface, String group, String version, String protocol) {
+ throw new UnsupportedOperationException("This method has been deprecated and should not be invoked!");
+ }
+
+ /**
+ * Map the specified Dubbo service {@link URL} to current Dubbo service name
+ *
+ * @param exportedURL the {@link URL} that the Dubbo Provider exported
+ * @since 2.7.8
+ */
+ void map(URL exportedURL);
/**
* Get the service names from the specified Dubbo service interface, group, version and protocol
@@ -47,10 +61,22 @@ public interface ServiceNameMapping {
* @param group the group of Dubbo service interface (optional)
* @param version the version of Dubbo service interface version (optional)
* @param protocol the protocol of Dubbo service interface exported (optional)
- * @return
+ * @return non-null {@link Set}
+ * @deprecated 2.7.8 This method will be removed since 3.0
*/
- Set<String> get(String serviceInterface, String group, String version, String protocol);
+ @Deprecated
+ default Set<String> get(String serviceInterface, String group, String version, String protocol) {
+ throw new UnsupportedOperationException("This method has been deprecated and should not be invoked!");
+ }
+ /**
+ * Get the service names from the subscribed Dubbo service {@link URL}
+ *
+ * @param subscribedURL the {@link URL} that the Dubbo consumer subscribed
+ * @return non-null {@link Set}
+ * @since 2.7.8
+ */
+ Set<String> get(URL subscribedURL);
/**
* Get the default extension of {@link ServiceNameMapping}
diff --git a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/URLRevisionResolver.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/URLRevisionResolver.java
similarity index 67%
rename from dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/URLRevisionResolver.java
rename to dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/URLRevisionResolver.java
index 66f4dbf..f3fe79c 100644
--- a/dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/client/metadata/URLRevisionResolver.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/URLRevisionResolver.java
@@ -14,12 +14,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.registry.client.metadata;
+package org.apache.dubbo.metadata;
import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.compiler.support.ClassUtils;
-import org.apache.dubbo.metadata.MetadataService;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
@@ -27,7 +27,9 @@ import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
+import static java.util.Collections.emptyList;
import static org.apache.dubbo.common.constants.CommonConstants.PID_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.TIMESTAMP_KEY;
import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
@@ -35,29 +37,64 @@ import static org.apache.dubbo.common.utils.CollectionUtils.isEmpty;
/**
* A class to resolve the version from {@link URL URLs}
*
+ * @revised 2.7.8 repackage and refactor
* @since 2.7.5
*/
public class URLRevisionResolver {
- public static final String NO_REVISION = "N/A";
+ /**
+ * @since 2.7.8
+ */
+ public static final String UNKNOWN_REVISION = "X";
+
+ /**
+ * @since 2.7.8
+ */
+ public static final URLRevisionResolver INSTANCE = new URLRevisionResolver();
+
+ /**
+ * Resolve revision as {@link String} from the specified the {@link URL#toFullString() strings} presenting the {@link URL URLs}.
+ *
+ * @param url one {@link URL}
+ * @param others the others {@link URL}
+ * @return non-null
+ * @since 2.7.8
+ */
+ public String resolve(String url, String... others) {
+ List<String> urls = new ArrayList<>(others.length + 1);
+ urls.add(url);
+ urls.addAll(Arrays.asList(others));
+ return resolve(urls);
+ }
/**
* Resolve revision as {@link String}
*
* @param urls {@link URL#toFullString() strings} presenting the {@link URL URLs}
* @return non-null
+ * @revised 2.7.8 refactor the parameter as the super interface (from Collection to Iterable)
*/
- public String resolve(Collection<String> urls) {
+ public String resolve(Iterable<String> urls) {
+ List<URL> urlsList = toURLsList(urls);
+ return resolve(urlsList);
+ }
+
+ /**
+ * Resolve revision as {@link String} from the specified the {@link URL URLs}.
+ *
+ * @param urls the {@link URL URLs}
+ * @return non-null
+ * @since 2.7.8
+ */
+ public String resolve(Collection<URL> urls) {
if (isEmpty(urls)) {
- return NO_REVISION;
+ return UNKNOWN_REVISION;
}
- List<URL> urlsList = toURLsList(urls);
-
- SortedSet<String> methodSignatures = resolveMethodSignatures(urlsList);
+ SortedSet<String> methodSignatures = resolveMethodSignatures(urls);
- SortedSet<String> urlParameters = resolveURLParameters(urlsList);
+ SortedSet<String> urlParameters = resolveURLParameters(urls);
SortedSet<String> values = new TreeSet<>(methodSignatures);
@@ -66,18 +103,22 @@ public class URLRevisionResolver {
return values.stream()
.map(this::hashCode) // generate Long hashCode
.reduce(Long::sum) // sum hashCode
- .map(String::valueOf) // Long to String
- .orElse(NO_REVISION); // NO_REVISION as default
+ .map(Long::toHexString) // Using Hex for the shorten content
+ .orElse(UNKNOWN_REVISION); // NO_REVISION as default
}
- private List<URL> toURLsList(Collection<String> urls) {
- return urls.stream()
+ private List<URL> toURLsList(Iterable<String> urls) {
+ if (urls == null) {
+ return emptyList();
+ }
+ return StreamSupport.
+ stream(urls.spliterator(), false)
.map(URL::valueOf) // String to URL
.filter(url -> isNotMetadataService(url.getServiceInterface())) // filter not MetadataService interface
.collect(Collectors.toList());
}
- private SortedSet<String> resolveMethodSignatures(List<URL> urls) {
+ private SortedSet<String> resolveMethodSignatures(Collection<URL> urls) {
return urls.stream()
.map(URL::getServiceInterface) // get the service interface
.map(ClassUtils::forName) // load business interface class
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
index 3a17395..6cde356 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/WritableMetadataService.java
@@ -20,10 +20,10 @@ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.extension.ExtensionLoader;
import org.apache.dubbo.common.extension.SPI;
import org.apache.dubbo.metadata.store.InMemoryWritableMetadataService;
-import org.apache.dubbo.rpc.model.ApplicationModel;
import static org.apache.dubbo.common.constants.CommonConstants.DEFAULT_METADATA_STORAGE_TYPE;
import static org.apache.dubbo.common.extension.ExtensionLoader.getExtensionLoader;
+import static org.apache.dubbo.rpc.model.ApplicationModel.getName;
/**
* Local {@link MetadataService} that extends {@link MetadataService} and provides the modification, which is used for
@@ -40,7 +40,7 @@ public interface WritableMetadataService extends MetadataService {
*/
@Override
default String serviceName() {
- return ApplicationModel.getApplication();
+ return getName();
}
/**
@@ -63,7 +63,9 @@ public interface WritableMetadataService extends MetadataService {
* fresh Exports
*
* @return If success , return <code>true</code>
+ * @deprecated Recommend to use {@link MetadataServiceExporter} since 2.7.8
*/
+ @Deprecated
default boolean refreshMetadata(String exportedRevision, String subscribedRevision) {
return true;
}
@@ -84,7 +86,7 @@ public interface WritableMetadataService extends MetadataService {
*/
boolean unsubscribeURL(URL url);
- void publishServiceDefinition(URL providerUrl);
+ void publishServiceDefinition(URL url);
/**
* Get {@link ExtensionLoader#getDefaultExtension() the defautl extension} of {@link WritableMetadataService}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
index e5fc587..068d3a0 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/MetadataReport.java
@@ -17,34 +17,144 @@
package org.apache.dubbo.metadata.report;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.metadata.URLRevisionResolver;
import org.apache.dubbo.metadata.definition.model.ServiceDefinition;
import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
+import com.google.gson.Gson;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import static java.util.Collections.emptyList;
+import static java.util.Collections.emptySortedSet;
+import static org.apache.dubbo.rpc.model.ApplicationModel.getName;
+
/**
+ * The interface to report the metadata
*
+ * @see AutoCloseable since 2.7.8
*/
-public interface MetadataReport {
+public interface MetadataReport extends AutoCloseable {
void storeProviderMetadata(MetadataIdentifier providerMetadataIdentifier, ServiceDefinition serviceDefinition);
void storeConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, Map<String, String> serviceParameterMap);
- void saveServiceMetadata(ServiceMetadataIdentifier metadataIdentifier, URL url);
+ /**
+ * @deprecated 2.7.8
+ */
+ @Deprecated
+ default void saveServiceMetadata(ServiceMetadataIdentifier metadataIdentifier, URL url) {
+ }
- void removeServiceMetadata(ServiceMetadataIdentifier metadataIdentifier);
+ /**
+ * @deprecated 2.7.8
+ */
+ @Deprecated
+ default void removeServiceMetadata(ServiceMetadataIdentifier metadataIdentifier) {
- List<String> getExportedURLs(ServiceMetadataIdentifier metadataIdentifier);
+ }
- void saveSubscribedData(SubscriberMetadataIdentifier subscriberMetadataIdentifier, Set<String> urls);
+ /**
+ * @deprecated 2.7.8
+ */
+ @Deprecated
+ default List<String> getExportedURLs(ServiceMetadataIdentifier metadataIdentifier) {
+ return emptyList();
+ }
- List<String> getSubscribedURLs(SubscriberMetadataIdentifier subscriberMetadataIdentifier);
+ void saveSubscribedData(SubscriberMetadataIdentifier subscriberMetadataIdentifier, Collection<String> urls);
+
+ Collection<String> getSubscribedURLs(SubscriberMetadataIdentifier subscriberMetadataIdentifier);
String getServiceDefinition(MetadataIdentifier metadataIdentifier);
-}
+
+ /**
+ * Save the exported {@link URL#toFullString() strings} presenting the {@link URL URLs} in bulk.
+ *
+ * @param exportedURLs the exported {@link URL urls}
+ * @return If successful, return <code>true</code>, or <code>false</code>
+ * @since 2.7.8
+ */
+ default boolean saveExportedURLs(SortedSet<String> exportedURLs) {
+ return saveExportedURLs(getName(), exportedURLs);
+ }
+
+ /**
+ * Save the exported {@link URL#toFullString() strings} presenting the {@link URL URLs} in bulk.
+ *
+ * @param serviceName the specified Dubbo service name
+ * @param exportedURLs the exported {@link URL urls}
+ * @return If successful, return <code>true</code>, or <code>false</code>
+ * @since 2.7.8
+ */
+ default boolean saveExportedURLs(String serviceName, SortedSet<String> exportedURLs) {
+ return saveExportedURLs(serviceName, new URLRevisionResolver().resolve(exportedURLs), exportedURLs);
+ }
+
+ /**
+ * Save the exported {@link URL#toFullString() strings} presenting the {@link URL URLs} in bulk.
+ *
+ * @param serviceName the specified Dubbo service name
+ * @param exportedServicesRevision the revision of the exported Services
+ * @param exportedURLs the exported {@link URL urls}
+ * @return If successful, return <code>true</code>, or <code>false</code>
+ * @since 2.7.8
+ */
+ default boolean saveExportedURLs(String serviceName, String exportedServicesRevision, SortedSet<String> exportedURLs) {
+ Gson gson = new Gson();
+ String content = gson.toJson(exportedURLs);
+ return saveExportedURLs(serviceName, exportedServicesRevision, content);
+ }
+
+ /**
+ * Save the exported {@link URL#toFullString() strings} presenting the {@link URL URLs} in bulk.
+ *
+ * @param serviceName the specified Dubbo service name
+ * @param exportedServicesRevision the revision of the exported Services
+ * @param exportedURLsContent the content of the exported {@link URL urls}
+ * @return If successful, return <code>true</code>, or <code>false</code>
+ * @since 2.7.8
+ */
+ default boolean saveExportedURLs(String serviceName, String exportedServicesRevision, String exportedURLsContent) {
+ return true;
+ }
+
+ /**
+ * Get the {@link URL#toFullString() strings} presenting the {@link URL URLs} that were exported by the provider
+ *
+ * @param serviceName the specified Dubbo service name
+ * @param exportedServicesRevision the revision of the exported Services
+ * @return non-null
+ * @since 2.7.8
+ */
+ default SortedSet<String> getExportedURLs(String serviceName, String exportedServicesRevision) {
+ String exportedURLsContent = getExportedURLsContent(serviceName, exportedServicesRevision);
+ if (StringUtils.isBlank(exportedURLsContent)) {
+ return emptySortedSet();
+ }
+ Gson gson = new Gson();
+ return gson.fromJson(exportedURLsContent, TreeSet.class);
+ }
+
+ /**
+ * Get the {@link URL#toFullString() strings} presenting the {@link URL URLs} that were exported by the provider
+ *
+ * @param serviceName the specified Dubbo service name
+ * @param exportedServicesRevision the revision of the exported Services
+ * @return the content of the exported {@link URL urls} if found, or <code>null</code>
+ * @since 2.7.8
+ */
+ default String getExportedURLsContent(String serviceName, String exportedServicesRevision) {
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseApplicationMetadataIdentifier.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseApplicationMetadataIdentifier.java
index 9e6b76b..f70678b 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseApplicationMetadataIdentifier.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/BaseApplicationMetadataIdentifier.java
@@ -17,6 +17,7 @@
package org.apache.dubbo.metadata.report.identifier;
import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
+import static org.apache.dubbo.common.utils.PathUtils.buildPath;
import static org.apache.dubbo.metadata.MetadataConstants.DEFAULT_PATH_TAG;
import static org.apache.dubbo.metadata.MetadataConstants.KEY_SEPARATOR;
@@ -36,9 +37,7 @@ public class BaseApplicationMetadataIdentifier {
}
String getIdentifierKey(String... params) {
-
- return application
- + joinParams(KEY_SEPARATOR, params);
+ return application + joinParams(KEY_SEPARATOR, params);
}
private String joinParams(String joinChar, String... params) {
@@ -58,9 +57,7 @@ public class BaseApplicationMetadataIdentifier {
}
private String getFilePathKey(String pathTag, String... params) {
- return pathTag
- + application
- + joinParams(PATH_SEPARATOR, params);
+ return buildPath(pathTag, application, joinParams(PATH_SEPARATOR, params));
}
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/KeyTypeEnum.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/KeyTypeEnum.java
index 2c0da57..3253f85 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/KeyTypeEnum.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/KeyTypeEnum.java
@@ -16,9 +16,47 @@
*/
package org.apache.dubbo.metadata.report.identifier;
+import static org.apache.dubbo.common.constants.CommonConstants.PATH_SEPARATOR;
+import static org.apache.dubbo.common.utils.PathUtils.buildPath;
+import static org.apache.dubbo.common.utils.StringUtils.EMPTY_STRING;
+import static org.apache.dubbo.common.utils.StringUtils.isBlank;
+import static org.apache.dubbo.metadata.MetadataConstants.KEY_SEPARATOR;
+
/**
* 2019-08-15
*/
public enum KeyTypeEnum {
- PATH, UNIQUE_KEY
+
+ PATH(PATH_SEPARATOR) {
+ public String build(String one, String... others) {
+ return buildPath(one, others);
+ }
+ },
+
+ UNIQUE_KEY(KEY_SEPARATOR) {
+ public String build(String one, String... others) {
+ StringBuilder keyBuilder = new StringBuilder(one);
+ for (String other : others) {
+ keyBuilder.append(separator).append(isBlank(other) ? EMPTY_STRING : other);
+ }
+ return keyBuilder.toString();
+ }
+ };
+
+ final String separator;
+
+ KeyTypeEnum(String separator) {
+ this.separator = separator;
+ }
+
+ /**
+ * Build Key
+ *
+ * @param one one
+ * @param others the others
+ * @return
+ * @since 2.7.8
+ */
+ public abstract String build(String one, String... others);
+
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
index 1d39401..f3b90db 100644
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
@@ -44,6 +44,7 @@ import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -52,7 +53,6 @@ import java.util.Set;
import java.util.SortedSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadLocalRandom;
@@ -61,11 +61,15 @@ import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
+import static java.util.concurrent.Executors.newScheduledThreadPool;
+import static java.util.concurrent.Executors.newSingleThreadExecutor;
+import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor;
import static org.apache.dubbo.common.constants.CommonConstants.APPLICATION_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.FILE_KEY;
import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
import static org.apache.dubbo.common.constants.CommonConstants.SIDE_KEY;
+import static org.apache.dubbo.common.utils.StringUtils.replace;
import static org.apache.dubbo.metadata.report.support.Constants.CYCLE_REPORT_KEY;
import static org.apache.dubbo.metadata.report.support.Constants.DEFAULT_METADATA_REPORT_CYCLE_REPORT;
import static org.apache.dubbo.metadata.report.support.Constants.DEFAULT_METADATA_REPORT_RETRY_PERIOD;
@@ -86,24 +90,52 @@ public abstract class AbstractMetadataReport implements MetadataReport {
// Log output
protected final Logger logger = LoggerFactory.getLogger(getClass());
- // Local disk cache, where the special key value.registries records the list of metadata centers, and the others are the list of notified service providers
- final Properties properties = new Properties();
- private final ExecutorService reportCacheExecutor = Executors.newFixedThreadPool(1, new NamedThreadFactory("DubboSaveMetadataReport", true));
+ private final AtomicBoolean initialized = new AtomicBoolean(false);
+
final Map<MetadataIdentifier, Object> allMetadataReports = new ConcurrentHashMap<>(4);
- private final AtomicLong lastCacheChanged = new AtomicLong();
final Map<MetadataIdentifier, Object> failedReports = new ConcurrentHashMap<>(4);
+
private URL reportURL;
boolean syncReport;
+
// Local disk cache file
- File file;
- private AtomicBoolean initialized = new AtomicBoolean(false);
- public MetadataReportRetry metadataReportRetry;
+ File localCacheFile;
+ // Local disk cache, where the special key value.registries records the list of metadata centers, and the others are the list of notified service providers
+ final Properties properties = new Properties();
+
+ private final AtomicLong lastCacheChanged = new AtomicLong();
+
+ // ThreadPoolExecutors
+ private final ExecutorService reportCacheExecutor;
+
+ public final MetadataReportRetry metadataReportRetry;
+
+ private final ScheduledExecutorService cycleReportExecutor;
public AbstractMetadataReport(URL reportServerURL) {
setUrl(reportServerURL);
+
+ this.localCacheFile = initializeLocalCacheFile(reportServerURL);
+ loadProperties();
+ syncReport = reportServerURL.getParameter(SYNC_REPORT_KEY, false);
+ metadataReportRetry = new MetadataReportRetry(reportServerURL.getParameter(RETRY_TIMES_KEY, DEFAULT_METADATA_REPORT_RETRY_TIMES),
+ reportServerURL.getParameter(RETRY_PERIOD_KEY, DEFAULT_METADATA_REPORT_RETRY_PERIOD));
+ this.reportCacheExecutor = newSingleThreadExecutor(new NamedThreadFactory("DubboSaveMetadataReport", true));
+ this.cycleReportExecutor = newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboMetadataReportTimer", true));
+ // cycle report the data switch
+ if (reportServerURL.getParameter(CYCLE_REPORT_KEY, DEFAULT_METADATA_REPORT_CYCLE_REPORT)) {
+ cycleReportExecutor.scheduleAtFixedRate(this::publishAll, calculateStartTime(), ONE_DAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
+ }
+ }
+
+ private File initializeLocalCacheFile(URL reportServerURL) {
// Start file save timer
- String defaultFilename = System.getProperty("user.home") + "/.dubbo/dubbo-metadata-" + reportServerURL.getParameter(APPLICATION_KEY) + "-" + reportServerURL.getAddress().replaceAll(":", "-") + ".cache";
+ String defaultFilename = System.getProperty("user.home") +
+ "/.dubbo/dubbo-metadata-" +
+ reportServerURL.getParameter(APPLICATION_KEY) + "-" +
+ replace(reportServerURL.getAddress(), ":", "-") +
+ ".cache";
String filename = reportServerURL.getParameter(FILE_KEY, defaultFilename);
File file = null;
if (ConfigUtils.isNotEmpty(filename)) {
@@ -118,16 +150,7 @@ public abstract class AbstractMetadataReport implements MetadataReport {
file.delete();
}
}
- this.file = file;
- loadProperties();
- syncReport = reportServerURL.getParameter(SYNC_REPORT_KEY, false);
- metadataReportRetry = new MetadataReportRetry(reportServerURL.getParameter(RETRY_TIMES_KEY, DEFAULT_METADATA_REPORT_RETRY_TIMES),
- reportServerURL.getParameter(RETRY_PERIOD_KEY, DEFAULT_METADATA_REPORT_RETRY_PERIOD));
- // cycle report the data switch
- if (reportServerURL.getParameter(CYCLE_REPORT_KEY, DEFAULT_METADATA_REPORT_CYCLE_REPORT)) {
- ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboMetadataReportTimer", true));
- scheduler.scheduleAtFixedRate(this::publishAll, calculateStartTime(), ONE_DAY_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
- }
+ return file;
}
public URL getUrl() {
@@ -145,12 +168,12 @@ public abstract class AbstractMetadataReport implements MetadataReport {
if (version < lastCacheChanged.get()) {
return;
}
- if (file == null) {
+ if (localCacheFile == null) {
return;
}
// Save
try {
- File lockfile = new File(file.getAbsolutePath() + ".lock");
+ File lockfile = new File(localCacheFile.getAbsolutePath() + ".lock");
if (!lockfile.exists()) {
lockfile.createNewFile();
}
@@ -158,14 +181,14 @@ public abstract class AbstractMetadataReport implements MetadataReport {
FileChannel channel = raf.getChannel()) {
FileLock lock = channel.tryLock();
if (lock == null) {
- throw new IOException("Can not lock the metadataReport cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.metadata.file=xxx.properties");
+ throw new IOException("Can not lock the metadataReport cache file " + localCacheFile.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.metadata.file=xxx.properties");
}
// Save
try {
- if (!file.exists()) {
- file.createNewFile();
+ if (!localCacheFile.exists()) {
+ localCacheFile.createNewFile();
}
- try (FileOutputStream outputFile = new FileOutputStream(file)) {
+ try (FileOutputStream outputFile = new FileOutputStream(localCacheFile)) {
properties.store(outputFile, "Dubbo metadataReport Cache");
}
} finally {
@@ -183,20 +206,20 @@ public abstract class AbstractMetadataReport implements MetadataReport {
}
void loadProperties() {
- if (file != null && file.exists()) {
- try (InputStream in = new FileInputStream(file)) {
+ if (localCacheFile != null && localCacheFile.exists()) {
+ try (InputStream in = new FileInputStream(localCacheFile)) {
properties.load(in);
if (logger.isInfoEnabled()) {
- logger.info("Load service store file " + file + ", data: " + properties);
+ logger.info("Load service store file " + localCacheFile + ", data: " + properties);
}
} catch (Throwable e) {
- logger.warn("Failed to load service store file " + file, e);
+ logger.warn("Failed to load service store file " + localCacheFile, e);
}
}
}
private void saveProperties(MetadataIdentifier metadataIdentifier, String value, boolean add, boolean sync) {
- if (file == null) {
+ if (localCacheFile == null) {
return;
}
@@ -318,7 +341,7 @@ public abstract class AbstractMetadataReport implements MetadataReport {
}
@Override
- public void saveSubscribedData(SubscriberMetadataIdentifier subscriberMetadataIdentifier, Set<String> urls) {
+ public void saveSubscribedData(SubscriberMetadataIdentifier subscriberMetadataIdentifier, Collection<String> urls) {
if (syncReport) {
doSaveSubscriberData(subscriberMetadataIdentifier, new Gson().toJson(urls));
} else {
@@ -328,7 +351,7 @@ public abstract class AbstractMetadataReport implements MetadataReport {
@Override
- public List<String> getSubscribedURLs(SubscriberMetadataIdentifier subscriberMetadataIdentifier) {
+ public Set<String> getSubscribedURLs(SubscriberMetadataIdentifier subscriberMetadataIdentifier) {
String content = doGetSubscribedURLs(subscriberMetadataIdentifier);
Type setType = new TypeToken<SortedSet<String>>() {
}.getType();
@@ -392,7 +415,7 @@ public abstract class AbstractMetadataReport implements MetadataReport {
class MetadataReportRetry {
protected final Logger logger = LoggerFactory.getLogger(getClass());
- final ScheduledExecutorService retryExecutor = Executors.newScheduledThreadPool(0, new NamedThreadFactory("DubboMetadataReportRetryTimer", true));
+ final ScheduledExecutorService retryExecutor = newScheduledThreadPool(0, new NamedThreadFactory("DubboMetadataReportRetryTimer", true));
volatile ScheduledFuture retryScheduledFuture;
final AtomicInteger retryCounter = new AtomicInteger(0);
// retry task schedule period
@@ -435,8 +458,10 @@ public abstract class AbstractMetadataReport implements MetadataReport {
}
void cancelRetryTask() {
- retryScheduledFuture.cancel(false);
- retryExecutor.shutdown();
+ if (retryScheduledFuture != null) {
+ retryScheduledFuture.cancel(false);
+ }
+ shutdown(retryExecutor);
}
}
@@ -451,6 +476,13 @@ public abstract class AbstractMetadataReport implements MetadataReport {
doSaveSubscriberData(subscriberMetadataIdentifier, encodedUrlList);
}
+ @Override
+ public final void close() throws Exception {
+ this.shutdownThreadPoolExecutors();
+ this.clearCache();
+ doClose();
+ }
+
protected abstract void doStoreProviderMetadata(MetadataIdentifier providerMetadataIdentifier, String serviceDefinitions);
protected abstract void doStoreConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, String serviceParameterString);
@@ -465,4 +497,35 @@ public abstract class AbstractMetadataReport implements MetadataReport {
protected abstract String doGetSubscribedURLs(SubscriberMetadataIdentifier subscriberMetadataIdentifier);
+ /**
+ * Close other resources
+ *
+ * @since 2.7.8
+ */
+ protected void doClose() throws Exception {
+
+ }
+
+ private void clearCache() {
+ this.properties.clear();
+ this.allMetadataReports.clear();
+ this.failedReports.clear();
+ this.localCacheFile.delete();
+ }
+
+ private void shutdownThreadPoolExecutors() {
+ this.metadataReportRetry.cancelRetryTask();
+ shutdown(this.reportCacheExecutor);
+ shutdown(cycleReportExecutor);
+ }
+
+ private static void shutdown(ExecutorService executorService) {
+ if (executorService == null) {
+ return;
+ }
+ if (!executorService.isShutdown()) {
+ executorService.shutdown();
+ }
+ }
+
}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReport.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReport.java
new file mode 100644
index 0000000..d962ca5
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReport.java
@@ -0,0 +1,162 @@
+/*
+ * 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.metadata.report.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.identifier.BaseMetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.ServiceMetadataIdentifier;
+import org.apache.dubbo.metadata.report.identifier.SubscriberMetadataIdentifier;
+
+import java.util.List;
+
+import static org.apache.dubbo.common.config.configcenter.DynamicConfigurationFactory.getDynamicConfigurationFactory;
+import static org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
+import static org.apache.dubbo.metadata.MetadataConstants.EXPORTED_URLS_TAG;
+
+/**
+ * The generic implementation of {@link MetadataReport} based on {@link DynamicConfiguration
+ * the config-center infrastructure}
+ *
+ * @see AbstractMetadataReport
+ * @since 2.7.8
+ */
+public class ConfigCenterBasedMetadataReport extends AbstractMetadataReport {
+
+ private final KeyTypeEnum keyType;
+
+ private final String group;
+
+ private final DynamicConfiguration dynamicConfiguration;
+
+ public ConfigCenterBasedMetadataReport(URL reportServerURL, KeyTypeEnum keyTypeEnum) {
+ super(reportServerURL);
+ this.keyType = keyTypeEnum;
+ this.group = reportServerURL.getParameter(GROUP_KEY, DEFAULT_ROOT);
+ String extensionName = reportServerURL.getProtocol();
+ DynamicConfigurationFactory dynamicConfigurationFactory = getDynamicConfigurationFactory(extensionName);
+ dynamicConfiguration = dynamicConfigurationFactory.getDynamicConfiguration(reportServerURL);
+ }
+
+
+ @Override
+ protected void doStoreProviderMetadata(MetadataIdentifier providerMetadataIdentifier, String serviceDefinitions) {
+ saveMetadata(providerMetadataIdentifier, serviceDefinitions);
+ }
+
+ @Override
+ protected void doStoreConsumerMetadata(MetadataIdentifier consumerMetadataIdentifier, String serviceParameterString) {
+ saveMetadata(consumerMetadataIdentifier, serviceParameterString);
+ }
+
+ @Override
+ protected void doSaveMetadata(ServiceMetadataIdentifier metadataIdentifier, URL url) {
+ saveMetadata(metadataIdentifier, URL.encode(url.toFullString()));
+ }
+
+ @Override
+ protected void doRemoveMetadata(ServiceMetadataIdentifier metadataIdentifier) {
+ removeMetadata(metadataIdentifier);
+ }
+
+ @Override
+ protected List<String> doGetExportedURLs(ServiceMetadataIdentifier metadataIdentifier) {
+ throw new UnsupportedOperationException("doGetExportedURLs method will not be supported!");
+ }
+
+ @Override
+ protected void doSaveSubscriberData(SubscriberMetadataIdentifier subscriberMetadataIdentifier, String urlListStr) {
+ saveMetadata(subscriberMetadataIdentifier, urlListStr);
+ }
+
+ @Override
+ protected String doGetSubscribedURLs(SubscriberMetadataIdentifier subscriberMetadataIdentifier) {
+ return getMetadata(subscriberMetadataIdentifier);
+ }
+
+ @Override
+ public String getServiceDefinition(MetadataIdentifier metadataIdentifier) {
+ return getMetadata(metadataIdentifier);
+ }
+
+ @Override
+ public boolean saveExportedURLs(String serviceName, String exportedServicesRevision, String exportedURLsContent) {
+ String key = buildExportedURLsMetadataKey(serviceName, exportedServicesRevision);
+ return dynamicConfiguration.publishConfig(key, group, exportedURLsContent);
+ }
+
+ @Override
+ public String getExportedURLsContent(String serviceName, String exportedServicesRevision) {
+ String key = buildExportedURLsMetadataKey(serviceName, exportedServicesRevision);
+ return dynamicConfiguration.getConfig(key, group);
+ }
+
+ private String buildExportedURLsMetadataKey(String serviceName, String exportedServicesRevision) {
+ return keyType.build(EXPORTED_URLS_TAG, serviceName, exportedServicesRevision);
+ }
+
+ protected void saveMetadata(BaseMetadataIdentifier metadataIdentifier, String value) {
+ String key = getKey(metadataIdentifier);
+ dynamicConfiguration.publishConfig(key, group, value);
+ }
+
+ protected void saveMetadata(MetadataIdentifier metadataIdentifier, String value) {
+ String key = getKey(metadataIdentifier);
+ dynamicConfiguration.publishConfig(key, group, value);
+ }
+
+ protected String getMetadata(ServiceMetadataIdentifier metadataIdentifier) {
+ String key = getKey(metadataIdentifier);
+ return dynamicConfiguration.getConfig(key, group);
+ }
+
+ protected String getMetadata(MetadataIdentifier metadataIdentifier) {
+ String key = getKey(metadataIdentifier);
+ return dynamicConfiguration.getConfig(key, group);
+ }
+
+ protected String getMetadata(SubscriberMetadataIdentifier metadataIdentifier) {
+ String key = getKey(metadataIdentifier);
+ return dynamicConfiguration.getConfig(key, group);
+ }
+
+ protected void removeMetadata(MetadataIdentifier metadataIdentifier) {
+ String key = getKey(metadataIdentifier);
+ dynamicConfiguration.removeConfig(key, group);
+ }
+
+ protected void removeMetadata(ServiceMetadataIdentifier metadataIdentifier) {
+ String key = getKey(metadataIdentifier);
+ dynamicConfiguration.removeConfig(key, group);
+ }
+
+ protected String getKey(BaseMetadataIdentifier metadataIdentifier) {
+ return metadataIdentifier.getUniqueKey(keyType);
+ }
+
+ protected String getKey(MetadataIdentifier metadataIdentifier) {
+ return metadataIdentifier.getUniqueKey(keyType);
+ }
+
+ protected void doClose() throws Exception {
+ this.dynamicConfiguration.close();
+ }
+}
diff --git a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReportFactory.java b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReportFactory.java
new file mode 100644
index 0000000..5b0f780
--- /dev/null
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/ConfigCenterBasedMetadataReportFactory.java
@@ -0,0 +1,86 @@
+/*
+ * 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.metadata.report.support;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+import org.apache.dubbo.metadata.report.MetadataReport;
+import org.apache.dubbo.metadata.report.MetadataReportFactory;
+import org.apache.dubbo.metadata.report.identifier.KeyTypeEnum;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static org.apache.dubbo.common.config.configcenter.TreePathDynamicConfiguration.CONFIG_BASE_PATH_PARAM_NAME;
+import static org.apache.dubbo.metadata.MetadataConstants.DEFAULT_PATH_TAG;
+import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
+
+/**
+ * The abstract implementation of {@link MetadataReportFactory} based on
+ * {@link DynamicConfiguration the config-center infrastructure}
+ *
+ * @see MetadataReportFactory
+ * @see MetadataReport
+ * @see DynamicConfiguration
+ * @since 2.7.8
+ */
+public abstract class ConfigCenterBasedMetadataReportFactory implements MetadataReportFactory {
+
+ /**
+ * org.apache.dubbo.metadata.report.MetadataReport
+ */
+ private static final String URL_PATH = MetadataReport.class.getName();
... 5020 lines suppressed ...