You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@dubbo.apache.org by li...@apache.org on 2019/07/27 07:50:48 UTC
[dubbo] 01/04: Merge branch 'master' into cloud-native
This is an automated email from the ASF dual-hosted git repository.
liujun pushed a commit to branch cloud-native
in repository https://gitbox.apache.org/repos/asf/dubbo.git
commit c5dd1ea581622f03038255a43a4f808707afe5f2
Merge: fe562c3 f2af6fd
Author: ken.lj <ke...@gmail.com>
AuthorDate: Sat Jul 27 08:46:57 2019 +0800
Merge branch 'master' into cloud-native
# Conflicts:
# dubbo-all/pom.xml
# dubbo-bom/pom.xml
# dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/AbstractInterfaceConfig.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ConfigCenterConfig.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
# dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
# dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
# dubbo-configcenter/dubbo-configcenter-api/src/test/java/org/apache/dubbo/configcenter/mock/MockDynamicConfiguration.java
# dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
# dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
# dubbo-configcenter/dubbo-configcenter-nacos/src/main/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfiguration.java
# dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
# dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
# dubbo-metadata-report/dubbo-metadata-definition-protobuf/src/main/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilder.java
# dubbo-metadata-report/dubbo-metadata-definition-protobuf/src/test/java/org/apache/dubbo/metadata/definition/protobuf/ProtobufTypeBuilderTest.java
# dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
# dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
# dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/support/AbstractMetadataReport.java
# dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
# dubbo-metadata/pom.xml
# dubbo-registry/dubbo-registry-api/src/main/java/org/apache/dubbo/registry/integration/AbstractConfiguratorListener.java
# dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistry.java
# dubbo-registry/dubbo-registry-nacos/src/main/java/org/apache/dubbo/registry/nacos/NacosRegistryFactory.java
# dubbo-rpc/dubbo-rpc-xml/src/main/java/org/apache/dubbo/xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java
.travis.yml | 2 -
CHANGES.md | 140 ++
DISCLAIMER | 1 -
Jenkinsfile | 138 ++
README.md | 4 +-
dubbo-all/pom.xml | 7 +-
dubbo-bom/pom.xml | 9 +-
.../rpc/cluster/loadbalance/RandomLoadBalance.java | 15 +-
.../router/condition/config/ListenableRouter.java | 2 +-
.../router/condition/config/ServiceRouter.java | 2 +-
.../dubbo/rpc/cluster/router/tag/TagRouter.java | 2 +-
.../cluster/router/tag/model/TagRouterRule.java | 8 +-
.../dubbo/rpc/cluster/support/ClusterUtils.java | 51 +-
.../support/wrapper/MockClusterInvoker.java | 13 +-
.../org/apache/dubbo/rpc/cluster/StickyTest.java | 4 +-
.../dubbo/rpc/cluster/merger/ResultMergerTest.java | 18 +-
.../dubbo/rpc/cluster/router/TagRouterTest.java | 45 +
.../router/condition/ConditionRouterTest.java | 131 +-
.../support/AbstractClusterInvokerTest.java | 21 +-
.../rpc/cluster/support/ClusterUtilsTest.java | 72 +
.../support/FailoverClusterInvokerTest.java | 2 +-
.../dubbo/rpc/cluster/support/MenuService.java | 4 +-
.../support/wrapper/MockClusterInvokerTest.java | 38 +-
.../wrapper/MockProviderRpcExceptionTest.java | 238 +++
.../src/main/java/org/apache/dubbo/common/URL.java | 144 +-
.../main/java/org/apache/dubbo/common/Version.java | 19 +-
.../common/beanutil/JavaBeanSerializeUtil.java | 4 +-
.../org/apache/dubbo/common/bytecode/Proxy.java | 5 +-
.../dubbo/common/compiler/support/JdkCompiler.java | 2 +-
.../common/config/AbstractPrefixConfiguration.java | 17 +-
.../apache/dubbo/common/config/Environment.java | 1 +
.../common/config/EnvironmentConfiguration.java | 8 +-
.../config/configcenter/DynamicConfiguration.java | 44 +-
.../configcenter/nop/NopDynamicConfiguration.java | 4 +-
.../dubbo/common/constants/CommonConstants.java | 17 +-
.../dubbo/common/constants/QosConstants.java | 12 +-
.../extension/AdaptiveClassCodeGenerator.java | 765 ++++-----
.../dubbo/common/extension/ExtensionLoader.java | 19 +-
.../extension/support/ActivateComparator.java | 2 +-
.../java/org/apache/dubbo/common/io/Bytes.java | 10 +
.../org/apache/dubbo/common/json/JSONArray.java | 10 +-
.../org/apache/dubbo/common/json/JSONObject.java | 10 +-
.../org/apache/dubbo/common/json/JSONVisitor.java | 2 +-
.../dubbo/common/utils/CompatibleTypeUtils.java | 2 +
.../org/apache/dubbo/common/utils/IOUtils.java | 22 +-
.../org/apache/dubbo/common/utils/MethodUtils.java | 23 +
.../org/apache/dubbo/common/utils/NetUtils.java | 28 +-
.../org/apache/dubbo/common/utils/PojoUtils.java | 7 +-
.../org/apache/dubbo/common/utils/StringUtils.java | 32 +
.../org/apache/dubbo/common/utils/UrlUtils.java | 1 +
.../test/java/org/apache/dubbo/common/URLTest.java | 27 +-
.../common/beanutil/JavaBeanSerializeUtilTest.java | 14 +-
.../apache/dubbo/common/bytecode/MixinTest.java | 7 +-
.../apache/dubbo/common/bytecode/ProxyTest.java | 6 +-
.../apache/dubbo/common/bytecode/WrapperTest.java | 20 +-
.../common/compiler/support/ClassUtilsTest.java | 2 +-
.../config/EnvironmentConfigurationTest.java | 104 ++
.../common/config/InmemoryConfigurationTest.java | 95 ++
.../common/config/SystemConfigurationTest.java | 117 ++
.../common/extension/ExtensionLoaderTest.java | 30 +-
.../ext10_multi_names/Ext10MultiNames.java | 10 +-
.../impl/Ext10MultiNamesImpl.java} | 6 +-
.../dubbo/common/extension/ext6_inject/Dao.java | 2 +-
.../extension/support/ActivateComparatorTest.java | 1 -
.../java/org/apache/dubbo/common/io/BytesTest.java | 14 +
.../org/apache/dubbo/common/json/JSONTest.java | 6 +-
.../threadlocal/InternalThreadLocalTest.java | 29 +-
.../NamedInternalThreadFactoryTest.java | 2 +-
.../support/eager/EagerThreadPoolExecutorTest.java | 8 +-
.../common/utils/CompatibleTypeUtilsTest.java | 2 +-
.../org/apache/dubbo/common/utils/IOUtilsTest.java | 3 +-
.../apache/dubbo/common/utils/MethodUtilsTest.java | 4 +-
.../apache/dubbo/common/utils/PojoUtilsTest.java | 1699 ++++++++++----------
.../dubbo/common/utils/ReflectUtilsTest.java | 2 +-
.../apache/dubbo/common/utils/StringUtilsTest.java | 14 +
.../apache/dubbo/common/version/VersionTest.java | 7 +
...mon.extension.ext10_multi_names.Ext10MultiNames | 1 +
.../spring/context/annotation/EnableDubbo.java | 12 +-
.../alibaba/dubbo/remoting/RemotingException.java | 4 +
.../dubbo/remoting/exchange/ResponseCallback.java | 23 +-
.../dubbo/remoting/exchange/ResponseFuture.java | 44 +-
.../main/java/com/alibaba/dubbo/rpc/Result.java | 4 +-
.../java/com/alibaba/dubbo/rpc/RpcContext.java | 24 +-
.../dubbo/rpc/protocol/dubbo/FutureAdapter.java | 147 ++
.../com/alibaba/dubbo/rpc/support/RpcUtils.java | 5 -
...atibleReferenceAnnotationBeanPostProcessor.java | 508 ------
.../annotation/CompatibleReferenceBeanBuilder.java | 167 --
...mpatibleServiceAnnotationBeanPostProcessor.java | 525 ------
.../annotation/CompatibleDubboComponentScan.java | 66 -
.../CompatibleDubboComponentScanRegistrar.java | 110 --
.../CompatibleAnnotationBeanDefinitionParser.java | 93 --
.../org/apache/dubbo/config/MethodConfigTest.java | 7 +-
.../java/org/apache/dubbo/rpc/RpcContextTest.java | 37 +-
.../org/apache/dubbo/service/ComplexObject.java | 2 +-
.../alibaba/dubbo/config/annotation/Reference.java | 0
.../alibaba/dubbo/config/annotation/Service.java | 0
.../org/apache/dubbo/config/AbstractConfig.java | 40 +-
.../org/apache/dubbo/config/ApplicationConfig.java | 80 +-
.../apache/dubbo/config/ConfigCenterConfig.java | 22 +-
.../org/apache/dubbo/config/ReferenceConfig.java | 2 +-
.../org/apache/dubbo/config/RegistryConfig.java | 16 +
.../org/apache/dubbo/config/ServiceConfig.java | 2 +-
.../apache/dubbo/config/annotation/Reference.java | 25 +-
.../config/context/ConfigConfigurationAdapter.java | 21 +-
.../dubbo/config/telnet/ShutdownTelnetHandler.java | 2 +-
.../dubbo/config/utils/ReferenceConfigCache.java | 2 +-
.../apache/dubbo/config/AbstractConfigTest.java | 77 +
.../apache/dubbo/config/ApplicationConfigTest.java | 34 +
.../dubbo/config/ConfigCenterConfigTest.java | 14 +
.../apache/dubbo/config/ReferenceConfigTest.java | 14 +-
.../apache/dubbo/config/RegistryConfigTest.java | 10 +
.../dubbo/config/validation/ValidationTest.java | 2 +-
dubbo-config/dubbo-config-spring/pom.xml | 1 +
.../AbstractAnnotationConfigBeanBuilder.java | 3 +
.../AnnotatedInterfaceConfigBeanBuilder.java | 215 +++
.../AnnotationInjectedBeanPostProcessor.java | 135 +-
.../AnnotationPropertyValuesAdapter.java | 39 +-
.../ReferenceAnnotationBeanPostProcessor.java | 122 +-
.../factory/annotation/ReferenceBeanBuilder.java | 84 +-
.../ServiceAnnotationBeanPostProcessor.java | 126 +-
.../factory/annotation/ServiceBeanNameBuilder.java | 43 +-
.../annotation/DubboConfigConfiguration.java | 7 +-
.../spring/schema/DubboBeanDefinitionParser.java | 2 +-
.../util/AnnotatedBeanDefinitionRegistryUtils.java | 64 +-
.../dubbo/config/spring/util/AnnotationUtils.java | 179 ++-
.../dubbo/config/spring/util/BeanFactoryUtils.java | 6 +
.../config/spring/SimpleRegistryExporter.java | 4 +-
.../spring/annotation/merged/MergedReference.java | 34 +-
.../merged/MergedService.java} | 33 +-
.../AnnotationPropertyValuesAdapterTest.java | 10 +-
.../factory/annotation/MergedAnnotationTest.java | 76 +
.../ReferenceAnnotationBeanPostProcessorTest.java | 60 +-
.../annotation/ReferenceBeanBuilderTest.java | 2 +-
.../spring/context/annotation/EnableDubboTest.java | 5 +
.../annotation/consumer/ConsumerConfiguration.java | 22 +-
.../consumer/test/TestConsumerConfiguration.java | 18 +-
.../annotation/provider/HelloServiceImpl.java | 3 +-
.../DubboComponentScanRegistrarTest.java | 2 +
.../annotation/provider/DefaultHelloService.java | 4 +-
.../annotation/provider/ProviderConfiguration.java | 4 +-
.../AnnotatedBeanDefinitionRegistryUtilsTest.java | 74 +
.../support/apollo/ApolloDynamicConfiguration.java | 10 +-
.../consul/ConsulDynamicConfiguration.java | 38 +-
.../support/etcd/EtcdDynamicConfiguration.java | 27 +-
.../support/etcd/EtcdDynamicConfigurationTest.java | 5 +-
.../support/nacos/NacosDynamicConfiguration.java | 65 +-
.../nacos/NacosDynamicConfigurationTest.java | 55 +-
.../support/zookeeper/CacheListener.java | 13 +-
.../zookeeper/ZookeeperDynamicConfiguration.java | 46 +-
.../ZookeeperDynamicConfigurationTest.java | 29 +-
dubbo-demo/README.md | 4 +-
.../dubbo-demo-annotation-consumer/pom.xml | 24 +
.../dubbo-demo-annotation-provider/pom.xml | 24 +
.../dubbo-demo-xml/dubbo-demo-xml-consumer/pom.xml | 24 +
.../dubbo-demo-xml/dubbo-demo-xml-provider/pom.xml | 24 +
dubbo-dependencies-bom/pom.xml | 15 +-
.../dubbo/cache/support/expiring/ExpiringMap.java | 5 +-
.../apache/dubbo/cache/filter/CacheFilterTest.java | 4 +-
.../support/jvalidation/JValidationTest.java | 1 -
.../jvalidation/mock/JValidatorTestTarget.java | 10 +-
.../dubbo-metadata-definition-protobuf}/pom.xml | 40 +-
...e.dubbo.metadata.definition.builder.TypeBuilder | 1 +
.../definition/protobuf}/model/GooglePB.java | 2 +-
.../protobuf/model/ServiceInterface.java | 7 +-
.../metadata/definition/TypeDefinitionBuilder.java | 18 +-
.../definition/model/MethodDefinition.java | 18 +-
.../metadata/definition/model/TypeDefinition.java | 9 +
.../report/identifier/MetadataIdentifier.java | 10 +-
.../report/support/AbstractMetadataReport.java | 4 +-
.../dubbo/metadata/definition/MetadataTest.java | 10 +-
.../metadata/definition/common/ColorEnum.java | 2 +-
.../metadata/definition/service/ComplexObject.java | 2 +-
.../report/identifier/MetadataIdentifierTest.java | 11 +-
.../report/support/AbstractMetadataReportTest.java | 8 +-
.../metadata/store/InterfaceNameTestService2.java | 2 +-
.../store/etcd/EtcdMetadataReportTest.java | 2 +
.../metadata/store/nacos/NacosMetadataReport.java | 12 +-
.../store/nacos/NacosMetadataReportTest.java | 8 +-
.../metadata/store/redis/RedisMetadataReport.java | 4 +-
dubbo-metadata/pom.xml | 2 +
.../dubbo/monitor/support/MonitorFilterTest.java | 24 +-
.../dubbo/monitor/dubbo/AppResponseBuilder.java | 55 +
.../dubbo/monitor/dubbo/MetricsFilterTest.java | 80 +-
.../dubbo/qos/command/util/CommandHelperTest.java | 1 -
.../integration/AbstractConfiguratorListener.java | 7 +-
.../registry/integration/RegistryDirectory.java | 2 +-
.../registry/integration/RegistryProtocol.java | 4 +-
.../dubbo/registry/PerformanceRegistryTest.java | 1 -
.../java/org/apache/dubbo/registry/ZKTools.java | 3 +-
.../registry/support/AbstractRegistryTest.java | 2 +-
.../registry/support/FailbackRegistryTest.java | 4 +-
.../dubbo/registry/consul/ConsulRegistry.java | 30 +-
.../registry/dubbo/RegistryDirectoryTest.java | 64 +-
.../dubbo/registry/dubbo/RegistryProtocolTest.java | 11 +-
.../registry/dubbo/SimpleRegistryExporter.java | 4 +-
.../dubbo/registry/etcd/EtcdRegistryTest.java | 30 +-
.../registry/multicast/MulticastRegistry.java | 4 +-
.../multiple/MultipleRegistry2S2RTest.java | 30 +-
.../apache/dubbo/registry/nacos/NacosRegistry.java | 86 +-
.../dubbo/registry/nacos/NacosServiceName.java | 244 +++
.../consumer/DemoServiceConsumerXmlBootstrap.java | 10 +-
.../dubbo/registry/nacos/NacosServiceNameTest.java | 123 ++
.../META-INF/spring/dubbo-consumer-context.xml | 14 +-
.../META-INF/spring/dubbo-provider-context.xml | 3 +-
.../java/org/apache/dubbo/remoting/Constants.java | 6 +-
.../dubbo/remoting/buffer/ChannelBuffer.java | 2 +-
.../support/command/StatusTelnetHandler.java | 2 +-
.../dispatcher/WrappedChannelHandler.java | 7 +-
.../org/apache/dubbo/remoting/utils/UrlUtils.java | 1 +
.../apache/dubbo/remoting/RpcMessageHandler.java | 2 +-
.../dubbo/remoting/codec/ExchangeCodecTest.java | 32 +-
.../handler/ConnectChannelHandlerTest.java | 2 +-
.../handler/HeaderExchangeHandlerTest.java | 2 +-
.../handler/WrappedChannelHandlerTest.java | 2 -
.../remoting/transport/AbstractCodecTest.java | 5 +-
.../org/apache/dubbo/remoting/etcd/EtcdClient.java | 2 +-
.../apache/dubbo/remoting/etcd/RetryPolicy.java | 2 +-
.../dubbo/remoting/etcd/jetcd/JEtcdClient.java | 13 +-
.../dubbo/remoting/etcd/jetcd/JEtcdClientTest.java | 4 +-
.../remoting/transport/netty/NettyHelper.java | 2 +-
.../support/header/HeartbeatHandlerTest.java | 4 +-
.../transport/netty/ClientReconnectTest.java | 8 +-
.../remoting/transport/netty4/NettyChannel.java | 48 +-
.../remoting/transport/netty4/NettyClient.java | 42 +-
.../transport/netty4/NettyClientHandler.java | 1 +
.../remoting/transport/netty4/NettyServer.java | 26 +-
.../transport/netty4/NettyServerHandler.java | 10 +-
.../transport/netty4/NettyTransporter.java | 3 +
.../transport/netty4/ClientReconnectTest.java | 8 +-
.../zookeeper/curator/CuratorZookeeperClient.java | 8 +-
.../curator/CuratorZookeeperClientTest.java | 7 +-
.../curator/CuratorZookeeperTransporterTest.java | 1 -
.../java/org/apache/dubbo/rpc/AppResponse.java | 4 +-
.../org/apache/dubbo/rpc/AsyncContextImpl.java | 4 -
.../java/org/apache/dubbo/rpc/AsyncRpcResult.java | 91 +-
.../main/java/org/apache/dubbo/rpc/Constants.java | 4 -
.../java/org/apache/dubbo/rpc/FutureContext.java | 64 +-
.../main/java/org/apache/dubbo/rpc/InvokeMode.java | 2 +-
.../src/main/java/org/apache/dubbo/rpc/Result.java | 6 +-
.../main/java/org/apache/dubbo/rpc/RpcContext.java | 7 +-
.../java/org/apache/dubbo/rpc/RpcException.java | 7 +
.../java/org/apache/dubbo/rpc/RpcInvocation.java | 2 +-
.../apache/dubbo/rpc/filter/AccessLogFilter.java | 8 +-
.../apache/dubbo/rpc/filter/ActiveLimitFilter.java | 18 +-
.../dubbo/rpc/filter/ExecuteLimitFilter.java | 13 +-
.../rpc/model/invoker/ProviderInvokerWrapper.java | 2 +-
.../dubbo/rpc/protocol/AsyncToSyncInvoker.java | 6 +-
.../dubbo/rpc/protocol/ProtocolFilterWrapper.java | 17 +-
.../dubbo/rpc/protocol/dubbo/FutureAdapter.java | 3 +
.../dubbo/rpc/proxy/AbstractProxyInvoker.java | 6 +-
.../org/apache/dubbo/rpc/support/RpcUtils.java | 18 +-
.../java/org/apache/dubbo/rpc/AppResponseTest.java | 4 +-
.../org/apache/dubbo/rpc/FutureContextTest.java | 53 +
.../java/org/apache/dubbo/rpc/RpcContextTest.java | 8 +-
.../dubbo/rpc/filter/AccessLogFilterTest.java | 20 +-
.../rpc/filter/ConsumerContextFilterTest.java | 3 +-
.../apache/dubbo/rpc/filter/tps/StatItemTest.java | 4 +-
.../apache/dubbo/rpc/support/MockInvokerTest.java | 139 ++
.../org/apache/dubbo/rpc/support/RpcUtilsTest.java | 8 +-
.../rpc/protocol/dubbo/CallbackServiceCodec.java | 4 +-
.../dubbo/rpc/protocol/dubbo/DubboCodec.java | 6 +-
.../dubbo/rpc/protocol/dubbo/DubboInvoker.java | 17 +-
.../protocol/dubbo/telnet/ChangeTelnetHandler.java | 2 +-
.../protocol/dubbo/DubboInvokerAvilableTest.java | 18 +-
.../rpc/protocol/dubbo/DubboProtocolTest.java | 36 +-
.../rpc/protocol/dubbo/ExplicitCallbackTest.java | 12 +-
.../dubbo/rpc/protocol/dubbo/IDemoService.java | 2 +-
.../rpc/protocol/dubbo/ImplicitCallBackTest.java | 22 +-
.../dubbo/ReferenceCountExchangeClientTest.java | 12 +-
.../dubbo/decode/DubboTelnetDecodeTest.java | 2 +-
.../dubbo/telnet/CurrentTelnetHandlerTest.java | 1 -
.../rpc/protocol/hessian/HessianProtocol.java | 2 +-
.../dubbo/rpc/protocol/http/HttpProtocol.java | 2 +-
.../dubbo/rpc/protocol/http/HttpProtocolTest.java | 2 +-
.../rpc/protocol/jsonrpc/JsonRpcProtocol.java | 4 +-
.../rpc/protocol/nativethrift/DemoService.java | 24 +-
.../rpc/protocol/nativethrift/UserService.java | 4 +-
.../dubbo/rpc/protocol/rest/RestProtocol.java | 1 +
.../integration/swagger/DubboSwaggerService.java | 4 +-
.../rpc/protocol/rest/support/LoggingFilter.java | 5 +-
.../DubboSwaggerApiListingResourceTest.java | 2 -
.../dubbo/rpc/protocol/rmi/RmiProtocolTest.java | 7 +-
.../rpc/protocol/thrift/ClassNameGenerator.java | 4 +-
.../dubbo/rpc/protocol/thrift/ThriftInvoker.java | 6 +-
.../src/test/java/ClassNameTestDubbo.java | 2 +-
.../src/test/java/ClassNameTestThrift.java | 4 +-
.../java/org/apache/dubbo/rpc/gen/dubbo/Demo.java | 14 +-
.../java/org/apache/dubbo/rpc/gen/thrift/Demo.java | 30 +-
.../dubbo/rpc/protocol/thrift/ThriftCodecTest.java | 2 +-
.../xml/rpc/protocol/xmlrpc/XmlRpcProtocol.java | 7 +-
.../protocol/xmlrpc/XmlRpcProxyFactoryBean.java | 2 +-
.../common/serialize/avro/AvroObjectInput.java | 3 +-
.../common/serialize/avro/AvroObjectOutput.java | 5 +-
.../support/GenericProtobufObjectInput.java | 37 +-
.../support/GenericProtobufObjectOutput.java | 42 +-
.../serialize/protobuf/support/MapValue.java | 830 ++++++++++
.../protostuff/delegate/SqlDateDelegate.java | 55 +
.../serialize/protostuff/utils/WrapperUtils.java | 3 +
.../serialize/base/AbstractSerializationTest.java | 8 +-
.../serialize/hessian2/Hessian2PersonOkTest.java | 1 -
.../dubbo/common/serialize/model/AnimalEnum.java | 2 +-
.../support/GenericProtobufObjectOutputTest.java | 122 +-
.../serialize/protobuf/support/model/GooglePB.java | 4 +-
.../protostuff/ProtostuffObjectOutputTest.java | 32 +
.../protostuff/ProtostuffSerializationTest.java | 1 -
.../support/SerializableClassRegistryTest.java | 1 -
pom.xml | 9 +-
307 files changed, 7221 insertions(+), 4327 deletions(-)
diff --cc dubbo-all/pom.xml
index 473de7e,cf26097..f9932a1
--- a/dubbo-all/pom.xml
+++ b/dubbo-all/pom.xml
@@@ -787,9 -761,13 +788,13 @@@
</resource>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
- <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.store.MetadataReportFactory
+ <resource>META-INF/dubbo/internal/org.apache.dubbo.registry.client.ServiceDiscoveryFactory
</resource>
</transformer>
+ <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
+ <resource>META-INF/dubbo/internal/org.apache.dubbo.metadata.definition.builder.TypeBuilder
+ </resource>
+ </transformer>
</transformers>
<filters>
<filter>
diff --cc dubbo-bom/pom.xml
index a98794f,5ab6604..175a9cf
--- a/dubbo-bom/pom.xml
+++ b/dubbo-bom/pom.xml
@@@ -425,6 -422,16 +425,11 @@@
<artifactId>dubbo-configcenter-nacos</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
- <groupId>org.apache.dubbo</groupId>
- <artifactId>dubbo-metadata-definition</artifactId>
- <version>${project.version}</version>
- </dependency>
- <dependency>
+ <groupId>org.apache.dubbo</groupId>
+ <artifactId>dubbo-metadata-definition-protobuf</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
diff --cc dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
index cf335b4,1880874..bb2b40b
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/bytecode/Proxy.java
@@@ -155,9 -155,12 +155,12 @@@ public abstract class Proxy
for (Method method : ics[i].getMethods()) {
String desc = ReflectUtils.getDesc(method);
- if (worked.contains(desc)) {
+ if (worked.contains(desc) || Modifier.isStatic(method.getModifiers())) {
continue;
}
+ if (ics[i].isInterface() && Modifier.isStatic(method.getModifiers())) {
+ continue;
+ }
worked.add(desc);
int ix = methods.size();
diff --cc dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/DynamicConfiguration.java
index f5bf9a4,357632c..239208f
--- 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
@@@ -14,8 -14,9 +14,9 @@@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.dubbo.configcenter;
+package org.apache.dubbo.common.config.configcenter;
+ import org.apache.dubbo.common.URL;
import org.apache.dubbo.common.config.Configuration;
import org.apache.dubbo.common.config.Environment;
@@@ -127,69 -111,12 +117,68 @@@ public interface DynamicConfiguration e
}
/**
- * {@see #getConfig(String, String, long)}
- * <p>
* This method are mostly used to get a compound config file, such as a complete dubbo.properties file.
+ * Also {@see #getConfig(String, String, long)}
*/
- String getConfigs(String key, String group, long timeout) throws IllegalStateException;
+ String getProperties(String key, String group, long timeout) throws IllegalStateException;
/**
+ * Publish Config mapped to the given key and the given group.
+ *
+ * @param key the key to represent a configuration
+ * @param group the group where the key belongs to
+ * @param content the content of configuration
+ * @return <code>true</code> if success, or <code>false</code>
+ * @throws UnsupportedOperationException If the under layer does not support
+ * @since 2.7.4
+ */
+ default boolean publishConfig(String key, String group, String content) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("No support");
+ }
+
+ /**
+ * Get the config keys by the specified group
+ *
+ * @param group the specified group
+ * @return the read-only non-null sorted {@link Set set} of config keys
+ * @throws UnsupportedOperationException If the under layer does not support
+ * @since 2.7.4
+ */
+ default SortedSet<String> getConfigKeys(String group) throws UnsupportedOperationException {
+ throw new UnsupportedOperationException("No support");
+ }
+
+ /**
+ * Get the {@link SortedMap} with with config keys and contents value by the specified group
+ *
+ * @param group the specified group
+ * @return the read-only non-null sorted {@link SortedMap map}
+ * @throws UnsupportedOperationException If the under layer does not support
+ * @since 2.7.4
+ */
+ default SortedMap<String, String> getConfigs(String group) throws UnsupportedOperationException {
+ return getConfigs(group, -1);
+ }
+
+ /**
+ * Get the {@link SortedMap} with with config keys and content value by the specified group
+ *
+ * @param group the specified group
+ * @param timeout the millisecond for timeout
+ * @return the read-only non-null sorted {@link SortedMap map}
+ * @throws UnsupportedOperationException If the under layer does not support
+ * @throws IllegalStateException If timeout exceeds
+ * @since 2.7.4
+ */
+ default SortedMap<String, String> getConfigs(String group, long timeout) throws UnsupportedOperationException,
+ IllegalStateException {
+ SortedMap<String, String> configs = new TreeMap<>();
+ SortedSet<String> configKeys = getConfigKeys(group);
+ configKeys.forEach(key -> configs.put(key, getConfig(key, group, timeout)));
+ return Collections.unmodifiableSortedMap(configs);
+ }
+
+ /**
* Find DynamicConfiguration instance
*
* @return DynamicConfiguration instance
diff --cc dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
index 14accb2,6316821..23a2544
--- a/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
+++ b/dubbo-common/src/main/java/org/apache/dubbo/common/config/configcenter/nop/NopDynamicConfiguration.java
@@@ -55,23 -52,7 +55,23 @@@ public class NopDynamicConfiguration im
}
@Override
- public String getConfigs(String key, String group, long timeout) throws IllegalStateException {
+ public String getProperties(String key, String group, long timeout) throws IllegalStateException {
return null;
}
+
+ /**
+ * @since 2.7.4
+ */
+ @Override
+ public boolean publishConfig(String key, String group, String content) {
+ return true;
+ }
+
+ /**
+ * @since 2.7.4
+ */
+ @Override
+ public SortedSet<String> getConfigKeys(String group) {
+ return emptySortedSet();
+ }
}
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
index b33ec75,aa723de..1958372
--- a/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
+++ b/dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ApplicationConfig.java
@@@ -379,11 -382,45 +387,53 @@@ public class ApplicationConfig extends
return !StringUtils.isEmpty(name);
}
+ public String getMetadata() {
+ return metadata;
+ }
+
+ public void setMetadata(String metadata) {
+ this.metadata = metadata;
+ }
++
+ @Override
+ public void refresh() {
+ super.refresh();
+ appendEnvironmentProperties();
+ }
+
+ /**
+ * 1. OS Environment: DUBBO_LABELS=tag=pre;key=value
+ * 2. JVM Options: -Denv_keys = DUBBO_KEY1, DUBBO_KEY2
+ */
+ private void appendEnvironmentProperties() {
+ String rawLabels = ConfigurationUtils.getProperty(DUBBO_LABELS);
+ if (StringUtils.isNotEmpty(rawLabels)) {
+ String[] labelPairs = SEMICOLON_SPLIT_PATTERN.split(rawLabels);
+ for (String pair : labelPairs) {
+ String[] label = EQUAL_SPLIT_PATTERN.split(pair);
+ if (label.length == 2) {
+ updateParameters(parameters, label[0], label[1]);
+ }
+ }
+ }
+
+ String rawKeys = ConfigurationUtils.getProperty(DUBBO_ENV_KEYS);
+ if (StringUtils.isNotEmpty(rawKeys)) {
+ String[] keys = COMMA_SPLIT_PATTERN.split(rawKeys);
+ for (String key : keys) {
+ String value = ConfigurationUtils.getProperty(key);
+ if (value != null) {
+ updateParameters(parameters, key, value);
+ }
+ }
+ }
+ }
+
+ private void updateParameters(Map<String, String> map, String key, String value) {
+ if (parameters == null) {
+ parameters = new HashMap<>();
+ }
+ parameters.put(key, value);
+ }
+
}
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ReferenceConfig.java
index e98039c,3065a63..13ec542
--- 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
@@@ -1,694 -1,664 +1,694 @@@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.Version;
-import org.apache.dubbo.common.bytecode.Wrapper;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.utils.ClassUtils;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.ConfigUtils;
-import org.apache.dubbo.common.utils.NetUtils;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.config.annotation.Reference;
-import org.apache.dubbo.config.context.ConfigManager;
-import org.apache.dubbo.config.support.Parameter;
-import org.apache.dubbo.metadata.integration.MetadataReportService;
-import org.apache.dubbo.remoting.Constants;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Protocol;
-import org.apache.dubbo.rpc.ProxyFactory;
-import org.apache.dubbo.rpc.cluster.Cluster;
-import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
-import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
-import org.apache.dubbo.rpc.cluster.support.RegistryAwareCluster;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.ConsumerModel;
-import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol;
-import org.apache.dubbo.rpc.service.GenericService;
-import org.apache.dubbo.rpc.support.ProtocolUtils;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import static org.apache.dubbo.common.constants.CommonConstants.ANY_VALUE;
-import static org.apache.dubbo.common.constants.CommonConstants.COMMA_SEPARATOR;
-import static org.apache.dubbo.common.constants.CommonConstants.CONSUMER_SIDE;
-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
-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.METHODS_KEY;
-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.CommonConstants.CLUSTER_KEY;
-import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
-import static org.apache.dubbo.rpc.cluster.Constants.REFER_KEY;
-import static org.apache.dubbo.registry.Constants.REGISTER_IP_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
-import static org.apache.dubbo.registry.Constants.CONSUMER_PROTOCOL;
-import static org.apache.dubbo.common.constants.RegistryConstants.REGISTRY_PROTOCOL;
-import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
-import static org.apache.dubbo.common.utils.NetUtils.isInvalidLocalHost;
-
-/**
- * ReferenceConfig
- *
- * @export
- */
-public class ReferenceConfig<T> extends AbstractReferenceConfig {
-
- private static final long serialVersionUID = -5864351140409987595L;
-
- /**
- * The {@link Protocol} implementation with adaptive functionality,it will be different in different scenarios.
- * A particular {@link Protocol} implementation is determined by the protocol attribute in the {@link URL}.
- * For example:
- *
- * <li>when the url is registry://224.5.6.7:1234/org.apache.dubbo.registry.RegistryService?application=dubbo-sample,
- * then the protocol is <b>RegistryProtocol</b></li>
- *
- * <li>when the url is dubbo://224.5.6.7:1234/org.apache.dubbo.config.api.DemoService?application=dubbo-sample, then
- * the protocol is <b>DubboProtocol</b></li>
- * <p>
- * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
- * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
- */
- private static final Protocol REF_PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
-
- /**
- * The {@link Cluster}'s implementation with adaptive functionality, and actually it will get a {@link Cluster}'s
- * specific implementation who is wrapped with <b>MockClusterInvoker</b>
- */
- private static final Cluster CLUSTER = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension();
-
- /**
- * A {@link ProxyFactory} implementation that will generate a reference service's proxy,the JavassistProxyFactory is
- * its default implementation
- */
- private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
-
- /**
- * The url of the reference service
- */
- private final List<URL> urls = new ArrayList<URL>();
-
- /**
- * The interface name of the reference service
- */
- private String interfaceName;
-
- /**
- * The interface class of the reference service
- */
- private Class<?> interfaceClass;
-
- /**
- * client type
- */
- private String client;
-
- /**
- * The url for peer-to-peer invocation
- */
- private String url;
-
- /**
- * The method configs
- */
- private List<MethodConfig> methods;
-
- /**
- * The consumer config (default)
- */
- private ConsumerConfig consumer;
-
- /**
- * Only the service provider of the specified protocol is invoked, and other protocols are ignored.
- */
- private String protocol;
-
- /**
- * The interface proxy reference
- */
- private transient volatile T ref;
-
- /**
- * The invoker of the reference service
- */
- private transient volatile Invoker<?> invoker;
-
- /**
- * The flag whether the ReferenceConfig has been initialized
- */
- private transient volatile boolean initialized;
-
- /**
- * whether this ReferenceConfig has been destroyed
- */
- private transient volatile boolean destroyed;
-
- @SuppressWarnings("unused")
- private final Object finalizerGuardian = new Object() {
- @Override
- protected void finalize() throws Throwable {
- super.finalize();
-
- if (!ReferenceConfig.this.destroyed) {
- logger.warn("ReferenceConfig(" + url + ") is not DESTROYED when FINALIZE");
-
- /* don't destroy for now
- try {
- ReferenceConfig.this.destroy();
- } catch (Throwable t) {
- logger.warn("Unexpected err when destroy invoker of ReferenceConfig(" + url + ") in finalize method!", t);
- }
- */
- }
- }
- };
-
- public ReferenceConfig() {
- }
-
- public ReferenceConfig(Reference reference) {
- appendAnnotation(Reference.class, reference);
- setMethods(MethodConfig.constructMethodConfig(reference.methods()));
- }
-
- public URL toUrl() {
- return urls.isEmpty() ? null : urls.iterator().next();
- }
-
- public List<URL> toUrls() {
- return urls;
- }
-
- /**
- * This method should be called right after the creation of this class's instance, before any property in other config modules is used.
- * Check each config modules are created properly and override their properties if necessary.
- */
- public void checkAndUpdateSubConfigs() {
- if (StringUtils.isEmpty(interfaceName)) {
- throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
- }
- completeCompoundConfigs();
- startConfigCenter();
- // get consumer's global configuration
- checkDefault();
- this.refresh();
- if (getGeneric() == null && getConsumer() != null) {
- setGeneric(getConsumer().getGeneric());
- }
- if (ProtocolUtils.isGeneric(getGeneric())) {
- interfaceClass = GenericService.class;
- } else {
- try {
- interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
- .getContextClassLoader());
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(e.getMessage(), e);
- }
- checkInterfaceAndMethods(interfaceClass, methods);
- }
- resolveFile();
- checkApplication();
- checkMetadataReport();
- }
-
- public synchronized T get() {
- checkAndUpdateSubConfigs();
-
- if (destroyed) {
- throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
- }
- if (ref == null) {
- init();
- }
- return ref;
- }
-
- public synchronized void destroy() {
- if (ref == null) {
- return;
- }
- if (destroyed) {
- return;
- }
- destroyed = true;
- try {
- invoker.destroy();
- } catch (Throwable t) {
- logger.warn("Unexpected error occured when destroy invoker of ReferenceConfig(" + url + ").", t);
- }
- invoker = null;
- ref = null;
- }
-
- private void init() {
- if (initialized) {
- return;
- }
- checkStubAndLocal(interfaceClass);
- checkMock(interfaceClass);
- Map<String, String> map = new HashMap<String, String>();
-
- map.put(SIDE_KEY, CONSUMER_SIDE);
-
- appendRuntimeParameters(map);
- if (!isGeneric()) {
- String revision = Version.getVersion(interfaceClass, version);
- if (revision != null && revision.length() > 0) {
- map.put(REVISION_KEY, revision);
- }
-
- String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
- if (methods.length == 0) {
- logger.warn("No method found in service interface " + interfaceClass.getName());
- map.put(METHODS_KEY, ANY_VALUE);
- } else {
- map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), COMMA_SEPARATOR));
- }
- }
- map.put(INTERFACE_KEY, interfaceName);
- appendParameters(map, metrics);
- appendParameters(map, application);
- appendParameters(map, module);
- // remove 'default.' prefix for configs from ConsumerConfig
- // appendParameters(map, consumer, Constants.DEFAULT_KEY);
- appendParameters(map, consumer);
- appendParameters(map, this);
- Map<String, Object> attributes = null;
- if (CollectionUtils.isNotEmpty(methods)) {
- attributes = new HashMap<String, Object>();
- for (MethodConfig methodConfig : methods) {
- appendParameters(map, methodConfig, methodConfig.getName());
- String retryKey = methodConfig.getName() + ".retry";
- if (map.containsKey(retryKey)) {
- String retryValue = map.remove(retryKey);
- if ("false".equals(retryValue)) {
- map.put(methodConfig.getName() + ".retries", "0");
- }
- }
- attributes.put(methodConfig.getName(), convertMethodConfig2AsyncInfo(methodConfig));
- }
- }
-
- String hostToRegistry = ConfigUtils.getSystemProperty(DUBBO_IP_TO_REGISTRY);
- if (StringUtils.isEmpty(hostToRegistry)) {
- hostToRegistry = NetUtils.getLocalHost();
- } else if (isInvalidLocalHost(hostToRegistry)) {
- throw new IllegalArgumentException("Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
- }
- map.put(REGISTER_IP_KEY, hostToRegistry);
-
- ref = createProxy(map);
-
- String serviceKey = URL.buildKey(interfaceName, group, version);
- ApplicationModel.initConsumerModel(serviceKey, buildConsumerModel(serviceKey, attributes));
- initialized = true;
- }
-
- private ConsumerModel buildConsumerModel(String serviceKey, Map<String, Object> attributes) {
- Method[] methods = interfaceClass.getMethods();
- Class serviceInterface = interfaceClass;
- if (interfaceClass == GenericService.class) {
- try {
- serviceInterface = Class.forName(interfaceName);
- methods = serviceInterface.getMethods();
- } catch (ClassNotFoundException e) {
- methods = interfaceClass.getMethods();
- }
- }
- return new ConsumerModel(serviceKey, serviceInterface, ref, methods, attributes);
- }
-
- @SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
- private T createProxy(Map<String, String> map) {
- if (shouldJvmRefer(map)) {
- URL url = new URL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceClass.getName()).addParameters(map);
- invoker = REF_PROTOCOL.refer(interfaceClass, url);
- if (logger.isInfoEnabled()) {
- logger.info("Using injvm service " + interfaceClass.getName());
- }
- } else {
- urls.clear(); // reference retry init will add url to urls, lead to OOM
- if (url != null && url.length() > 0) { // user specified URL, could be peer-to-peer address, or register center's address.
- String[] us = SEMICOLON_SPLIT_PATTERN.split(url);
- if (us != null && us.length > 0) {
- for (String u : us) {
- URL url = URL.valueOf(u);
- if (StringUtils.isEmpty(url.getPath())) {
- url = url.setPath(interfaceName);
- }
- if (REGISTRY_PROTOCOL.equals(url.getProtocol())) {
- urls.add(url.addParameterAndEncoded(REFER_KEY, StringUtils.toQueryString(map)));
- } else {
- urls.add(ClusterUtils.mergeUrl(url, map));
- }
- }
- }
- } else { // assemble URL from register center's configuration
- // if protocols not injvm checkRegistry
- if (!LOCAL_PROTOCOL.equalsIgnoreCase(getProtocol())){
- checkRegistry();
- List<URL> us = loadRegistries(false);
- if (CollectionUtils.isNotEmpty(us)) {
- for (URL u : us) {
- URL monitorUrl = loadMonitor(u);
- if (monitorUrl != null) {
- map.put(MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
- }
- urls.add(u.addParameterAndEncoded(REFER_KEY, StringUtils.toQueryString(map)));
- }
- }
- if (urls.isEmpty()) {
- throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config.");
- }
- }
- }
-
- if (urls.size() == 1) {
- invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
- } else {
- List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
- URL registryURL = null;
- for (URL url : urls) {
- invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
- if (REGISTRY_PROTOCOL.equals(url.getProtocol())) {
- registryURL = url; // use last registry url
- }
- }
- if (registryURL != null) { // registry url is available
- // use RegistryAwareCluster only when register's CLUSTER is available
- URL u = registryURL.addParameter(CLUSTER_KEY, RegistryAwareCluster.NAME);
- // The invoker wrap relation would be: RegistryAwareClusterInvoker(StaticDirectory) -> FailoverClusterInvoker(RegistryDirectory, will execute route) -> Invoker
- invoker = CLUSTER.join(new StaticDirectory(u, invokers));
- } else { // not a registry url, must be direct invoke.
- invoker = CLUSTER.join(new StaticDirectory(invokers));
- }
- }
- }
-
- if (shouldCheck() && !invoker.isAvailable()) {
- throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
- }
- if (logger.isInfoEnabled()) {
- logger.info("Refer dubbo service " + interfaceClass.getName() + " from url " + invoker.getUrl());
- }
- /**
- * @since 2.7.0
- * ServiceData Store
- */
- MetadataReportService metadataReportService = null;
- if ((metadataReportService = getMetadataReportService()) != null) {
- URL consumerURL = new URL(CONSUMER_PROTOCOL, map.remove(REGISTER_IP_KEY), 0, map.get(INTERFACE_KEY), map);
- metadataReportService.publishConsumer(consumerURL);
- }
- // create service proxy
- return (T) PROXY_FACTORY.getProxy(invoker);
- }
-
- /**
- * Figure out should refer the service in the same JVM from configurations. The default behavior is true
- * 1. if injvm is specified, then use it
- * 2. then if a url is specified, then assume it's a remote call
- * 3. otherwise, check scope parameter
- * 4. if scope is not specified but the target service is provided in the same JVM, then prefer to make the local
- * call, which is the default behavior
- */
- protected boolean shouldJvmRefer(Map<String, String> map) {
- URL tmpUrl = new URL("temp", "localhost", 0, map);
- boolean isJvmRefer;
- if (isInjvm() == null) {
- // if a url is specified, don't do local reference
- if (url != null && url.length() > 0) {
- isJvmRefer = false;
- } else {
- // by default, reference local service if there is
- isJvmRefer = InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl);
- }
- } else {
- isJvmRefer = isInjvm();
- }
- return isJvmRefer;
- }
-
- protected boolean shouldCheck() {
- Boolean shouldCheck = isCheck();
- if (shouldCheck == null && getConsumer() != null) {
- shouldCheck = getConsumer().isCheck();
- }
- if (shouldCheck == null) {
- // default true
- shouldCheck = true;
- }
- return shouldCheck;
- }
-
- protected boolean shouldInit() {
- Boolean shouldInit = isInit();
- if (shouldInit == null && getConsumer() != null) {
- shouldInit = getConsumer().isInit();
- }
- if (shouldInit == null) {
- // default is false
- return false;
- }
- return shouldInit;
- }
-
- private void checkDefault() {
- if (consumer != null) {
- return;
- }
- setConsumer(ConfigManager.getInstance().getDefaultConsumer().orElseGet(() -> {
- ConsumerConfig consumerConfig = new ConsumerConfig();
- consumerConfig.refresh();
- return consumerConfig;
- }));
- }
-
- private void completeCompoundConfigs() {
- if (consumer != null) {
- if (application == null) {
- setApplication(consumer.getApplication());
- }
- if (module == null) {
- setModule(consumer.getModule());
- }
- if (registries == null) {
- setRegistries(consumer.getRegistries());
- }
- if (monitor == null) {
- setMonitor(consumer.getMonitor());
- }
- }
- if (module != null) {
- if (registries == null) {
- setRegistries(module.getRegistries());
- }
- if (monitor == null) {
- setMonitor(module.getMonitor());
- }
- }
- if (application != null) {
- if (registries == null) {
- setRegistries(application.getRegistries());
- }
- if (monitor == null) {
- setMonitor(application.getMonitor());
- }
- }
- }
-
- public Class<?> getInterfaceClass() {
- if (interfaceClass != null) {
- return interfaceClass;
- }
- if (isGeneric()
- || (getConsumer() != null && getConsumer().isGeneric())) {
- return GenericService.class;
- }
- try {
- if (interfaceName != null && interfaceName.length() > 0) {
- this.interfaceClass = Class.forName(interfaceName, true, ClassUtils.getClassLoader());
- }
- } catch (ClassNotFoundException t) {
- throw new IllegalStateException(t.getMessage(), t);
- }
- return interfaceClass;
- }
-
- /**
- * @param interfaceClass
- * @see #setInterface(Class)
- * @deprecated
- */
- @Deprecated
- public void setInterfaceClass(Class<?> interfaceClass) {
- setInterface(interfaceClass);
- }
-
- public String getInterface() {
- return interfaceName;
- }
-
- public void setInterface(String interfaceName) {
- this.interfaceName = interfaceName;
- if (StringUtils.isEmpty(id)) {
- id = interfaceName;
- }
- }
-
- public void setInterface(Class<?> interfaceClass) {
- if (interfaceClass != null && !interfaceClass.isInterface()) {
- throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
- }
- this.interfaceClass = interfaceClass;
- setInterface(interfaceClass == null ? null : interfaceClass.getName());
- }
-
- public String getClient() {
- return client;
- }
-
- public void setClient(String client) {
- checkName(Constants.CLIENT_KEY, client);
- this.client = client;
- }
-
- @Parameter(excluded = true)
- public String getUrl() {
- return url;
- }
-
- public void setUrl(String url) {
- this.url = url;
- }
-
- public List<MethodConfig> getMethods() {
- return methods;
- }
-
- @SuppressWarnings("unchecked")
- public void setMethods(List<? extends MethodConfig> methods) {
- this.methods = (List<MethodConfig>) methods;
- }
-
- public ConsumerConfig getConsumer() {
- return consumer;
- }
-
- public void setConsumer(ConsumerConfig consumer) {
- ConfigManager.getInstance().addConsumer(consumer);
- this.consumer = consumer;
- }
-
- public String getProtocol() {
- return protocol;
- }
-
- public void setProtocol(String protocol) {
- this.protocol = protocol;
- }
-
- // just for test
- Invoker<?> getInvoker() {
- return invoker;
- }
-
- @Override
- @Parameter(excluded = true)
- public String getPrefix() {
- return DUBBO + ".reference." + interfaceName;
- }
-
- private void resolveFile() {
- String resolve = System.getProperty(interfaceName);
- String resolveFile = null;
- if (StringUtils.isEmpty(resolve)) {
- resolveFile = System.getProperty("dubbo.resolve.file");
- if (StringUtils.isEmpty(resolveFile)) {
- File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");
- if (userResolveFile.exists()) {
- resolveFile = userResolveFile.getAbsolutePath();
- }
- }
- if (resolveFile != null && resolveFile.length() > 0) {
- Properties properties = new Properties();
- try (FileInputStream fis = new FileInputStream(new File(resolveFile))) {
- properties.load(fis);
- } catch (IOException e) {
- throw new IllegalStateException("Failed to load " + resolveFile + ", cause: " + e.getMessage(), e);
- }
-
- resolve = properties.getProperty(interfaceName);
- }
- }
- if (resolve != null && resolve.length() > 0) {
- url = resolve;
- if (logger.isWarnEnabled()) {
- if (resolveFile != null) {
- logger.warn("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service.");
- } else {
- logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service.");
- }
- }
- }
- }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.bytecode.Wrapper;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.ClassUtils;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.common.utils.NetUtils;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.config.annotation.Reference;
+import org.apache.dubbo.config.context.ConfigManager;
+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.event.Event;
+import org.apache.dubbo.event.EventDispatcher;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.remoting.Constants;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.cluster.Cluster;
+import org.apache.dubbo.rpc.cluster.directory.StaticDirectory;
+import org.apache.dubbo.rpc.cluster.support.ClusterUtils;
+import org.apache.dubbo.rpc.cluster.support.RegistryAwareCluster;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ConsumerModel;
+import org.apache.dubbo.rpc.protocol.injvm.InjvmProtocol;
+import org.apache.dubbo.rpc.service.GenericService;
+import org.apache.dubbo.rpc.support.ProtocolUtils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+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.CONSUMER_SIDE;
+import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
+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_DEFAULT;
+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.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.REGISTRY_PROTOCOL;
+import static org.apache.dubbo.common.utils.NetUtils.isInvalidLocalHost;
+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;
+
+/**
+ * ReferenceConfig
+ *
+ * @export
+ */
+public class ReferenceConfig<T> extends AbstractReferenceConfig {
+
+ private static final long serialVersionUID = -5864351140409987595L;
+
+ /**
+ * The {@link Protocol} implementation with adaptive functionality,it will be different in different scenarios.
+ * A particular {@link Protocol} implementation is determined by the protocol attribute in the {@link URL}.
+ * For example:
+ *
+ * <li>when the url is registry://224.5.6.7:1234/org.apache.dubbo.registry.RegistryService?application=dubbo-sample,
+ * then the protocol is <b>RegistryProtocol</b></li>
+ *
+ * <li>when the url is dubbo://224.5.6.7:1234/org.apache.dubbo.config.api.DemoService?application=dubbo-sample, then
+ * the protocol is <b>DubboProtocol</b></li>
+ * <p>
+ * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
+ * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
+ */
+ private static final Protocol REF_PROTOCOL = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+
+ /**
+ * The {@link Cluster}'s implementation with adaptive functionality, and actually it will get a {@link Cluster}'s
+ * specific implementation who is wrapped with <b>MockClusterInvoker</b>
+ */
+ private static final Cluster CLUSTER = ExtensionLoader.getExtensionLoader(Cluster.class).getAdaptiveExtension();
+
+ /**
+ * A {@link ProxyFactory} implementation that will generate a reference service's proxy,the JavassistProxyFactory is
+ * its default implementation
+ */
+ private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+
+ /**
+ * The url of the reference service
+ */
+ private final List<URL> urls = new ArrayList<URL>();
+
+ /**
+ * The interface name of the reference service
+ */
+ private String interfaceName;
+
+ /**
+ * The interface class of the reference service
+ */
+ private Class<?> interfaceClass;
+
+ /**
+ * client type
+ */
+ private String client;
+
+ /**
+ * The url for peer-to-peer invocation
+ */
+ private String url;
+
+ /**
+ * The method configs
+ */
+ private List<MethodConfig> methods;
+
+ /**
+ * The consumer config (default)
+ */
+ private ConsumerConfig consumer;
+
+ /**
+ * Only the service provider of the specified protocol is invoked, and other protocols are ignored.
+ */
+ private String protocol;
+
+ /**
+ * The interface proxy reference
+ */
+ private transient volatile T ref;
+
+ /**
+ * The invoker of the reference service
+ */
+ private transient volatile Invoker<?> invoker;
+
+ /**
+ * The flag whether the ReferenceConfig has been initialized
+ */
+ private transient volatile boolean initialized;
+
+ /**
+ * whether this ReferenceConfig has been destroyed
+ */
+ private transient volatile boolean destroyed;
+
+ /**
+ * The {@link EventDispatcher}
+ *
+ * @since 2.7.4
+ */
+ private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();
+
+ @SuppressWarnings("unused")
+ private final Object finalizerGuardian = new Object() {
+ @Override
+ protected void finalize() throws Throwable {
+ super.finalize();
+
+ if (!ReferenceConfig.this.destroyed) {
+ logger.warn("ReferenceConfig(" + url + ") is not DESTROYED when FINALIZE");
+
+ /* don't destroy for now
+ try {
+ ReferenceConfig.this.destroy();
+ } catch (Throwable t) {
+ logger.warn("Unexpected err when destroy invoker of ReferenceConfig(" + url + ") in finalize method!", t);
+ }
+ */
+ }
+ }
+ };
+
+ public ReferenceConfig() {
+ }
+
+ public ReferenceConfig(Reference reference) {
+ appendAnnotation(Reference.class, reference);
+ setMethods(MethodConfig.constructMethodConfig(reference.methods()));
+ }
+
+ public URL toUrl() {
+ return urls.isEmpty() ? null : urls.iterator().next();
+ }
+
+ public List<URL> toUrls() {
+ return urls;
+ }
+
+ /**
+ * This method should be called right after the creation of this class's instance, before any property in other config modules is used.
+ * Check each config modules are created properly and override their properties if necessary.
+ */
+ public void checkAndUpdateSubConfigs() {
+ if (StringUtils.isEmpty(interfaceName)) {
+ throw new IllegalStateException("<dubbo:reference interface=\"\" /> interface not allow null!");
+ }
+ completeCompoundConfigs();
+ // get consumer's global configuration
+ checkDefault();
+ this.refresh();
+ if (getGeneric() == null && getConsumer() != null) {
+ setGeneric(getConsumer().getGeneric());
+ }
+ if (ProtocolUtils.isGeneric(getGeneric())) {
+ interfaceClass = GenericService.class;
+ } else {
+ try {
+ interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
+ .getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ checkInterfaceAndMethods(interfaceClass, methods);
+ }
+ resolveFile();
+ checkApplication();
+ checkMetadataReport();
+ }
+
+ public synchronized T get() {
+ checkAndUpdateSubConfigs();
+
+ if (destroyed) {
+ throw new IllegalStateException("The invoker of ReferenceConfig(" + url + ") has already destroyed!");
+ }
+ if (ref == null) {
+ init();
+ }
+ return ref;
+ }
+
+ public synchronized void destroy() {
+ if (ref == null) {
+ return;
+ }
+ if (destroyed) {
+ return;
+ }
+ destroyed = true;
+ try {
+ invoker.destroy();
+ } catch (Throwable t) {
+ logger.warn("Unexpected error occured when destroy invoker of ReferenceConfig(" + url + ").", t);
+ }
+ invoker = null;
+ ref = null;
+
+ // dispatch a ReferenceConfigDestroyedEvent since 2.7.4
+ dispatch(new ReferenceConfigDestroyedEvent(this));
+ }
+
+ private void init() {
+ if (initialized) {
+ return;
+ }
+ checkStubAndLocal(interfaceClass);
+ checkMock(interfaceClass);
+ Map<String, String> map = new HashMap<String, String>();
+
+ map.put(SIDE_KEY, CONSUMER_SIDE);
+
+ appendRuntimeParameters(map);
+ if (!isGeneric()) {
+ String revision = Version.getVersion(interfaceClass, version);
+ if (revision != null && revision.length() > 0) {
+ map.put(REVISION_KEY, revision);
+ }
+
+ String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
+ if (methods.length == 0) {
+ logger.warn("No method found in service interface " + interfaceClass.getName());
+ map.put(METHODS_KEY, ANY_VALUE);
+ } else {
+ map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), COMMA_SEPARATOR));
+ }
+ }
+ map.put(INTERFACE_KEY, interfaceName);
+ appendParameters(map, metrics);
+ appendParameters(map, application);
+ appendParameters(map, module);
+ // remove 'default.' prefix for configs from ConsumerConfig
+ // appendParameters(map, consumer, Constants.DEFAULT_KEY);
+ appendParameters(map, consumer);
+ appendParameters(map, this);
+ Map<String, Object> attributes = null;
+ if (CollectionUtils.isNotEmpty(methods)) {
+ attributes = new HashMap<String, Object>();
+ for (MethodConfig methodConfig : methods) {
+ appendParameters(map, methodConfig, methodConfig.getName());
+ String retryKey = methodConfig.getName() + ".retry";
+ if (map.containsKey(retryKey)) {
+ String retryValue = map.remove(retryKey);
+ if ("false".equals(retryValue)) {
+ map.put(methodConfig.getName() + ".retries", "0");
+ }
+ }
- attributes.put(methodConfig.getName(), convertMethodConfig2AyncInfo(methodConfig));
++ attributes.put(methodConfig.getName(), convertMethodConfig2AsyncInfo(methodConfig));
+ }
+ }
+
+ String hostToRegistry = ConfigUtils.getSystemProperty(DUBBO_IP_TO_REGISTRY);
+ if (StringUtils.isEmpty(hostToRegistry)) {
+ hostToRegistry = NetUtils.getLocalHost();
+ } else if (isInvalidLocalHost(hostToRegistry)) {
+ throw new IllegalArgumentException("Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
+ }
+ map.put(REGISTER_IP_KEY, hostToRegistry);
+
+ String serviceKey = URL.buildKey(interfaceName, group, version);
+ ApplicationModel.initConsumerModel(serviceKey, buildConsumerModel(serviceKey, attributes));
+ ref = createProxy(map);
+ ApplicationModel.getConsumerModel(serviceKey).setProxyObject(ref);
+
+ initialized = true;
+
+ // dispatch a ReferenceConfigInitializedEvent since 2.7.4
+ dispatch(new ReferenceConfigInitializedEvent(this, invoker));
+ }
+
+ private ConsumerModel buildConsumerModel(String serviceKey, Map<String, Object> attributes) {
+ Method[] methods = interfaceClass.getMethods();
+ Class serviceInterface = interfaceClass;
+ if (interfaceClass == GenericService.class) {
+ try {
+ serviceInterface = Class.forName(interfaceName);
+ methods = serviceInterface.getMethods();
+ } catch (ClassNotFoundException e) {
+ methods = interfaceClass.getMethods();
+ }
+ }
+ return new ConsumerModel(serviceKey, serviceInterface, ref, methods, attributes);
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes", "deprecation"})
+ private T createProxy(Map<String, String> map) {
+ if (shouldJvmRefer(map)) {
+ URL url = new URL(LOCAL_PROTOCOL, LOCALHOST_VALUE, 0, interfaceClass.getName()).addParameters(map);
+ invoker = REF_PROTOCOL.refer(interfaceClass, url);
+ if (logger.isInfoEnabled()) {
+ logger.info("Using injvm service " + interfaceClass.getName());
+ }
+ } else {
+ urls.clear(); // reference retry init will add url to urls, lead to OOM
+ if (url != null && url.length() > 0) { // user specified URL, could be peer-to-peer address, or register center's address.
+ String[] us = SEMICOLON_SPLIT_PATTERN.split(url);
+ if (us != null && us.length > 0) {
+ for (String u : us) {
+ URL url = URL.valueOf(u);
+ if (StringUtils.isEmpty(url.getPath())) {
+ url = url.setPath(interfaceName);
+ }
+ if (REGISTRY_PROTOCOL.equals(url.getProtocol())) {
+ urls.add(url.addParameterAndEncoded(REFER_KEY, StringUtils.toQueryString(map)));
+ } else {
+ urls.add(ClusterUtils.mergeUrl(url, map));
+ }
+ }
+ }
+ } else { // assemble URL from register center's configuration
+ // if protocols not injvm checkRegistry
+ if (!LOCAL_PROTOCOL.equalsIgnoreCase(getProtocol())) {
+ checkRegistry();
+ List<URL> us = loadRegistries(false);
+ if (CollectionUtils.isNotEmpty(us)) {
+ for (URL u : us) {
+ URL monitorUrl = loadMonitor(u);
+ if (monitorUrl != null) {
+ map.put(MONITOR_KEY, URL.encode(monitorUrl.toFullString()));
+ }
+ urls.add(u.addParameterAndEncoded(REFER_KEY, StringUtils.toQueryString(map)));
+ }
+ }
+ if (urls.isEmpty()) {
+ throw new IllegalStateException("No such any registry to reference " + interfaceName + " on the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion() + ", please config <dubbo:registry address=\"...\" /> to your spring config.");
+ }
+ }
+ }
+
+ if (urls.size() == 1) {
+ invoker = REF_PROTOCOL.refer(interfaceClass, urls.get(0));
+ } else {
+ List<Invoker<?>> invokers = new ArrayList<Invoker<?>>();
+ URL registryURL = null;
+ for (URL url : urls) {
+ invokers.add(REF_PROTOCOL.refer(interfaceClass, url));
+ if (REGISTRY_PROTOCOL.equals(url.getProtocol())) {
+ registryURL = url; // use last registry url
+ }
+ }
+ if (registryURL != null) { // registry url is available
+ // use RegistryAwareCluster only when register's CLUSTER is available
+ URL u = registryURL.addParameter(CLUSTER_KEY, RegistryAwareCluster.NAME);
+ // The invoker wrap relation would be: RegistryAwareClusterInvoker(StaticDirectory) -> FailoverClusterInvoker(RegistryDirectory, will execute route) -> Invoker
+ invoker = CLUSTER.join(new StaticDirectory(u, invokers));
+ } else { // not a registry url, must be direct invoke.
+ invoker = CLUSTER.join(new StaticDirectory(invokers));
+ }
+ }
+ }
+
+ if (shouldCheck() && !invoker.isAvailable()) {
+ throw new IllegalStateException("Failed to check the status of the service " + interfaceName + ". No provider available for the service " + (group == null ? "" : group + "/") + interfaceName + (version == null ? "" : ":" + version) + " from the url " + invoker.getUrl() + " to the consumer " + NetUtils.getLocalHost() + " use dubbo version " + Version.getVersion());
+ }
+ 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 ? METADATA_DEFAULT : 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);
+ }
+
+ /**
+ * Figure out should refer the service in the same JVM from configurations. The default behavior is true
+ * 1. if injvm is specified, then use it
+ * 2. then if a url is specified, then assume it's a remote call
+ * 3. otherwise, check scope parameter
+ * 4. if scope is not specified but the target service is provided in the same JVM, then prefer to make the local
+ * call, which is the default behavior
+ */
+ protected boolean shouldJvmRefer(Map<String, String> map) {
+ URL tmpUrl = new URL("temp", "localhost", 0, map);
+ boolean isJvmRefer;
+ if (isInjvm() == null) {
+ // if a url is specified, don't do local reference
+ if (url != null && url.length() > 0) {
+ isJvmRefer = false;
+ } else {
+ // by default, reference local service if there is
+ isJvmRefer = InjvmProtocol.getInjvmProtocol().isInjvmRefer(tmpUrl);
+ }
+ } else {
+ isJvmRefer = isInjvm();
+ }
+ return isJvmRefer;
+ }
+
+ protected boolean shouldCheck() {
+ Boolean shouldCheck = isCheck();
+ if (shouldCheck == null && getConsumer() != null) {
+ shouldCheck = getConsumer().isCheck();
+ }
+ if (shouldCheck == null) {
+ // default true
+ shouldCheck = true;
+ }
+ return shouldCheck;
+ }
+
+ protected boolean shouldInit() {
+ Boolean shouldInit = isInit();
+ if (shouldInit == null && getConsumer() != null) {
+ shouldInit = getConsumer().isInit();
+ }
+ if (shouldInit == null) {
+ // default is false
+ return false;
+ }
+ return shouldInit;
+ }
+
+ private void checkDefault() {
+ if (consumer != null) {
+ return;
+ }
+ setConsumer(ConfigManager.getInstance().getDefaultConsumer().orElseGet(() -> {
+ ConsumerConfig consumerConfig = new ConsumerConfig();
+ consumerConfig.refresh();
+ return consumerConfig;
+ }));
+ }
+
+ private void completeCompoundConfigs() {
+ if (consumer != null) {
+ if (application == null) {
+ setApplication(consumer.getApplication());
+ }
+ if (module == null) {
+ setModule(consumer.getModule());
+ }
+ if (registries == null) {
+ setRegistries(consumer.getRegistries());
+ }
+ if (monitor == null) {
+ setMonitor(consumer.getMonitor());
+ }
+ }
+ if (module != null) {
+ if (registries == null) {
+ setRegistries(module.getRegistries());
+ }
+ if (monitor == null) {
+ setMonitor(module.getMonitor());
+ }
+ }
+ if (application != null) {
+ if (registries == null) {
+ setRegistries(application.getRegistries());
+ }
+ if (monitor == null) {
+ setMonitor(application.getMonitor());
+ }
+ }
+ }
+
+ public Class<?> getInterfaceClass() {
+ if (interfaceClass != null) {
+ return interfaceClass;
+ }
+ if (isGeneric()
+ || (getConsumer() != null && getConsumer().isGeneric())) {
+ return GenericService.class;
+ }
+ try {
+ if (interfaceName != null && interfaceName.length() > 0) {
+ this.interfaceClass = Class.forName(interfaceName, true, ClassUtils.getClassLoader());
+ }
+ } catch (ClassNotFoundException t) {
+ throw new IllegalStateException(t.getMessage(), t);
+ }
+ return interfaceClass;
+ }
+
+ /**
+ * @param interfaceClass
+ * @see #setInterface(Class)
+ * @deprecated
+ */
+ @Deprecated
+ public void setInterfaceClass(Class<?> interfaceClass) {
+ setInterface(interfaceClass);
+ }
+
+ public String getInterface() {
+ return interfaceName;
+ }
+
+ public void setInterface(String interfaceName) {
+ this.interfaceName = interfaceName;
+ if (StringUtils.isEmpty(id)) {
+ id = interfaceName;
+ }
+ }
+
+ public void setInterface(Class<?> interfaceClass) {
+ if (interfaceClass != null && !interfaceClass.isInterface()) {
+ throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
+ }
+ this.interfaceClass = interfaceClass;
+ setInterface(interfaceClass == null ? null : interfaceClass.getName());
+ }
+
+ public String getClient() {
+ return client;
+ }
+
+ public void setClient(String client) {
+ checkName(Constants.CLIENT_KEY, client);
+ this.client = client;
+ }
+
+ @Parameter(excluded = true)
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public List<MethodConfig> getMethods() {
+ return methods;
+ }
+
+ @SuppressWarnings("unchecked")
+ public void setMethods(List<? extends MethodConfig> methods) {
+ this.methods = (List<MethodConfig>) methods;
+ }
+
+ public ConsumerConfig getConsumer() {
+ return consumer;
+ }
+
+ public void setConsumer(ConsumerConfig consumer) {
+ ConfigManager.getInstance().addConsumer(consumer);
+ this.consumer = consumer;
+ }
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+ // just for test
+ Invoker<?> getInvoker() {
+ return invoker;
+ }
+
+ @Override
+ @Parameter(excluded = true)
+ public String getPrefix() {
+ return DUBBO + ".reference." + interfaceName;
+ }
+
+ private void resolveFile() {
+ String resolve = System.getProperty(interfaceName);
+ String resolveFile = null;
+ if (StringUtils.isEmpty(resolve)) {
+ resolveFile = System.getProperty("dubbo.resolve.file");
+ if (StringUtils.isEmpty(resolveFile)) {
+ File userResolveFile = new File(new File(System.getProperty("user.home")), "dubbo-resolve.properties");
+ if (userResolveFile.exists()) {
+ resolveFile = userResolveFile.getAbsolutePath();
+ }
+ }
+ if (resolveFile != null && resolveFile.length() > 0) {
+ Properties properties = new Properties();
+ try (FileInputStream fis = new FileInputStream(new File(resolveFile))) {
+ properties.load(fis);
+ } catch (IOException e) {
+ throw new IllegalStateException("Failed to load " + resolveFile + ", cause: " + e.getMessage(), e);
+ }
+
+ resolve = properties.getProperty(interfaceName);
+ }
+ }
+ if (resolve != null && resolve.length() > 0) {
+ url = resolve;
+ if (logger.isWarnEnabled()) {
+ if (resolveFile != null) {
+ logger.warn("Using default dubbo resolve file " + resolveFile + " replace " + interfaceName + "" + resolve + " to p2p invoke remote service.");
+ } else {
+ logger.warn("Using -D" + interfaceName + "=" + resolve + " to p2p invoke remote service.");
+ }
+ }
+ }
+ }
+
+ /**
+ * Dispatch an {@link Event event}
+ *
+ * @param event an {@link Event event}
+ * @since 2.7.4
+ */
+ protected void dispatch(Event event) {
+ eventDispatcher.dispatch(event);
+ }
+}
diff --cc dubbo-config/dubbo-config-api/src/main/java/org/apache/dubbo/config/ServiceConfig.java
index fb9d247,c0bd1e8..dd161ff
--- 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
@@@ -1,1064 -1,1054 +1,1064 @@@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.dubbo.config;
-
-import org.apache.dubbo.common.URL;
-import org.apache.dubbo.common.URLBuilder;
-import org.apache.dubbo.common.Version;
-import org.apache.dubbo.common.bytecode.Wrapper;
-import org.apache.dubbo.common.config.Environment;
-import org.apache.dubbo.common.extension.ExtensionLoader;
-import org.apache.dubbo.common.utils.ClassUtils;
-import org.apache.dubbo.common.utils.CollectionUtils;
-import org.apache.dubbo.common.utils.ConfigUtils;
-import org.apache.dubbo.common.utils.NamedThreadFactory;
-import org.apache.dubbo.common.utils.StringUtils;
-import org.apache.dubbo.config.annotation.Service;
-import org.apache.dubbo.config.context.ConfigManager;
-import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
-import org.apache.dubbo.config.support.Parameter;
-import org.apache.dubbo.metadata.integration.MetadataReportService;
-import org.apache.dubbo.remoting.Constants;
-import org.apache.dubbo.rpc.Exporter;
-import org.apache.dubbo.rpc.Invoker;
-import org.apache.dubbo.rpc.Protocol;
-import org.apache.dubbo.rpc.ProxyFactory;
-import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
-import org.apache.dubbo.rpc.model.ApplicationModel;
-import org.apache.dubbo.rpc.model.ProviderModel;
-import org.apache.dubbo.rpc.service.GenericService;
-import org.apache.dubbo.rpc.support.ProtocolUtils;
-
-import java.lang.reflect.Method;
-import java.net.InetAddress;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketAddress;
-import java.net.UnknownHostException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-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.COMMA_SPLIT_PATTERN;
-import static org.apache.dubbo.common.constants.CommonConstants.DUBBO;
-import static org.apache.dubbo.common.constants.CommonConstants.LOCALHOST_VALUE;
-import static org.apache.dubbo.common.constants.CommonConstants.METHODS_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PATH_KEY;
-import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
-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.CommonConstants.DUBBO_IP_TO_BIND;
-import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
-import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_BIND;
-import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_REGISTRY;
-import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
-import static org.apache.dubbo.config.Constants.MULTICAST;
-import static org.apache.dubbo.config.Constants.PROTOCOLS_SUFFIX;
-import static org.apache.dubbo.rpc.Constants.SCOPE_KEY;
-import static org.apache.dubbo.rpc.Constants.SCOPE_LOCAL;
-import static org.apache.dubbo.config.Constants.SCOPE_NONE;
-import static org.apache.dubbo.rpc.Constants.SCOPE_REMOTE;
-import static org.apache.dubbo.common.constants.CommonConstants.MONITOR_KEY;
-import static org.apache.dubbo.common.constants.RegistryConstants.DYNAMIC_KEY;
-import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
-import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
-import static org.apache.dubbo.rpc.Constants.PROXY_KEY;
-import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
-import static org.apache.dubbo.common.utils.NetUtils.getAvailablePort;
-import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
-import static org.apache.dubbo.common.utils.NetUtils.isInvalidLocalHost;
-import static org.apache.dubbo.common.utils.NetUtils.isInvalidPort;
-
-/**
- * ServiceConfig
- *
- * @export
- */
-public class ServiceConfig<T> extends AbstractServiceConfig {
-
- private static final long serialVersionUID = 3033787999037024738L;
-
- /**
- * The {@link Protocol} implementation with adaptive functionality,it will be different in different scenarios.
- * A particular {@link Protocol} implementation is determined by the protocol attribute in the {@link URL}.
- * For example:
- *
- * <li>when the url is registry://224.5.6.7:1234/org.apache.dubbo.registry.RegistryService?application=dubbo-sample,
- * then the protocol is <b>RegistryProtocol</b></li>
- *
- * <li>when the url is dubbo://224.5.6.7:1234/org.apache.dubbo.config.api.DemoService?application=dubbo-sample, then
- * the protocol is <b>DubboProtocol</b></li>
- * <p>
- * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
- * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
- */
- private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
-
- /**
- * A {@link ProxyFactory} implementation that will generate a exported service proxy,the JavassistProxyFactory is its
- * default implementation
- */
- private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
-
- /**
- * A random port cache, the different protocols who has no port specified have different random port
- */
- private static final Map<String, Integer> RANDOM_PORT_MAP = new HashMap<String, Integer>();
-
- /**
- * A delayed exposure service timer
- */
- private static final ScheduledExecutorService DELAY_EXPORT_EXECUTOR = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboServiceDelayExporter", true));
-
- /**
- * The urls of the services exported
- */
- private final List<URL> urls = new ArrayList<URL>();
-
- /**
- * The exported services
- */
- private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
-
- /**
- * The interface name of the exported service
- */
- private String interfaceName;
-
- /**
- * The interface class of the exported service
- */
- private Class<?> interfaceClass;
-
- /**
- * The reference of the interface implementation
- */
- private T ref;
-
- /**
- * The service name
- */
- private String path;
-
- /**
- * The method configuration
- */
- private List<MethodConfig> methods;
-
- /**
- * The provider configuration
- */
- private ProviderConfig provider;
-
- /**
- * The providerIds
- */
- private String providerIds;
-
- /**
- * Whether the provider has been exported
- */
- private transient volatile boolean exported;
-
- /**
- * The flag whether a service has unexported ,if the method unexported is invoked, the value is true
- */
- private transient volatile boolean unexported;
-
- /**
- * whether it is a GenericService
- */
- private volatile String generic;
-
- public ServiceConfig() {
- }
-
- public ServiceConfig(Service service) {
- appendAnnotation(Service.class, service);
- setMethods(MethodConfig.constructMethodConfig(service.methods()));
- }
-
- @Deprecated
- private static List<ProtocolConfig> convertProviderToProtocol(List<ProviderConfig> providers) {
- if (CollectionUtils.isEmpty(providers)) {
- return null;
- }
- List<ProtocolConfig> protocols = new ArrayList<ProtocolConfig>(providers.size());
- for (ProviderConfig provider : providers) {
- protocols.add(convertProviderToProtocol(provider));
- }
- return protocols;
- }
-
- @Deprecated
- private static List<ProviderConfig> convertProtocolToProvider(List<ProtocolConfig> protocols) {
- if (CollectionUtils.isEmpty(protocols)) {
- return null;
- }
- List<ProviderConfig> providers = new ArrayList<ProviderConfig>(protocols.size());
- for (ProtocolConfig provider : protocols) {
- providers.add(convertProtocolToProvider(provider));
- }
- return providers;
- }
-
- @Deprecated
- private static ProtocolConfig convertProviderToProtocol(ProviderConfig provider) {
- ProtocolConfig protocol = new ProtocolConfig();
- protocol.setName(provider.getProtocol().getName());
- protocol.setServer(provider.getServer());
- protocol.setClient(provider.getClient());
- protocol.setCodec(provider.getCodec());
- protocol.setHost(provider.getHost());
- protocol.setPort(provider.getPort());
- protocol.setPath(provider.getPath());
- protocol.setPayload(provider.getPayload());
- protocol.setThreads(provider.getThreads());
- protocol.setParameters(provider.getParameters());
- return protocol;
- }
-
- @Deprecated
- private static ProviderConfig convertProtocolToProvider(ProtocolConfig protocol) {
- ProviderConfig provider = new ProviderConfig();
- provider.setProtocol(protocol);
- provider.setServer(protocol.getServer());
- provider.setClient(protocol.getClient());
- provider.setCodec(protocol.getCodec());
- provider.setHost(protocol.getHost());
- provider.setPort(protocol.getPort());
- provider.setPath(protocol.getPath());
- provider.setPayload(protocol.getPayload());
- provider.setThreads(protocol.getThreads());
- provider.setParameters(protocol.getParameters());
- return provider;
- }
-
- private static Integer getRandomPort(String protocol) {
- protocol = protocol.toLowerCase();
- return RANDOM_PORT_MAP.getOrDefault(protocol, Integer.MIN_VALUE);
- }
-
- private static void putRandomPort(String protocol, Integer port) {
- protocol = protocol.toLowerCase();
- if (!RANDOM_PORT_MAP.containsKey(protocol)) {
- RANDOM_PORT_MAP.put(protocol, port);
- logger.warn("Use random available port(" + port + ") for protocol " + protocol);
- }
- }
-
- public URL toUrl() {
- return urls.isEmpty() ? null : urls.iterator().next();
- }
-
- public List<URL> toUrls() {
- return urls;
- }
-
- @Parameter(excluded = true)
- public boolean isExported() {
- return exported;
- }
-
- @Parameter(excluded = true)
- public boolean isUnexported() {
- return unexported;
- }
-
- public void checkAndUpdateSubConfigs() {
- // Use default configs defined explicitly on global configs
- completeCompoundConfigs();
- // Config Center should always being started first.
- startConfigCenter();
- checkDefault();
- checkProtocol();
- checkApplication();
- // if protocol is not injvm checkRegistry
- if (!isOnlyInJvm()) {
- checkRegistry();
- }
- this.refresh();
- checkMetadataReport();
-
- if (StringUtils.isEmpty(interfaceName)) {
- throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
- }
-
- if (ref instanceof GenericService) {
- interfaceClass = GenericService.class;
- if (StringUtils.isEmpty(generic)) {
- generic = Boolean.TRUE.toString();
- }
- } else {
- try {
- interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
- .getContextClassLoader());
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(e.getMessage(), e);
- }
- checkInterfaceAndMethods(interfaceClass, methods);
- checkRef();
- generic = Boolean.FALSE.toString();
- }
- if (local != null) {
- if ("true".equals(local)) {
- local = interfaceName + "Local";
- }
- Class<?> localClass;
- try {
- localClass = ClassUtils.forNameWithThreadContextClassLoader(local);
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(e.getMessage(), e);
- }
- if (!interfaceClass.isAssignableFrom(localClass)) {
- throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceName);
- }
- }
- if (stub != null) {
- if ("true".equals(stub)) {
- stub = interfaceName + "Stub";
- }
- Class<?> stubClass;
- try {
- stubClass = ClassUtils.forNameWithThreadContextClassLoader(stub);
- } catch (ClassNotFoundException e) {
- throw new IllegalStateException(e.getMessage(), e);
- }
- if (!interfaceClass.isAssignableFrom(stubClass)) {
- throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + interfaceName);
- }
- }
- checkStubAndLocal(interfaceClass);
- checkMock(interfaceClass);
- }
-
- /**
- * Determine if it is injvm
- *
- * @return
- */
- private boolean isOnlyInJvm() {
- return getProtocols().size() == 1 && LOCAL_PROTOCOL.equalsIgnoreCase(getProtocols().get(0).getName());
- }
-
- public synchronized void export() {
- checkAndUpdateSubConfigs();
-
- if (!shouldExport()) {
- return;
- }
-
- if (shouldDelay()) {
- DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS);
- } else {
- doExport();
- }
- }
-
- private boolean shouldExport() {
- Boolean export = getExport();
- // default value is true
- return export == null ? true : export;
- }
-
- @Override
- public Boolean getExport() {
- return (export == null && provider != null) ? provider.getExport() : export;
- }
-
- private boolean shouldDelay() {
- Integer delay = getDelay();
- return delay != null && delay > 0;
- }
-
- @Override
- public Integer getDelay() {
- return (delay == null && provider != null) ? provider.getDelay() : delay;
- }
-
- protected synchronized void doExport() {
- if (unexported) {
- throw new IllegalStateException("The service " + interfaceClass.getName() + " has already unexported!");
- }
- if (exported) {
- return;
- }
- exported = true;
-
- if (StringUtils.isEmpty(path)) {
- path = interfaceName;
- }
- doExportUrls();
- }
-
- private void checkRef() {
- // reference should not be null, and is the implementation of the given interface
- if (ref == null) {
- throw new IllegalStateException("ref not allow null!");
- }
- if (!interfaceClass.isInstance(ref)) {
- throw new IllegalStateException("The class "
- + ref.getClass().getName() + " unimplemented interface "
- + interfaceClass + "!");
- }
- }
-
- public synchronized void unexport() {
- if (!exported) {
- return;
- }
- if (unexported) {
- return;
- }
- if (!exporters.isEmpty()) {
- for (Exporter<?> exporter : exporters) {
- try {
- exporter.unexport();
- } catch (Throwable t) {
- logger.warn("Unexpected error occured when unexport " + exporter, t);
- }
- }
- exporters.clear();
- }
- unexported = true;
- }
-
- @SuppressWarnings({"unchecked", "rawtypes"})
- private void doExportUrls() {
- List<URL> registryURLs = loadRegistries(true);
- for (ProtocolConfig protocolConfig : protocols) {
- String pathKey = URL.buildKey(getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), group, version);
- ProviderModel providerModel = new ProviderModel(pathKey, ref, interfaceClass);
- ApplicationModel.initProviderModel(pathKey, providerModel);
- doExportUrlsFor1Protocol(protocolConfig, registryURLs);
- }
- }
-
- private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
- String name = protocolConfig.getName();
- if (StringUtils.isEmpty(name)) {
- name = DUBBO;
- }
-
- Map<String, String> map = new HashMap<String, String>();
- map.put(SIDE_KEY, PROVIDER_SIDE);
-
- appendRuntimeParameters(map);
- appendParameters(map, metrics);
- appendParameters(map, application);
- appendParameters(map, module);
- // remove 'default.' prefix for configs from ProviderConfig
- // appendParameters(map, provider, Constants.DEFAULT_KEY);
- appendParameters(map, provider);
- appendParameters(map, protocolConfig);
- appendParameters(map, this);
- if (CollectionUtils.isNotEmpty(methods)) {
- for (MethodConfig method : methods) {
- appendParameters(map, method, method.getName());
- String retryKey = method.getName() + ".retry";
- if (map.containsKey(retryKey)) {
- String retryValue = map.remove(retryKey);
- if ("false".equals(retryValue)) {
- map.put(method.getName() + ".retries", "0");
- }
- }
- List<ArgumentConfig> arguments = method.getArguments();
- if (CollectionUtils.isNotEmpty(arguments)) {
- for (ArgumentConfig argument : arguments) {
- // convert argument type
- if (argument.getType() != null && argument.getType().length() > 0) {
- Method[] methods = interfaceClass.getMethods();
- // visit all methods
- if (methods != null && methods.length > 0) {
- for (int i = 0; i < methods.length; i++) {
- String methodName = methods[i].getName();
- // target the method, and get its signature
- if (methodName.equals(method.getName())) {
- Class<?>[] argtypes = methods[i].getParameterTypes();
- // one callback in the method
- if (argument.getIndex() != -1) {
- if (argtypes[argument.getIndex()].getName().equals(argument.getType())) {
- appendParameters(map, argument, method.getName() + "." + argument.getIndex());
- } else {
- throw new IllegalArgumentException("Argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
- }
- } else {
- // multiple callbacks in the method
- for (int j = 0; j < argtypes.length; j++) {
- Class<?> argclazz = argtypes[j];
- if (argclazz.getName().equals(argument.getType())) {
- appendParameters(map, argument, method.getName() + "." + j);
- if (argument.getIndex() != -1 && argument.getIndex() != j) {
- throw new IllegalArgumentException("Argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
- }
- }
- }
- }
- }
- }
- }
- } else if (argument.getIndex() != -1) {
- appendParameters(map, argument, method.getName() + "." + argument.getIndex());
- } else {
- throw new IllegalArgumentException("Argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
- }
-
- }
- }
- } // end of methods for
- }
-
- if (ProtocolUtils.isGeneric(generic)) {
- map.put(GENERIC_KEY, generic);
- map.put(METHODS_KEY, ANY_VALUE);
- } else {
- String revision = Version.getVersion(interfaceClass, version);
- if (revision != null && revision.length() > 0) {
- map.put(REVISION_KEY, revision);
- }
-
- String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
- if (methods.length == 0) {
- logger.warn("No method found in service interface " + interfaceClass.getName());
- map.put(METHODS_KEY, ANY_VALUE);
- } else {
- map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
- }
- }
- if (!ConfigUtils.isEmpty(token)) {
- if (ConfigUtils.isDefault(token)) {
- map.put(TOKEN_KEY, UUID.randomUUID().toString());
- } else {
- map.put(TOKEN_KEY, token);
- }
- }
- // export service
- String host = this.findConfigedHosts(protocolConfig, registryURLs, map);
- Integer port = this.findConfigedPorts(protocolConfig, name, map);
- URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map);
-
- if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
- .hasExtension(url.getProtocol())) {
- url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
- .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
- }
-
- String scope = url.getParameter(SCOPE_KEY);
- // don't export when none is configured
- if (!SCOPE_NONE.equalsIgnoreCase(scope)) {
-
- // export to local if the config is not remote (export to remote only when config is remote)
- if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) {
- exportLocal(url);
- }
- // export to remote if the config is not local (export to local only when config is local)
- if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
- if (!isOnlyInJvm() && logger.isInfoEnabled()) {
- logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
- }
- if (CollectionUtils.isNotEmpty(registryURLs)) {
- for (URL registryURL : registryURLs) {
- //if protocol is only injvm ,not register
- if (LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
- continue;
- }
- url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY));
- URL monitorUrl = loadMonitor(registryURL);
- if (monitorUrl != null) {
- url = url.addParameterAndEncoded(MONITOR_KEY, monitorUrl.toFullString());
- }
- if (logger.isInfoEnabled()) {
- logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
- }
-
- // For providers, this is used to enable custom proxy to generate invoker
- String proxy = url.getParameter(PROXY_KEY);
- if (StringUtils.isNotEmpty(proxy)) {
- registryURL = registryURL.addParameter(PROXY_KEY, proxy);
- }
-
- Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
- DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
-
- Exporter<?> exporter = protocol.export(wrapperInvoker);
- exporters.add(exporter);
- }
- } else {
- Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
- DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
-
- Exporter<?> exporter = protocol.export(wrapperInvoker);
- exporters.add(exporter);
- }
- /**
- * @since 2.7.0
- * ServiceData Store
- */
- MetadataReportService metadataReportService = null;
- if ((metadataReportService = getMetadataReportService()) != null) {
- metadataReportService.publishProvider(url);
- }
- }
- }
- this.urls.add(url);
- }
-
- @SuppressWarnings({"unchecked", "rawtypes"})
- /**
- * always export injvm
- */
- private void exportLocal(URL url) {
- URL local = URLBuilder.from(url)
- .setProtocol(LOCAL_PROTOCOL)
- .setHost(LOCALHOST_VALUE)
- .setPort(0)
- .build();
- Exporter<?> exporter = protocol.export(
- PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, local));
- exporters.add(exporter);
- logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry url : " + local);
- }
-
- private Optional<String> getContextPath(ProtocolConfig protocolConfig) {
- String contextPath = protocolConfig.getContextpath();
- if (StringUtils.isEmpty(contextPath) && provider != null) {
- contextPath = provider.getContextpath();
- }
- return Optional.ofNullable(contextPath);
- }
-
- protected Class getServiceClass(T ref) {
- return ref.getClass();
- }
-
- /**
- * Register & bind IP address for service provider, can be configured separately.
- * Configuration priority: environment variables -> java system properties -> host property in config file ->
- * /etc/hosts -> default network address -> first available network address
- *
- * @param protocolConfig
- * @param registryURLs
- * @param map
- * @return
- */
- private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> registryURLs, Map<String, String> map) {
- boolean anyhost = false;
-
- String hostToBind = getValueFromConfig(protocolConfig, DUBBO_IP_TO_BIND);
- if (hostToBind != null && hostToBind.length() > 0 && isInvalidLocalHost(hostToBind)) {
- throw new IllegalArgumentException("Specified invalid bind ip from property:" + DUBBO_IP_TO_BIND + ", value:" + hostToBind);
- }
-
- // if bind ip is not found in environment, keep looking up
- if (StringUtils.isEmpty(hostToBind)) {
- hostToBind = protocolConfig.getHost();
- if (provider != null && StringUtils.isEmpty(hostToBind)) {
- hostToBind = provider.getHost();
- }
- if (isInvalidLocalHost(hostToBind)) {
- anyhost = true;
- try {
- hostToBind = InetAddress.getLocalHost().getHostAddress();
- } catch (UnknownHostException e) {
- logger.warn(e.getMessage(), e);
- }
- if (isInvalidLocalHost(hostToBind)) {
- if (CollectionUtils.isNotEmpty(registryURLs)) {
- for (URL registryURL : registryURLs) {
- if (MULTICAST.equalsIgnoreCase(registryURL.getParameter("registry"))) {
- // skip multicast registry since we cannot connect to it via Socket
- continue;
- }
- try (Socket socket = new Socket()) {
- SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
- socket.connect(addr, 1000);
- hostToBind = socket.getLocalAddress().getHostAddress();
- break;
- } catch (Exception e) {
- logger.warn(e.getMessage(), e);
- }
- }
- }
- if (isInvalidLocalHost(hostToBind)) {
- hostToBind = getLocalHost();
- }
- }
- }
- }
-
- map.put(Constants.BIND_IP_KEY, hostToBind);
-
- // registry ip is not used for bind ip by default
- String hostToRegistry = getValueFromConfig(protocolConfig, DUBBO_IP_TO_REGISTRY);
- if (hostToRegistry != null && hostToRegistry.length() > 0 && isInvalidLocalHost(hostToRegistry)) {
- throw new IllegalArgumentException("Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
- } else if (StringUtils.isEmpty(hostToRegistry)) {
- // bind ip is used as registry ip by default
- hostToRegistry = hostToBind;
- }
-
- map.put(ANYHOST_KEY, String.valueOf(anyhost));
-
- return hostToRegistry;
- }
-
- /**
- * Register port and bind port for the provider, can be configured separately
- * Configuration priority: environment variable -> java system properties -> port property in protocol config file
- * -> protocol default port
- *
- * @param protocolConfig
- * @param name
- * @return
- */
- private Integer findConfigedPorts(ProtocolConfig protocolConfig, String name, Map<String, String> map) {
- Integer portToBind = null;
-
- // parse bind port from environment
- String port = getValueFromConfig(protocolConfig, DUBBO_PORT_TO_BIND);
- portToBind = parsePort(port);
-
- // if there's no bind port found from environment, keep looking up.
- if (portToBind == null) {
- portToBind = protocolConfig.getPort();
- if (provider != null && (portToBind == null || portToBind == 0)) {
- portToBind = provider.getPort();
- }
- final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
- if (portToBind == null || portToBind == 0) {
- portToBind = defaultPort;
- }
- if (portToBind <= 0) {
- portToBind = getRandomPort(name);
- if (portToBind == null || portToBind < 0) {
- portToBind = getAvailablePort(defaultPort);
- putRandomPort(name, portToBind);
- }
- }
- }
-
- // save bind port, used as url's key later
- map.put(Constants.BIND_PORT_KEY, String.valueOf(portToBind));
-
- // registry port, not used as bind port by default
- String portToRegistryStr = getValueFromConfig(protocolConfig, DUBBO_PORT_TO_REGISTRY);
- Integer portToRegistry = parsePort(portToRegistryStr);
- if (portToRegistry == null) {
- portToRegistry = portToBind;
- }
-
- return portToRegistry;
- }
-
- private Integer parsePort(String configPort) {
- Integer port = null;
- if (configPort != null && configPort.length() > 0) {
- try {
- Integer intPort = Integer.parseInt(configPort);
- if (isInvalidPort(intPort)) {
- throw new IllegalArgumentException("Specified invalid port from env value:" + configPort);
- }
- port = intPort;
- } catch (Exception e) {
- throw new IllegalArgumentException("Specified invalid port from env value:" + configPort);
- }
- }
- return port;
- }
-
- private String getValueFromConfig(ProtocolConfig protocolConfig, String key) {
- String protocolPrefix = protocolConfig.getName().toUpperCase() + "_";
- String port = ConfigUtils.getSystemProperty(protocolPrefix + key);
- if (StringUtils.isEmpty(port)) {
- port = ConfigUtils.getSystemProperty(key);
- }
- return port;
- }
-
- private void completeCompoundConfigs() {
- if (provider != null) {
- if (application == null) {
- setApplication(provider.getApplication());
- }
- if (module == null) {
- setModule(provider.getModule());
- }
- if (registries == null) {
- setRegistries(provider.getRegistries());
- }
- if (monitor == null) {
- setMonitor(provider.getMonitor());
- }
- if (protocols == null) {
- setProtocols(provider.getProtocols());
- }
- if (configCenter == null) {
- setConfigCenter(provider.getConfigCenter());
- }
- }
- if (module != null) {
- if (registries == null) {
- setRegistries(module.getRegistries());
- }
- if (monitor == null) {
- setMonitor(module.getMonitor());
- }
- }
- if (application != null) {
- if (registries == null) {
- setRegistries(application.getRegistries());
- }
- if (monitor == null) {
- setMonitor(application.getMonitor());
- }
- }
- }
-
- private void checkDefault() {
- createProviderIfAbsent();
- }
-
- private void createProviderIfAbsent() {
- if (provider != null) {
- return;
- }
- setProvider(
- ConfigManager.getInstance()
- .getDefaultProvider()
- .orElseGet(() -> {
- ProviderConfig providerConfig = new ProviderConfig();
- providerConfig.refresh();
- return providerConfig;
- })
- );
- }
-
- private void checkProtocol() {
- if (CollectionUtils.isEmpty(protocols) && provider != null) {
- setProtocols(provider.getProtocols());
- }
- convertProtocolIdsToProtocols();
- }
-
- private void convertProtocolIdsToProtocols() {
- if (StringUtils.isEmpty(protocolIds) && CollectionUtils.isEmpty(protocols)) {
- List<String> configedProtocols = new ArrayList<>();
- configedProtocols.addAll(getSubProperties(Environment.getInstance()
- .getExternalConfigurationMap(), PROTOCOLS_SUFFIX));
- configedProtocols.addAll(getSubProperties(Environment.getInstance()
- .getAppExternalConfigurationMap(), PROTOCOLS_SUFFIX));
-
- protocolIds = String.join(",", configedProtocols);
- }
-
- if (StringUtils.isEmpty(protocolIds)) {
- if (CollectionUtils.isEmpty(protocols)) {
- setProtocols(
- ConfigManager.getInstance().getDefaultProtocols()
- .filter(CollectionUtils::isNotEmpty)
- .orElseGet(() -> {
- ProtocolConfig protocolConfig = new ProtocolConfig();
- protocolConfig.refresh();
- return new ArrayList<>(Arrays.asList(protocolConfig));
- })
- );
- }
- } else {
- String[] arr = COMMA_SPLIT_PATTERN.split(protocolIds);
- List<ProtocolConfig> tmpProtocols = CollectionUtils.isNotEmpty(protocols) ? protocols : new ArrayList<>();
- Arrays.stream(arr).forEach(id -> {
- if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
- tmpProtocols.add(ConfigManager.getInstance().getProtocol(id).orElseGet(() -> {
- ProtocolConfig protocolConfig = new ProtocolConfig();
- protocolConfig.setId(id);
- protocolConfig.refresh();
- return protocolConfig;
- }));
- }
- });
- if (tmpProtocols.size() > arr.length) {
- throw new IllegalStateException("Too much protocols found, the protocols comply to this service are :" + protocolIds + " but got " + protocols
- .size() + " registries!");
- }
- setProtocols(tmpProtocols);
- }
- }
-
- public Class<?> getInterfaceClass() {
- if (interfaceClass != null) {
- return interfaceClass;
- }
- if (ref instanceof GenericService) {
- return GenericService.class;
- }
- try {
- if (interfaceName != null && interfaceName.length() > 0) {
- this.interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
- .getContextClassLoader());
- }
- } catch (ClassNotFoundException t) {
- throw new IllegalStateException(t.getMessage(), t);
- }
- return interfaceClass;
- }
-
- /**
- * @param interfaceClass
- * @see #setInterface(Class)
- * @deprecated
- */
- public void setInterfaceClass(Class<?> interfaceClass) {
- setInterface(interfaceClass);
- }
-
- public String getInterface() {
- return interfaceName;
- }
-
- public void setInterface(Class<?> interfaceClass) {
- if (interfaceClass != null && !interfaceClass.isInterface()) {
- throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
- }
- this.interfaceClass = interfaceClass;
- setInterface(interfaceClass == null ? null : interfaceClass.getName());
- }
-
- public void setInterface(String interfaceName) {
- this.interfaceName = interfaceName;
- if (StringUtils.isEmpty(id)) {
- id = interfaceName;
- }
- }
-
- public T getRef() {
- return ref;
- }
-
- public void setRef(T ref) {
- this.ref = ref;
- }
-
- @Parameter(excluded = true)
- public String getPath() {
- return path;
- }
-
- public void setPath(String path) {
- checkPathName(PATH_KEY, path);
- this.path = path;
- }
-
- public List<MethodConfig> getMethods() {
- return methods;
- }
-
- // ======== Deprecated ========
-
- @SuppressWarnings("unchecked")
- public void setMethods(List<? extends MethodConfig> methods) {
- this.methods = (List<MethodConfig>) methods;
- }
-
- public ProviderConfig getProvider() {
- return provider;
- }
-
- public void setProvider(ProviderConfig provider) {
- ConfigManager.getInstance().addProvider(provider);
- this.provider = provider;
- }
-
- @Parameter(excluded = true)
- public String getProviderIds() {
- return providerIds;
- }
-
- public void setProviderIds(String providerIds) {
- this.providerIds = providerIds;
- }
-
- public String getGeneric() {
- return generic;
- }
-
- public void setGeneric(String generic) {
- if (StringUtils.isEmpty(generic)) {
- return;
- }
- if (ProtocolUtils.isGeneric(generic)) {
- this.generic = generic;
- } else {
- throw new IllegalArgumentException("Unsupported generic type " + generic);
- }
- }
-
- @Override
- public void setMock(Boolean mock) {
- throw new IllegalArgumentException("mock doesn't support on provider side");
- }
-
- @Override
- public void setMock(String mock) {
- throw new IllegalArgumentException("mock doesn't support on provider side");
- }
-
- public List<URL> getExportedUrls() {
- return urls;
- }
-
- /**
- * @deprecated Replace to getProtocols()
- */
- @Deprecated
- public List<ProviderConfig> getProviders() {
- return convertProtocolToProvider(protocols);
- }
-
- /**
- * @deprecated Replace to setProtocols()
- */
- @Deprecated
- public void setProviders(List<ProviderConfig> providers) {
- this.protocols = convertProviderToProtocol(providers);
- }
-
- @Override
- @Parameter(excluded = true)
- public String getPrefix() {
- return DUBBO + ".service." + interfaceName;
- }
-}
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.dubbo.config;
+
+import org.apache.dubbo.common.URL;
+import org.apache.dubbo.common.URLBuilder;
+import org.apache.dubbo.common.Version;
+import org.apache.dubbo.common.bytecode.Wrapper;
+import org.apache.dubbo.common.extension.ExtensionLoader;
+import org.apache.dubbo.common.utils.ClassUtils;
+import org.apache.dubbo.common.utils.CollectionUtils;
+import org.apache.dubbo.common.utils.ConfigUtils;
+import org.apache.dubbo.common.utils.NamedThreadFactory;
+import org.apache.dubbo.common.utils.StringUtils;
+import org.apache.dubbo.config.annotation.Service;
+import org.apache.dubbo.config.context.ConfigManager;
+import org.apache.dubbo.config.event.ServiceConfigExportedEvent;
+import org.apache.dubbo.config.event.ServiceConfigUnexportedEvent;
+import org.apache.dubbo.config.invoker.DelegateProviderMetaDataInvoker;
+import org.apache.dubbo.config.support.Parameter;
+import org.apache.dubbo.event.Event;
+import org.apache.dubbo.event.EventDispatcher;
+import org.apache.dubbo.metadata.WritableMetadataService;
+import org.apache.dubbo.remoting.Constants;
+import org.apache.dubbo.rpc.Exporter;
+import org.apache.dubbo.rpc.Invoker;
+import org.apache.dubbo.rpc.Protocol;
+import org.apache.dubbo.rpc.ProxyFactory;
+import org.apache.dubbo.rpc.cluster.ConfiguratorFactory;
+import org.apache.dubbo.rpc.model.ApplicationModel;
+import org.apache.dubbo.rpc.model.ProviderModel;
+import org.apache.dubbo.rpc.service.GenericService;
+import org.apache.dubbo.rpc.support.ProtocolUtils;
+
+import java.lang.reflect.Method;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Socket;
+import java.net.SocketAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.UUID;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+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.COMMA_SPLIT_PATTERN;
+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_DEFAULT;
+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.PATH_KEY;
+import static org.apache.dubbo.common.constants.CommonConstants.PROVIDER_SIDE;
+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;
+import static org.apache.dubbo.common.utils.NetUtils.getAvailablePort;
+import static org.apache.dubbo.common.utils.NetUtils.getLocalHost;
+import static org.apache.dubbo.common.utils.NetUtils.isInvalidLocalHost;
+import static org.apache.dubbo.common.utils.NetUtils.isInvalidPort;
+import static org.apache.dubbo.config.Constants.DUBBO_IP_TO_REGISTRY;
+import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_BIND;
+import static org.apache.dubbo.config.Constants.DUBBO_PORT_TO_REGISTRY;
+import static org.apache.dubbo.config.Constants.MULTICAST;
+import static org.apache.dubbo.config.Constants.SCOPE_NONE;
+import static org.apache.dubbo.rpc.Constants.GENERIC_KEY;
+import static org.apache.dubbo.rpc.Constants.LOCAL_PROTOCOL;
+import static org.apache.dubbo.rpc.Constants.PROXY_KEY;
+import static org.apache.dubbo.rpc.Constants.SCOPE_KEY;
+import static org.apache.dubbo.rpc.Constants.SCOPE_LOCAL;
+import static org.apache.dubbo.rpc.Constants.SCOPE_REMOTE;
+import static org.apache.dubbo.rpc.Constants.TOKEN_KEY;
+import static org.apache.dubbo.rpc.cluster.Constants.EXPORT_KEY;
+
+/**
+ * ServiceConfig
+ *
+ * @export
+ */
+public class ServiceConfig<T> extends AbstractServiceConfig {
+
+ private static final long serialVersionUID = 3033787999037024738L;
+
+ /**
+ * The {@link Protocol} implementation with adaptive functionality,it will be different in different scenarios.
+ * A particular {@link Protocol} implementation is determined by the protocol attribute in the {@link URL}.
+ * For example:
+ *
+ * <li>when the url is registry://224.5.6.7:1234/org.apache.dubbo.registry.RegistryService?application=dubbo-sample,
+ * then the protocol is <b>RegistryProtocol</b></li>
+ *
+ * <li>when the url is dubbo://224.5.6.7:1234/org.apache.dubbo.config.api.DemoService?application=dubbo-sample, then
+ * the protocol is <b>DubboProtocol</b></li>
+ * <p>
+ * Actually,when the {@link ExtensionLoader} init the {@link Protocol} instants,it will automatically wraps two
+ * layers, and eventually will get a <b>ProtocolFilterWrapper</b> or <b>ProtocolListenerWrapper</b>
+ */
+ private static final Protocol protocol = ExtensionLoader.getExtensionLoader(Protocol.class).getAdaptiveExtension();
+
+ /**
+ * A {@link ProxyFactory} implementation that will generate a exported service proxy,the JavassistProxyFactory is its
+ * default implementation
+ */
+ private static final ProxyFactory PROXY_FACTORY = ExtensionLoader.getExtensionLoader(ProxyFactory.class).getAdaptiveExtension();
+
+ /**
+ * A random port cache, the different protocols who has no port specified have different random port
+ */
+ private static final Map<String, Integer> RANDOM_PORT_MAP = new HashMap<String, Integer>();
+
+ /**
+ * A delayed exposure service timer
+ */
+ private static final ScheduledExecutorService DELAY_EXPORT_EXECUTOR = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("DubboServiceDelayExporter", true));
+
+ /**
+ * The urls of the services exported
+ */
+ private final List<URL> urls = new ArrayList<URL>();
+
+ /**
+ * The exported services
+ */
+ private final List<Exporter<?>> exporters = new ArrayList<Exporter<?>>();
+
+ /**
+ * The interface name of the exported service
+ */
+ private String interfaceName;
+
+ /**
+ * The interface class of the exported service
+ */
+ private Class<?> interfaceClass;
+
+ /**
+ * The reference of the interface implementation
+ */
+ private T ref;
+
+ /**
+ * The service name
+ */
+ private String path;
+
+ /**
+ * The method configuration
+ */
+ private List<MethodConfig> methods;
+
+ /**
+ * The provider configuration
+ */
+ private ProviderConfig provider;
+
+ /**
+ * The providerIds
+ */
+ private String providerIds;
+
+ /**
+ * Whether the provider has been exported
+ */
+ private transient volatile boolean exported;
+
+ /**
+ * The flag whether a service has unexported ,if the method unexported is invoked, the value is true
+ */
+ private transient volatile boolean unexported;
+
+ /**
+ * whether it is a GenericService
+ */
+ private volatile String generic;
+
+ /**
+ * @since 2.7.4
+ */
+ private final EventDispatcher eventDispatcher = EventDispatcher.getDefaultExtension();
+
+
+ public ServiceConfig() {
+ }
+
+ public ServiceConfig(Service service) {
+ appendAnnotation(Service.class, service);
+ setMethods(MethodConfig.constructMethodConfig(service.methods()));
+ }
+
+ @Deprecated
+ private static List<ProtocolConfig> convertProviderToProtocol(List<ProviderConfig> providers) {
+ if (CollectionUtils.isEmpty(providers)) {
+ return null;
+ }
+ List<ProtocolConfig> protocols = new ArrayList<ProtocolConfig>(providers.size());
+ for (ProviderConfig provider : providers) {
+ protocols.add(convertProviderToProtocol(provider));
+ }
+ return protocols;
+ }
+
+ @Deprecated
+ private static List<ProviderConfig> convertProtocolToProvider(List<ProtocolConfig> protocols) {
+ if (CollectionUtils.isEmpty(protocols)) {
+ return null;
+ }
+ List<ProviderConfig> providers = new ArrayList<ProviderConfig>(protocols.size());
+ for (ProtocolConfig provider : protocols) {
+ providers.add(convertProtocolToProvider(provider));
+ }
+ return providers;
+ }
+
+ @Deprecated
+ private static ProtocolConfig convertProviderToProtocol(ProviderConfig provider) {
+ ProtocolConfig protocol = new ProtocolConfig();
+ protocol.setName(provider.getProtocol().getName());
+ protocol.setServer(provider.getServer());
+ protocol.setClient(provider.getClient());
+ protocol.setCodec(provider.getCodec());
+ protocol.setHost(provider.getHost());
+ protocol.setPort(provider.getPort());
+ protocol.setPath(provider.getPath());
+ protocol.setPayload(provider.getPayload());
+ protocol.setThreads(provider.getThreads());
+ protocol.setParameters(provider.getParameters());
+ return protocol;
+ }
+
+ @Deprecated
+ private static ProviderConfig convertProtocolToProvider(ProtocolConfig protocol) {
+ ProviderConfig provider = new ProviderConfig();
+ provider.setProtocol(protocol);
+ provider.setServer(protocol.getServer());
+ provider.setClient(protocol.getClient());
+ provider.setCodec(protocol.getCodec());
+ provider.setHost(protocol.getHost());
+ provider.setPort(protocol.getPort());
+ provider.setPath(protocol.getPath());
+ provider.setPayload(protocol.getPayload());
+ provider.setThreads(protocol.getThreads());
+ provider.setParameters(protocol.getParameters());
+ return provider;
+ }
+
+ private static Integer getRandomPort(String protocol) {
+ protocol = protocol.toLowerCase();
+ return RANDOM_PORT_MAP.getOrDefault(protocol, Integer.MIN_VALUE);
+ }
+
+ private static void putRandomPort(String protocol, Integer port) {
+ protocol = protocol.toLowerCase();
+ if (!RANDOM_PORT_MAP.containsKey(protocol)) {
+ RANDOM_PORT_MAP.put(protocol, port);
+ logger.warn("Use random available port(" + port + ") for protocol " + protocol);
+ }
+ }
+
+ public URL toUrl() {
+ return urls.isEmpty() ? null : urls.iterator().next();
+ }
+
+ public List<URL> toUrls() {
+ return urls;
+ }
+
+ @Parameter(excluded = true)
+ public boolean isExported() {
+ return exported;
+ }
+
+ @Parameter(excluded = true)
+ public boolean isUnexported() {
+ return unexported;
+ }
+
+ public void checkAndUpdateSubConfigs() {
+ // Use default configs defined explicitly on global scope
+ completeCompoundConfigs();
+ checkDefault();
+ checkProtocol();
+ checkApplication();
+ // if protocol is not injvm checkRegistry
+ if (!isOnlyInJvm()) {
+ checkRegistry();
+ }
+ this.refresh();
+ checkMetadataReport();
+
+ if (StringUtils.isEmpty(interfaceName)) {
+ throw new IllegalStateException("<dubbo:service interface=\"\" /> interface not allow null!");
+ }
+
+ if (ref instanceof GenericService) {
+ interfaceClass = GenericService.class;
+ if (StringUtils.isEmpty(generic)) {
+ generic = Boolean.TRUE.toString();
+ }
+ } else {
+ try {
+ interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
+ .getContextClassLoader());
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ checkInterfaceAndMethods(interfaceClass, methods);
+ checkRef();
+ generic = Boolean.FALSE.toString();
+ }
+ if (local != null) {
+ if ("true".equals(local)) {
+ local = interfaceName + "Local";
+ }
+ Class<?> localClass;
+ try {
+ localClass = ClassUtils.forNameWithThreadContextClassLoader(local);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ if (!interfaceClass.isAssignableFrom(localClass)) {
+ throw new IllegalStateException("The local implementation class " + localClass.getName() + " not implement interface " + interfaceName);
+ }
+ }
+ if (stub != null) {
+ if ("true".equals(stub)) {
+ stub = interfaceName + "Stub";
+ }
+ Class<?> stubClass;
+ try {
+ stubClass = ClassUtils.forNameWithThreadContextClassLoader(stub);
+ } catch (ClassNotFoundException e) {
+ throw new IllegalStateException(e.getMessage(), e);
+ }
+ if (!interfaceClass.isAssignableFrom(stubClass)) {
+ throw new IllegalStateException("The stub implementation class " + stubClass.getName() + " not implement interface " + interfaceName);
+ }
+ }
+ checkStubAndLocal(interfaceClass);
+ checkMock(interfaceClass);
+ }
+
+ /**
+ * Determine if it is injvm
+ *
+ * @return
+ */
+ private boolean isOnlyInJvm() {
+ return getProtocols().size() == 1 && LOCAL_PROTOCOL.equalsIgnoreCase(getProtocols().get(0).getName());
+ }
+
+ public synchronized void export() {
+ checkAndUpdateSubConfigs();
+
+ if (!shouldExport()) {
+ return;
+ }
+
+ if (shouldDelay()) {
+ DELAY_EXPORT_EXECUTOR.schedule(this::doExport, getDelay(), TimeUnit.MILLISECONDS);
+ } else {
+ doExport();
+ }
+ }
+
+ private boolean shouldExport() {
+ Boolean export = getExport();
+ // default value is true
+ return export == null ? true : export;
+ }
+
+ @Override
+ public Boolean getExport() {
+ return (export == null && provider != null) ? provider.getExport() : export;
+ }
+
+ private boolean shouldDelay() {
+ Integer delay = getDelay();
+ return delay != null && delay > 0;
+ }
+
+ @Override
+ public Integer getDelay() {
+ return (delay == null && provider != null) ? provider.getDelay() : delay;
+ }
+
+ protected synchronized void doExport() {
+ if (unexported) {
+ throw new IllegalStateException("The service " + interfaceClass.getName() + " has already unexported!");
+ }
+ if (exported) {
+ return;
+ }
+ exported = true;
+
+ if (StringUtils.isEmpty(path)) {
+ path = interfaceName;
+ }
+ doExportUrls();
+
+ // dispatch a ServiceConfigExportedEvent since 2.7.4
+ dispatch(new ServiceConfigExportedEvent(this));
+ }
+
+ private void checkRef() {
+ // reference should not be null, and is the implementation of the given interface
+ if (ref == null) {
+ throw new IllegalStateException("ref not allow null!");
+ }
+ if (!interfaceClass.isInstance(ref)) {
+ throw new IllegalStateException("The class "
+ + ref.getClass().getName() + " unimplemented interface "
+ + interfaceClass + "!");
+ }
+ }
+
+ public synchronized void unexport() {
+ if (!exported) {
+ return;
+ }
+ if (unexported) {
+ return;
+ }
+ if (!exporters.isEmpty()) {
+ for (Exporter<?> exporter : exporters) {
+ try {
+ exporter.unexport();
+ } catch (Throwable t) {
+ logger.warn("Unexpected error occured when unexport " + exporter, t);
+ }
+ }
+ exporters.clear();
+ }
+ unexported = true;
+
+ // dispatch a ServiceConfigUnExportedEvent since 2.7.4
+ dispatch(new ServiceConfigUnexportedEvent(this));
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ private void doExportUrls() {
+ List<URL> registryURLs = loadRegistries(true);
+ for (ProtocolConfig protocolConfig : protocols) {
+ String pathKey = URL.buildKey(getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), group, version);
+ ProviderModel providerModel = new ProviderModel(pathKey, ref, interfaceClass);
+ ApplicationModel.initProviderModel(pathKey, providerModel);
+ doExportUrlsFor1Protocol(protocolConfig, registryURLs);
+ }
+ }
+
+ private void doExportUrlsFor1Protocol(ProtocolConfig protocolConfig, List<URL> registryURLs) {
+ String name = protocolConfig.getName();
+ if (StringUtils.isEmpty(name)) {
+ name = DUBBO;
+ }
+
+ Map<String, String> map = new HashMap<String, String>();
+ map.put(SIDE_KEY, PROVIDER_SIDE);
+
+ appendRuntimeParameters(map);
+ appendParameters(map, metrics);
+ appendParameters(map, application);
+ appendParameters(map, module);
+ // remove 'default.' prefix for configs from ProviderConfig
+ // appendParameters(map, provider, Constants.DEFAULT_KEY);
+ appendParameters(map, provider);
+ appendParameters(map, protocolConfig);
+ appendParameters(map, this);
+ if (CollectionUtils.isNotEmpty(methods)) {
+ for (MethodConfig method : methods) {
+ appendParameters(map, method, method.getName());
+ String retryKey = method.getName() + ".retry";
+ if (map.containsKey(retryKey)) {
+ String retryValue = map.remove(retryKey);
+ if ("false".equals(retryValue)) {
+ map.put(method.getName() + ".retries", "0");
+ }
+ }
+ List<ArgumentConfig> arguments = method.getArguments();
+ if (CollectionUtils.isNotEmpty(arguments)) {
+ for (ArgumentConfig argument : arguments) {
+ // convert argument type
+ if (argument.getType() != null && argument.getType().length() > 0) {
+ Method[] methods = interfaceClass.getMethods();
+ // visit all methods
+ if (methods != null && methods.length > 0) {
+ for (int i = 0; i < methods.length; i++) {
+ String methodName = methods[i].getName();
+ // target the method, and get its signature
+ if (methodName.equals(method.getName())) {
+ Class<?>[] argtypes = methods[i].getParameterTypes();
+ // one callback in the method
+ if (argument.getIndex() != -1) {
+ if (argtypes[argument.getIndex()].getName().equals(argument.getType())) {
+ appendParameters(map, argument, method.getName() + "." + argument.getIndex());
+ } else {
+ throw new IllegalArgumentException("Argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
+ }
+ } else {
+ // multiple callbacks in the method
+ for (int j = 0; j < argtypes.length; j++) {
+ Class<?> argclazz = argtypes[j];
+ if (argclazz.getName().equals(argument.getType())) {
+ appendParameters(map, argument, method.getName() + "." + j);
+ if (argument.getIndex() != -1 && argument.getIndex() != j) {
+ throw new IllegalArgumentException("Argument config error : the index attribute and type attribute not match :index :" + argument.getIndex() + ", type:" + argument.getType());
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ } else if (argument.getIndex() != -1) {
+ appendParameters(map, argument, method.getName() + "." + argument.getIndex());
+ } else {
+ throw new IllegalArgumentException("Argument config must set index or type attribute.eg: <dubbo:argument index='0' .../> or <dubbo:argument type=xxx .../>");
+ }
+
+ }
+ }
+ } // end of methods for
+ }
+
+ if (ProtocolUtils.isGeneric(generic)) {
+ map.put(GENERIC_KEY, generic);
+ map.put(METHODS_KEY, ANY_VALUE);
+ } else {
+ String revision = Version.getVersion(interfaceClass, version);
+ if (revision != null && revision.length() > 0) {
+ map.put(REVISION_KEY, revision);
+ }
+
+ String[] methods = Wrapper.getWrapper(interfaceClass).getMethodNames();
+ if (methods.length == 0) {
+ logger.warn("No method found in service interface " + interfaceClass.getName());
+ map.put(METHODS_KEY, ANY_VALUE);
+ } else {
+ map.put(METHODS_KEY, StringUtils.join(new HashSet<String>(Arrays.asList(methods)), ","));
+ }
+ }
+ if (!ConfigUtils.isEmpty(token)) {
+ if (ConfigUtils.isDefault(token)) {
+ map.put(TOKEN_KEY, UUID.randomUUID().toString());
+ } else {
+ map.put(TOKEN_KEY, token);
+ }
+ }
+ // export service
+ String host = this.findConfigedHosts(protocolConfig, registryURLs, map);
+ Integer port = this.findConfigedPorts(protocolConfig, name, map);
+ URL url = new URL(name, host, port, getContextPath(protocolConfig).map(p -> p + "/" + path).orElse(path), map);
+
+ if (ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
+ .hasExtension(url.getProtocol())) {
+ url = ExtensionLoader.getExtensionLoader(ConfiguratorFactory.class)
+ .getExtension(url.getProtocol()).getConfigurator(url).configure(url);
+ }
+
+ String scope = url.getParameter(SCOPE_KEY);
+ // don't export when none is configured
+ if (!SCOPE_NONE.equalsIgnoreCase(scope)) {
+
+ // export to local if the config is not remote (export to remote only when config is remote)
+ if (!SCOPE_REMOTE.equalsIgnoreCase(scope)) {
+ exportLocal(url);
+ }
+ // export to remote if the config is not local (export to local only when config is local)
+ if (!SCOPE_LOCAL.equalsIgnoreCase(scope)) {
+ if (!isOnlyInJvm() && logger.isInfoEnabled()) {
+ logger.info("Export dubbo service " + interfaceClass.getName() + " to url " + url);
+ }
+ if (CollectionUtils.isNotEmpty(registryURLs)) {
+ for (URL registryURL : registryURLs) {
+ //if protocol is only injvm ,not register
+ if (LOCAL_PROTOCOL.equalsIgnoreCase(url.getProtocol())) {
+ continue;
+ }
+ url = url.addParameterIfAbsent(DYNAMIC_KEY, registryURL.getParameter(DYNAMIC_KEY));
+ URL monitorUrl = loadMonitor(registryURL);
+ if (monitorUrl != null) {
+ url = url.addParameterAndEncoded(MONITOR_KEY, monitorUrl.toFullString());
+ }
+ if (logger.isInfoEnabled()) {
+ logger.info("Register dubbo service " + interfaceClass.getName() + " url " + url + " to registry " + registryURL);
+ }
+
+ // For providers, this is used to enable custom proxy to generate invoker
+ String proxy = url.getParameter(PROXY_KEY);
+ if (StringUtils.isNotEmpty(proxy)) {
+ registryURL = registryURL.addParameter(PROXY_KEY, proxy);
+ }
+
+ Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, registryURL.addParameterAndEncoded(EXPORT_KEY, url.toFullString()));
+ DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
+
+ Exporter<?> exporter = protocol.export(wrapperInvoker);
+ exporters.add(exporter);
+ }
+ } else {
+ Invoker<?> invoker = PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, url);
+ DelegateProviderMetaDataInvoker wrapperInvoker = new DelegateProviderMetaDataInvoker(invoker, this);
+
+ Exporter<?> exporter = protocol.export(wrapperInvoker);
+ exporters.add(exporter);
+ }
+ /**
+ * @since 2.7.0
+ * ServiceData Store
+ */
+ WritableMetadataService metadataService = WritableMetadataService.getExtension(url.getParameter(METADATA_KEY, METADATA_DEFAULT));
+ if (metadataService != null) {
+ metadataService.publishServiceDefinition(url);
+ }
+ }
+ }
+ this.urls.add(url);
+ }
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ /**
+ * always export injvm
+ */
+ private void exportLocal(URL url) {
+ URL local = URLBuilder.from(url)
+ .setProtocol(LOCAL_PROTOCOL)
+ .setHost(LOCALHOST_VALUE)
+ .setPort(0)
+ .build();
+ Exporter<?> exporter = protocol.export(
+ PROXY_FACTORY.getInvoker(ref, (Class) interfaceClass, local));
+ exporters.add(exporter);
+ logger.info("Export dubbo service " + interfaceClass.getName() + " to local registry url : " + local);
+ }
+
+ private Optional<String> getContextPath(ProtocolConfig protocolConfig) {
+ String contextPath = protocolConfig.getContextpath();
+ if (StringUtils.isEmpty(contextPath) && provider != null) {
+ contextPath = provider.getContextpath();
+ }
+ return Optional.ofNullable(contextPath);
+ }
+
+ protected Class getServiceClass(T ref) {
+ return ref.getClass();
+ }
+
+ /**
+ * Register & bind IP address for service provider, can be configured separately.
+ * Configuration priority: environment variables -> java system properties -> host property in config file ->
+ * /etc/hosts -> default network address -> first available network address
+ *
+ * @param protocolConfig
+ * @param registryURLs
+ * @param map
+ * @return
+ */
+ private String findConfigedHosts(ProtocolConfig protocolConfig, List<URL> registryURLs, Map<String, String> map) {
+ boolean anyhost = false;
+
+ String hostToBind = getValueFromConfig(protocolConfig, DUBBO_IP_TO_BIND);
+ if (hostToBind != null && hostToBind.length() > 0 && isInvalidLocalHost(hostToBind)) {
+ throw new IllegalArgumentException("Specified invalid bind ip from property:" + DUBBO_IP_TO_BIND + ", value:" + hostToBind);
+ }
+
+ // if bind ip is not found in environment, keep looking up
+ if (StringUtils.isEmpty(hostToBind)) {
+ hostToBind = protocolConfig.getHost();
+ if (provider != null && StringUtils.isEmpty(hostToBind)) {
+ hostToBind = provider.getHost();
+ }
+ if (isInvalidLocalHost(hostToBind)) {
+ anyhost = true;
+ try {
+ hostToBind = InetAddress.getLocalHost().getHostAddress();
+ } catch (UnknownHostException e) {
+ logger.warn(e.getMessage(), e);
+ }
+ if (isInvalidLocalHost(hostToBind)) {
+ if (CollectionUtils.isNotEmpty(registryURLs)) {
+ for (URL registryURL : registryURLs) {
+ if (MULTICAST.equalsIgnoreCase(registryURL.getParameter("registry"))) {
+ // skip multicast registry since we cannot connect to it via Socket
+ continue;
+ }
+ try (Socket socket = new Socket()) {
+ SocketAddress addr = new InetSocketAddress(registryURL.getHost(), registryURL.getPort());
+ socket.connect(addr, 1000);
+ hostToBind = socket.getLocalAddress().getHostAddress();
+ break;
+ } catch (Exception e) {
+ logger.warn(e.getMessage(), e);
+ }
+ }
+ }
+ if (isInvalidLocalHost(hostToBind)) {
+ hostToBind = getLocalHost();
+ }
+ }
+ }
+ }
+
+ map.put(Constants.BIND_IP_KEY, hostToBind);
+
+ // registry ip is not used for bind ip by default
+ String hostToRegistry = getValueFromConfig(protocolConfig, DUBBO_IP_TO_REGISTRY);
+ if (hostToRegistry != null && hostToRegistry.length() > 0 && isInvalidLocalHost(hostToRegistry)) {
+ throw new IllegalArgumentException("Specified invalid registry ip from property:" + DUBBO_IP_TO_REGISTRY + ", value:" + hostToRegistry);
+ } else if (StringUtils.isEmpty(hostToRegistry)) {
+ // bind ip is used as registry ip by default
+ hostToRegistry = hostToBind;
+ }
+
+ map.put(ANYHOST_KEY, String.valueOf(anyhost));
+
+ return hostToRegistry;
+ }
+
+ /**
+ * Register port and bind port for the provider, can be configured separately
+ * Configuration priority: environment variable -> java system properties -> port property in protocol config file
+ * -> protocol default port
+ *
+ * @param protocolConfig
+ * @param name
+ * @return
+ */
+ private Integer findConfigedPorts(ProtocolConfig protocolConfig, String name, Map<String, String> map) {
+ Integer portToBind = null;
+
+ // parse bind port from environment
+ String port = getValueFromConfig(protocolConfig, DUBBO_PORT_TO_BIND);
+ portToBind = parsePort(port);
+
+ // if there's no bind port found from environment, keep looking up.
+ if (portToBind == null) {
+ portToBind = protocolConfig.getPort();
+ if (provider != null && (portToBind == null || portToBind == 0)) {
+ portToBind = provider.getPort();
+ }
+ final int defaultPort = ExtensionLoader.getExtensionLoader(Protocol.class).getExtension(name).getDefaultPort();
+ if (portToBind == null || portToBind == 0) {
+ portToBind = defaultPort;
+ }
- if (portToBind == null || portToBind <= 0) {
++ if (portToBind <= 0) {
+ portToBind = getRandomPort(name);
+ if (portToBind == null || portToBind < 0) {
+ portToBind = getAvailablePort(defaultPort);
+ putRandomPort(name, portToBind);
+ }
+ }
+ }
+
+ // save bind port, used as url's key later
+ map.put(Constants.BIND_PORT_KEY, String.valueOf(portToBind));
+
+ // registry port, not used as bind port by default
+ String portToRegistryStr = getValueFromConfig(protocolConfig, DUBBO_PORT_TO_REGISTRY);
+ Integer portToRegistry = parsePort(portToRegistryStr);
+ if (portToRegistry == null) {
+ portToRegistry = portToBind;
+ }
+
+ return portToRegistry;
+ }
+
+ private Integer parsePort(String configPort) {
+ Integer port = null;
+ if (configPort != null && configPort.length() > 0) {
+ try {
+ Integer intPort = Integer.parseInt(configPort);
+ if (isInvalidPort(intPort)) {
+ throw new IllegalArgumentException("Specified invalid port from env value:" + configPort);
+ }
+ port = intPort;
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Specified invalid port from env value:" + configPort);
+ }
+ }
+ return port;
+ }
+
+ private String getValueFromConfig(ProtocolConfig protocolConfig, String key) {
+ String protocolPrefix = protocolConfig.getName().toUpperCase() + "_";
+ String port = ConfigUtils.getSystemProperty(protocolPrefix + key);
+ if (StringUtils.isEmpty(port)) {
+ port = ConfigUtils.getSystemProperty(key);
+ }
+ return port;
+ }
+
+ private void completeCompoundConfigs() {
+ if (provider != null) {
+ if (application == null) {
+ setApplication(provider.getApplication());
+ }
+ if (module == null) {
+ setModule(provider.getModule());
+ }
+ if (registries == null) {
+ setRegistries(provider.getRegistries());
+ }
+ if (monitor == null) {
+ setMonitor(provider.getMonitor());
+ }
+ if (protocols == null) {
+ setProtocols(provider.getProtocols());
+ }
+ if (configCenter == null) {
+ setConfigCenter(provider.getConfigCenter());
+ }
+ }
+ if (module != null) {
+ if (registries == null) {
+ setRegistries(module.getRegistries());
+ }
+ if (monitor == null) {
+ setMonitor(module.getMonitor());
+ }
+ }
+ if (application != null) {
+ if (registries == null) {
+ setRegistries(application.getRegistries());
+ }
+ if (monitor == null) {
+ setMonitor(application.getMonitor());
+ }
+ }
+ }
+
+ private void checkDefault() {
+ createProviderIfAbsent();
+ }
+
+ private void createProviderIfAbsent() {
+ if (provider != null) {
+ return;
+ }
+ setProvider(
+ ConfigManager.getInstance()
+ .getDefaultProvider()
+ .orElseGet(() -> {
+ ProviderConfig providerConfig = new ProviderConfig();
+ providerConfig.refresh();
+ return providerConfig;
+ })
+ );
+ }
+
+ private void checkProtocol() {
+ if (CollectionUtils.isEmpty(protocols) && provider != null) {
+ setProtocols(provider.getProtocols());
+ }
+ convertProtocolIdsToProtocols();
+ }
+
+ private void convertProtocolIdsToProtocols() {
+ if (StringUtils.isEmpty(protocolIds)) {
+ if (CollectionUtils.isEmpty(protocols)) {
+ setProtocols(
+ ConfigManager.getInstance().getDefaultProtocols()
+ .filter(CollectionUtils::isNotEmpty)
+ .orElseGet(() -> {
+ ProtocolConfig protocolConfig = new ProtocolConfig();
+ protocolConfig.refresh();
+ return new ArrayList<>(Arrays.asList(protocolConfig));
+ })
+ );
+ }
+ } else {
+ String[] arr = COMMA_SPLIT_PATTERN.split(protocolIds);
+ List<ProtocolConfig> tmpProtocols = CollectionUtils.isNotEmpty(protocols) ? protocols : new ArrayList<>();
+ Arrays.stream(arr).forEach(id -> {
+ if (tmpProtocols.stream().noneMatch(prot -> prot.getId().equals(id))) {
+ ConfigManager.getInstance().getProtocol(id).ifPresent(tmpProtocols::add);
+ }
+ });
+ if (tmpProtocols.size() > arr.length) {
+ throw new IllegalStateException("Too much protocols found, the protocols comply to this service are :" + protocolIds + " but got " + protocols
+ .size() + " registries!");
+ }
+ setProtocols(tmpProtocols);
+ }
+ }
+
+ public Class<?> getInterfaceClass() {
+ if (interfaceClass != null) {
+ return interfaceClass;
+ }
+ if (ref instanceof GenericService) {
+ return GenericService.class;
+ }
+ try {
+ if (interfaceName != null && interfaceName.length() > 0) {
+ this.interfaceClass = Class.forName(interfaceName, true, Thread.currentThread()
+ .getContextClassLoader());
+ }
+ } catch (ClassNotFoundException t) {
+ throw new IllegalStateException(t.getMessage(), t);
+ }
+ return interfaceClass;
+ }
+
+ /**
+ * @param interfaceClass
+ * @see #setInterface(Class)
+ * @deprecated
+ */
+ public void setInterfaceClass(Class<?> interfaceClass) {
+ setInterface(interfaceClass);
+ }
+
+ public String getInterface() {
+ return interfaceName;
+ }
+
+ public void setInterface(Class<?> interfaceClass) {
+ if (interfaceClass != null && !interfaceClass.isInterface()) {
+ throw new IllegalStateException("The interface class " + interfaceClass + " is not a interface!");
+ }
+ this.interfaceClass = interfaceClass;
+ setInterface(interfaceClass == null ? null : interfaceClass.getName());
+ }
+
+ public void setInterface(String interfaceName) {
+ this.interfaceName = interfaceName;
+ if (StringUtils.isEmpty(id)) {
+ id = interfaceName;
+ }
+ }
+
+ public T getRef() {
+ return ref;
+ }
+
+ public void setRef(T ref) {
+ this.ref = ref;
+ }
+
+ @Parameter(excluded = true)
+ public String getPath() {
+ return path;
+ }
+
+ public void setPath(String path) {
+ checkPathName(PATH_KEY, path);
+ this.path = path;
+ }
+
+ public List<MethodConfig> getMethods() {
+ return methods;
+ }
+
+ // ======== Deprecated ========
+
+ @SuppressWarnings("unchecked")
+ public void setMethods(List<? extends MethodConfig> methods) {
+ this.methods = (List<MethodConfig>) methods;
+ }
+
+ public ProviderConfig getProvider() {
+ return provider;
+ }
+
+ public void setProvider(ProviderConfig provider) {
+ ConfigManager.getInstance().addProvider(provider);
+ this.provider = provider;
+ }
+
+ @Parameter(excluded = true)
+ public String getProviderIds() {
+ return providerIds;
+ }
+
+ public void setProviderIds(String providerIds) {
+ this.providerIds = providerIds;
+ }
+
+ public String getGeneric() {
+ return generic;
+ }
+
+ public void setGeneric(String generic) {
+ if (StringUtils.isEmpty(generic)) {
+ return;
+ }
+ if (ProtocolUtils.isGeneric(generic)) {
+ this.generic = generic;
+ } else {
+ throw new IllegalArgumentException("Unsupported generic type " + generic);
+ }
+ }
+
+ @Override
+ public void setMock(Boolean mock) {
+ throw new IllegalArgumentException("mock doesn't support on provider side");
+ }
+
+ @Override
+ public void setMock(String mock) {
+ throw new IllegalArgumentException("mock doesn't support on provider side");
+ }
+
+ public List<URL> getExportedUrls() {
+ return urls;
+ }
+
+ /**
+ * @deprecated Replace to getProtocols()
+ */
+ @Deprecated
+ public List<ProviderConfig> getProviders() {
+ return convertProtocolToProvider(protocols);
+ }
+
+ /**
+ * @deprecated Replace to setProtocols()
+ */
+ @Deprecated
+ public void setProviders(List<ProviderConfig> providers) {
+ this.protocols = convertProviderToProtocol(providers);
+ }
+
+ @Override
+ @Parameter(excluded = true)
+ public String getPrefix() {
+ return DUBBO + ".service." + interfaceName;
+ }
+
+ /**
+ * Dispatch an {@link Event event}
+ *
+ * @param event an {@link Event event}
+ * @since 2.7.4
+ */
+ protected void dispatch(Event event) {
+ eventDispatcher.dispatch(event);
+ }
+}
diff --cc dubbo-config/dubbo-config-api/src/test/java/org/apache/dubbo/config/ReferenceConfigTest.java
index f9afb35,b77a33c..cb4d7fd
--- 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
@@@ -169,18 -133,18 +169,18 @@@ public class ReferenceConfigTest
public void testConstructWithReferenceAnnotation() throws NoSuchFieldException {
Reference reference = getClass().getDeclaredField("innerTest").getAnnotation(Reference.class);
ReferenceConfig referenceConfig = new ReferenceConfig(reference);
- Assertions.assertTrue(referenceConfig.getMethods().size() == 1);
- assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getName(), "sayHello");
- Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getTimeout() == 1300);
- Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getRetries() == 4);
- assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getLoadbalance(), "random");
- Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getActives() == 3);
- Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).getExecutes() == 5);
+ Assertions.assertEquals(1, referenceConfig.getMethods().size());
+ Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getName(), "sayHello");
+ Assertions.assertEquals(1300, (int)((MethodConfig)referenceConfig.getMethods().get(0)).getTimeout());
+ Assertions.assertEquals(4, (int)((MethodConfig)referenceConfig.getMethods().get(0)).getRetries());
+ Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getLoadbalance(), "random");
+ Assertions.assertEquals(3, (int)((MethodConfig)referenceConfig.getMethods().get(0)).getActives());
+ Assertions.assertEquals(5, (int)((MethodConfig)referenceConfig.getMethods().get(0)).getExecutes());
Assertions.assertTrue(((MethodConfig) referenceConfig.getMethods().get(0)).isAsync());
- Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOninvoke(), "i");
- Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnreturn(), "r");
- Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnthrow(), "t");
- Assertions.assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getCache(), "c");
+ assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOninvoke(), "i");
+ assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnreturn(), "r");
+ assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getOnthrow(), "t");
+ assertEquals(((MethodConfig) referenceConfig.getMethods().get(0)).getCache(), "c");
}
diff --cc dubbo-configcenter/dubbo-configcenter-consul/src/main/java/org/apache/dubbo/configcenter/consul/ConsulDynamicConfiguration.java
index 0303984,f57f639..26f9cac
--- 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
@@@ -39,9 -39,9 +39,11 @@@ import java.util.concurrent.ConcurrentM
import java.util.concurrent.ExecutorService;
import static java.util.concurrent.Executors.newCachedThreadPool;
+import static org.apache.dubbo.common.config.configcenter.ConfigChangeType.ADDED;
+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.configcenter.ConfigChangeType.ADDED;
+ import static org.apache.dubbo.configcenter.Constants.CONFIG_NAMESPACE_KEY;
/**
* config center implementation for consul
diff --cc dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
index 8b4f739,6cd1058..bc4fd68
--- a/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
+++ b/dubbo-configcenter/dubbo-configcenter-etcd/src/test/java/org/apache/dubbo/configcenter/support/etcd/EtcdDynamicConfigurationTest.java
@@@ -18,8 -18,9 +18,9 @@@
package org.apache.dubbo.configcenter.support.etcd;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
++import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
import io.etcd.jetcd.ByteSequence;
import io.etcd.jetcd.Client;
diff --cc dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
index e48699c,78c1211..df3f5e2
--- a/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
+++ b/dubbo-configcenter/dubbo-configcenter-nacos/src/test/java/org/apache/dubbo/configcenter/support/nacos/NacosDynamicConfigurationTest.java
@@@ -18,9 -18,13 +18,13 @@@
package org.apache.dubbo.configcenter.support.nacos;
import org.apache.dubbo.common.URL;
-import org.apache.dubbo.configcenter.ConfigChangeEvent;
-import org.apache.dubbo.configcenter.ConfigurationListener;
-import org.apache.dubbo.configcenter.DynamicConfiguration;
+import org.apache.dubbo.common.config.configcenter.ConfigChangeEvent;
+import org.apache.dubbo.common.config.configcenter.ConfigurationListener;
++import org.apache.dubbo.common.config.configcenter.DynamicConfiguration;
+ import com.alibaba.nacos.api.NacosFactory;
+ import com.alibaba.nacos.api.config.ConfigService;
+ import com.alibaba.nacos.api.exception.NacosException;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
diff --cc dubbo-configcenter/dubbo-configcenter-zookeeper/src/main/java/org/apache/dubbo/configcenter/support/zookeeper/ZookeeperDynamicConfiguration.java
index 8ee4581,096b71c..2dd32fc
--- 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
@@@ -99,70 -97,20 +103,68 @@@ public class ZookeeperDynamicConfigurat
}
@Override
- public String getConfig(String key, String group, long timeout) throws IllegalStateException {
- String path = buildPath(key, group);
- return (String) getInternalProperty(path);
+ public String getRule(String key, String group, long timeout) throws IllegalStateException {
+ return (String) getInternalProperty(getPathKey(group, key));
}
- /**
- * For zookeeper, {@link #getConfig(String, String, long)} and {@link #getConfigs(String, String, long)} have the same meaning.
- *
- * @param key
- * @param group
- * @param timeout
- * @return
- * @throws IllegalStateException
- */
@Override
- public String getConfigs(String key, String group, long timeout) throws IllegalStateException {
- return getConfig(key, group, timeout);
+ public String getProperties(String key, String group, long timeout) throws IllegalStateException {
+ // use global group 'dubbo' if no group specified
+ if (StringUtils.isEmpty(group)) {
+ group = DEFAULT_GROUP;
+ }
+ return (String) getInternalProperty(getPathKey(group, key));
}
+ @Override
+ public boolean publishConfig(String key, String group, String content) {
+ String path = buildPath(key, group);
+ zkClient.create(path, content, true);
+ return true;
+ }
+
+ @Override
+ public SortedSet<String> getConfigKeys(String group) {
+ String path = buildPath(group);
+ List<String> nodes = zkClient.getChildren(path);
+ return isEmpty(nodes) ? emptySortedSet() : unmodifiableSortedSet(new TreeSet<>(nodes));
+ }
+
+ private String getPathKey(String group, String key) {
+ return rootPath + PATH_SEPARATOR + group + PATH_SEPARATOR + key;
+ }
++
+ /**
+ * Build the config node path by the specified <code>key</code> and <code>group</code>
+ *
+ * @param key the key to represent a configuration
+ * @param group the group where the key belongs to
+ * @return
+ */
+ protected String buildPath(String key, String group) {
+ String path = null;
+ /**
+ * when group is not null, we are getting startup configs from Config Center, for example:
+ * group=dubbo, key=dubbo.properties
+ */
+ if (StringUtils.isNotEmpty(group)) {
+ path = group + "/" + key;
+ }
+ /**
+ * when group is null, we are fetching governance rules, for example:
+ * 1. key=org.apache.dubbo.DemoService.configurators
+ * 2. key = org.apache.dubbo.DemoService.condition-router
+ */
+ else {
+ int i = key.lastIndexOf(".");
+ path = key.substring(0, i) + "/" + key.substring(i + 1);
+ }
+ return buildPath(path);
+ }
+
+ protected String buildPath(String relativePath) {
+ String path = rootPath + "/" + relativePath;
+ return path;
+ }
+
}
diff --cc dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
index 3635621,01be977..932af2b
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/definition/model/MethodDefinition.java
@@@ -16,10 -16,7 +16,9 @@@
*/
package org.apache.dubbo.metadata.definition.model;
+import java.io.Serializable;
+import java.util.ArrayList;
import java.util.Arrays;
- import java.util.List;
import java.util.Objects;
/**
diff --cc dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
index 7ffa2a9,6c79a67..1e70a1d
--- a/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/main/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifier.java
@@@ -68,11 -67,7 +68,11 @@@ public class MetadataIdentifier
}
public String getIdentifierKey() {
- return serviceInterface + SEPARATOR + (version == null ? "" : version) + SEPARATOR + (group == null ? "" : group) + SEPARATOR + side + SEPARATOR + application;
+ return serviceInterface
- + (version == null ? "" : (SEPARATOR + version))
- + (group == null ? "" : (SEPARATOR + version))
- + (side == null ? "" : (SEPARATOR + side))
- + (getApplication() == null ? "" : (SEPARATOR + getApplication()));
++ + SEPARATOR + (version == null ? "" : version)
++ + SEPARATOR + (group == null ? "" : group)
++ + SEPARATOR + (side == null ? "" : side)
++ + SEPARATOR + application;
}
private String getFilePathKey() {
diff --cc dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
index c85ee48,3a54e72..c104c76
--- a/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
+++ b/dubbo-metadata/dubbo-metadata-api/src/test/java/org/apache/dubbo/metadata/report/identifier/MetadataIdentifierTest.java
@@@ -16,8 -16,7 +16,9 @@@
*/
package org.apache.dubbo.metadata.identifier;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier.KeyTypeEnum;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
++import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier.KeyTypeEnum;
+
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
diff --cc dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
index 846bc74,b12e4f0..1f3fc1a
--- a/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
+++ b/dubbo-metadata/dubbo-metadata-report-nacos/src/main/java/org/apache/dubbo/metadata/store/nacos/NacosMetadataReport.java
@@@ -21,24 -24,20 +21,25 @@@ 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.StringUtils;
-import org.apache.dubbo.metadata.identifier.MetadataIdentifier;
-import org.apache.dubbo.metadata.support.AbstractMetadataReport;
+import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
+import org.apache.dubbo.metadata.report.support.AbstractMetadataReport;
import org.apache.dubbo.rpc.RpcException;
+import com.alibaba.nacos.api.NacosFactory;
+import com.alibaba.nacos.api.config.ConfigService;
+import com.alibaba.nacos.api.exception.NacosException;
+
+import java.util.List;
import java.util.Properties;
-import static com.alibaba.nacos.api.PropertyKeyConst.SERVER_ADDR;
-import static com.alibaba.nacos.api.PropertyKeyConst.SECRET_KEY;
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.ENDPOINT;
import static com.alibaba.nacos.api.PropertyKeyConst.NAMESPACE;
-import static com.alibaba.nacos.api.PropertyKeyConst.CLUSTER_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 org.apache.dubbo.common.constants.CommonConstants.GROUP_KEY;
import static org.apache.dubbo.common.constants.RemotingConstants.BACKUP_KEY;
/**
@@@ -113,34 -121,9 +123,34 @@@ public class NacosMetadataReport extend
this.storeMetadata(consumerMetadataIdentifier, value);
}
+ @Override
+ protected void doSaveMetadata(URL url) {
+ throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+ }
+
+ @Override
+ protected void doRemoveMetadata(URL url) {
+ throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+ }
+
+ @Override
+ protected List<String> doGetExportedURLs() {
+ throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+ }
+
+ @Override
+ protected List<String> doGetSubscribedURLs() {
+ throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+ }
+
+ @Override
+ public String getServiceDefinition(MetadataIdentifier consumerMetadataIdentifier) {
+ throw new UnsupportedOperationException("This extension does not support working as a remote metadata center.");
+ }
+
private void storeMetadata(MetadataIdentifier identifier, String value) {
try {
- boolean publishResult = configService.publishConfig(identifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY), identifier.getGroup(), value);
+ boolean publishResult = configService.publishConfig(identifier.getUniqueKey(MetadataIdentifier.KeyTypeEnum.UNIQUE_KEY), group, value);
if (!publishResult) {
throw new RuntimeException("publish nacos metadata failed");
}
diff --cc dubbo-metadata/pom.xml
index 2c8bb6b,cbc11f5..9f09ca5
--- a/dubbo-metadata/pom.xml
+++ b/dubbo-metadata/pom.xml
@@@ -25,12 -22,14 +25,14 @@@
</parent>
<modelVersion>4.0.0</modelVersion>
- <artifactId>dubbo-metadata-report</artifactId>
+ <artifactId>dubbo-metadata</artifactId>
<packaging>pom</packaging>
<modules>
- <module>dubbo-metadata-report-api</module>
+ <module>dubbo-metadata-api</module>
<module>dubbo-metadata-report-zookeeper</module>
<module>dubbo-metadata-report-redis</module>
+ <module>dubbo-metadata-definition</module>
+ <module>dubbo-metadata-definition-protobuf</module>
<module>dubbo-metadata-report-consul</module>
<module>dubbo-metadata-report-etcd</module>
<module>dubbo-metadata-report-nacos</module>